Changeset 9012

Show
Ignore:
Timestamp:
08/18/11 16:00:15 (21 months ago)
Author:
jdenton
Message:

Made many changes suggested by C Programming Guidlines in the OrangeFS Wiki

Location:
branches/Orange-Branch/src/client/usrint
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • branches/Orange-Branch/src/client/usrint/ucache.c

    r9001 r9012  
    11/*  
    2  * (C) 2011 Clemson University and The University of Chicago  
     2 * (C) 2011 Clemson University 
    33 * 
    44 * See COPYING in top-level directory. 
    55 */ 
    66 
    7 /*  Experimental cache for user data 
    8  *      Currently under development. 
    9  */ 
    10  
    11 /*   
    12  *   Note: When unsigned ints are set to NIL, their values are based on type: 
     7/* Experimental cache for user data 
     8 * Currently under development. 
     9 * 
     10 * Note: When unsigned ints are set to NIL, their values are based on type: 
    1311 *   ex: 16      0xFFFF   
    1412 *       32      0XFFFFFFFF 
    1513 *       64      0XFFFFFFFFFFFFFFFF  
    16  *   ALL EQUAL THE SIGNED REPRESENTATION OF -1, CALLED NIL.   
     14 *   ALL EQUAL THE SIGNED REPRESENTATION OF -1, CALLED NIL IN ucache.h   
    1715 */ 
    1816 
    1917#include "ucache.h" 
    2018 
     19/* Global Variables */ 
    2120static union user_cache_u *ucache; 
    2221static int ucache_blk_cnt; 
    23 static ucache_lock_t *ucache_lock;  /*  For maintaining concurrency */ 
    24 static FILE *out;   /*  For Logging Purposes    */ 
     22static ucache_lock_t *ucache_lock;  /* For maintaining concurrency */ 
     23static FILE *out;                   /* For Logging Purposes */ 
     24 
     25/* Internal Only Function Declarations */ 
     26 
     27/* Global Cache Lock */ 
     28static int lock_init(ucache_lock_t * lock); 
     29static int lock_lock(ucache_lock_t * lock); 
     30static int lock_unlock(ucache_lock_t * lock); 
     31static int lock_destroy(ucache_lock_t * lock); 
     32 
     33/* Initialization */ 
     34static void add_free_mtbls(int blk); 
     35static void init_memory_table(int blk, int ent); 
     36 
     37/* Gets */ 
     38static int get_next_free_mtbl(uint32_t *free_mtbl_blk, uint16_t *free_mtbl_ent); 
     39static int get_free_fent(void); 
     40static int get_free_ment(struct mem_table_s *mtbl); 
     41static uint16_t get_free_blk(void); 
     42 
     43/* Puts */ 
     44static void put_free_mtbl(struct mem_table_s *mtbl, struct file_ent_s *file); 
     45static void put_free_fent(int fent); 
     46static void put_free_ment(struct mem_table_s *mtbl, int ent); 
     47static void put_free_blk(int blk); 
     48 
     49/* File Entry Chain Iterator */ 
     50static int file_done(int index); 
     51static int file_next(struct file_table_s *ftbl, int index); 
     52 
     53/* Memory Entry Chain Iterator */ 
     54static int ment_done(int index); 
     55static int ment_next(struct mem_table_s *mtbl, int index); 
     56 
     57/* Dirty List Iterator */ 
     58static int dirty_done(uint16_t index); 
     59static int dirty_next(struct mem_table_s *mtbl, uint16_t index); 
     60 
     61/* File and Memory Insertion */ 
     62static struct mem_table_s *insert_file(uint32_t fs_id, uint64_t handle); 
     63static void *insert_mem(struct mem_table_s *mtbl, uint64_t offset); 
     64static void *set_item(struct mem_table_s *mtbl,uint64_t offset, uint16_t index); 
     65 
     66/* File and Memory Lookup */ 
     67static struct mem_table_s *lookup_file( 
     68    uint32_t fs_id,  
     69    uint64_t handle, 
     70    uint32_t *file_mtbl_blk,    /* Can be NULL if not desired TODO: remove these later? */ 
     71    uint16_t *file_mtbl_ent,   
     72    uint16_t *file_ent_index, 
     73    uint16_t *file_ent_prev_index 
     74); 
     75static void *lookup_mem(struct mem_table_s *mtbl,  
     76                    uint64_t offset,  
     77                    uint32_t *item_index, 
     78                    uint16_t *mem_ent_index, 
     79                    uint16_t *mem_ent_prev_index 
     80); 
     81 
     82/* File and Memory Entry Removal */ 
     83static int remove_file(uint32_t fs_id, uint64_t handle); 
     84static void remove_all_memory_entries(struct mem_table_s *mtbl); 
     85static int remove_mem(struct mem_table_s *mtbl, uint64_t offset); 
     86 
     87/* Eviction Utilities */ 
     88static int evict_file(unsigned int index); 
     89static int locate_max_mtbl(struct mem_table_s **mtbl); 
     90static void update_lru(struct mem_table_s *mtbl, uint16_t index); 
     91static int evict_LRU(struct mem_table_s *mtbl); 
     92 
     93/* List Printing Functions */ 
     94/*  
     95 * static void print_lru(struct mem_table_s *mtbl); 
     96 * static void print_dirty(struct mem_table_s *mtbl); 
     97 */ 
    2598 
    2699/*  Externally Visible API 
     
    29102 */ 
    30103 
    31 /*  Initializes the cache.  
     104/**  Initializes the cache.  
    32105 *  Mainly, it aquires a shared memory segment used to cache data.  
    33106 *  
     
    37110 *  Currently using posix semaphores 
    38111 */ 
    39 extern void ucache_initialize(void) 
    40 { 
    41     /*  Aquire shared memory for ucache_lock    */ 
     112void ucache_initialize(void) 
     113{ 
     114    /* Aquire shared memory for ucache_lock */ 
    42115    ucache_lock = shmat(shmget(ftok(GET_KEY_FILE, 'a'),  
    43116        sizeof(ucache_lock_t), CACHE_FLAGS), NULL, AT_FLAGS); 
    44     ucache_lock_init(ucache_lock); 
    45     ucache_lock_lock(ucache_lock); 
    46     /*  Aquire shared memory for lock for ucache    */ 
     117    lock_init(ucache_lock); 
     118    lock_lock(ucache_lock); 
     119    #if LOCK_TYPE==0 
     120    int lockVal; 
     121    ucache_lock_getvalue(ucache_lock, &lockVal); 
     122    printf("lock value = %d\n", lockVal); 
     123    #endif 
     124    /* Aquire shared memory for lock for ucache */ 
    47125    int key, id, i; 
    48126    char *key_file_path; 
    49127    /*  Direct output   */ 
    50128    if(!out)out = stdout; 
    51     /*  Note: had to set: kernel.shmmax amd kernel.shmall  */ 
     129    /* Note: had to set: kernel.shmmax amd kernel.shmall */ 
    52130    /* set up shared memory region */ 
    53131    key_file_path = GET_KEY_FILE; 
     
    76154    for (i = 0; i < FILE_TABLE_HASH_MAX; i++) 
    77155    { 
     156        ucache->ftbl.file[i].tag_handle = NIL; 
     157        ucache->ftbl.file[i].tag_id = NIL; 
    78158        ucache->ftbl.file[i].mtbl_blk = NIL; 
    79159        ucache->ftbl.file[i].mtbl_ent = NIL; 
     
    89169    } 
    90170    ucache->ftbl.file[FILE_TABLE_ENTRY_COUNT - 1].next = NIL; 
    91     ucache_lock_unlock(ucache_lock); 
    92 } 
    93  
    94 extern int ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 
    95 { 
    96     ucache_lock_lock(ucache_lock); 
     171    lock_unlock(ucache_lock); 
     172} 
     173 
     174int ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 
     175{ 
     176    lock_lock(ucache_lock); 
    97177    struct mem_table_s *mtbl= lookup_file( 
    98178        (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); 
     
    101181        insert_file((uint32_t)*fs_id, (uint64_t)*handle); 
    102182    } 
    103     ucache_lock_unlock(ucache_lock); 
     183    lock_unlock(ucache_lock); 
    104184    return 1; 
    105185} 
    106186 
    107 /*  Returns ptr to block in cache based on file and offset */ 
    108 extern void *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 
    109 { 
    110     ucache_lock_lock(ucache_lock); 
     187/** Returns ptr to block in cache based on file and offset */ 
     188void *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 
     189{ 
     190    lock_lock(ucache_lock); 
    111191    struct mem_table_s *mtbl= lookup_file( 
    112192        (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); 
    113193    if((int)mtbl!=NIL) 
    114194    { 
    115         char *retVal = (char *)lookup_mem(mtbl, (uint64_t)offset, NULL, NULL, NULL); 
    116         ucache_lock_unlock(ucache_lock); 
     195        char *retVal = (char *)lookup_mem(mtbl, (uint64_t)offset, NULL, NULL,  
     196                                                                        NULL); 
     197        lock_unlock(ucache_lock); 
    117198        return((void *)retVal);  
    118199    } 
    119     ucache_lock_unlock(ucache_lock); 
     200    lock_unlock(ucache_lock); 
    120201    return (void *)NIL; 
    121202} 
    122203 
    123 /*  Inserts block of data into cache    */ 
    124 extern void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 
    125 { 
    126     ucache_lock_lock(ucache_lock); 
     204/** Prepares the data structures for block storage.  
     205 * On success, returns a pointer to where the block of data should be written.  
     206 * On failure, returns NIL. 
     207 */ 
     208void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 
     209{ 
     210    lock_lock(ucache_lock); 
    127211    struct mem_table_s *mtbl= lookup_file( 
    128212        (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); 
    129213    if((int)mtbl==NIL) 
    130214    { 
    131         ucache_lock_unlock(ucache_lock); 
     215        lock_unlock(ucache_lock); 
    132216        return (void *)NIL; 
    133217    } 
    134218    else 
    135219    { 
    136         remove_mem(mtbl, (uint64_t)offset); 
     220        if(remove_mem(mtbl, (uint64_t)offset)==NIL){ 
     221            lock_unlock(ucache_lock); 
     222            return (void *)NIL; 
     223        } 
    137224        char * retVal= insert_mem(mtbl, (uint64_t)offset); 
    138         ucache_lock_unlock(ucache_lock); 
     225        lock_unlock(ucache_lock); 
    139226        return ((void *)retVal);  
    140227    } 
    141228} 
    142229 
    143 /*  Removes a cached block of data from mtbl    */ 
    144 extern int ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 
    145 { 
    146     ucache_lock_lock(ucache_lock); 
     230/**  Removes a cached block of data from mtbl */ 
     231int ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset) 
     232{ 
     233    lock_lock(ucache_lock); 
    147234    struct mem_table_s *mtbl= lookup_file( 
    148235        (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); 
     
    150237    { 
    151238        int retVal = remove_mem(mtbl, (uint64_t)offset); 
    152         ucache_lock_unlock(ucache_lock);  
     239        lock_unlock(ucache_lock);  
    153240        return retVal;  
    154241    }         
    155     ucache_lock_unlock(ucache_lock); 
     242    lock_unlock(ucache_lock); 
    156243    return NIL; 
    157244} 
    158245 
    159 /*  Flushes dirty blocks to the I/O Nodes  */ 
    160 extern int ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 
    161 { 
    162     ucache_lock_lock(ucache_lock); 
     246/** Flushes dirty blocks to the I/O Nodes */ 
     247int ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 
     248{ 
     249    lock_lock(ucache_lock); 
    163250    struct mem_table_s *mtbl= lookup_file( 
    164251        (uint32_t)(*fs_id), (uint64_t)(*handle), NULL, NULL, NULL, NULL); 
     
    174261            break; 
    175262        } 
    176         /*  //flush block to disk   */ 
     263        /* //flush block to disk   - 2 means write */ 
     264        //iocommon_readorwrite_nocache(2,); 
    177265    } 
    178266    mtbl->dirty_list = NIL; 
    179     ucache_lock_unlock(ucache_lock); 
     267    lock_unlock(ucache_lock); 
    180268    return 1; 
    181269} 
    182270 
    183 /*  Removes all memory entries in the mtbl corresponding to the file info  
    184  *  provided as parameters. It also removes the mtbl and the file entry from  
    185  *  the cache. 
    186  */ 
    187 extern int ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 
    188 { 
    189     ucache_lock_lock(ucache_lock); 
     271/** Removes all memory entries in the mtbl corresponding to the file info  
     272 * provided as parameters. It also removes the mtbl and the file entry from  
     273 * the cache. 
     274 */ 
     275int ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle) 
     276{ 
     277    lock_lock(ucache_lock); 
    190278    uint32_t file_mtbl_blk; 
    191279    uint16_t file_mtbl_ent; 
     
    201289    if((int)mtbl==NIL) 
    202290    { 
    203         ucache_lock_unlock(ucache_lock); 
     291        lock_unlock(ucache_lock); 
    204292        return NIL; 
    205293    } 
     
    208296    put_free_mtbl(mtbl, file); 
    209297    put_free_fent(file_ent_index); 
    210     ucache_lock_unlock(ucache_lock); 
     298    lock_unlock(ucache_lock); 
    211299    return 1; 
    212300} 
    213301 
    214 /*  Use the following function to decrement the reference count of a particular  
    215  *  mtbl. This function must be called when a user's code is done with the 
    216  *  pointer provided via any of the pointer returning external functions listed 
    217  *  above. 
    218  */ 
    219 extern int ucache_dec_ref_cnt(struct mem_table_s * mtbl) 
    220 { 
    221     ucache_lock_lock(ucache_lock); 
    222     /*  decrement ref_cnt of mtbl   */ 
    223     mtbl->ref_cnt--; 
    224     ucache_lock_unlock(ucache_lock);     
    225 } 
    226 /*****************************************  End of Externally Visible API    */ 
    227  
    228  
    229 /*  Beginning of internal only (static) functions 
    230  */ 
    231  
    232 /*  Internally Available Locking Mechanism - using POSIX semaphores    
    233  */ 
    234 static int ucache_lock_init(ucache_lock_t * lock) 
     302/** Decrements the reference count of a particular mtbl. */ 
     303void ucache_dec_ref_cnt(struct mem_table_s * mtbl) 
     304{ 
     305    lock_lock(ucache_lock); 
     306    /* decrement ref_cnt of mtbl */ 
     307    if(mtbl->ref_cnt!=0) 
     308        mtbl->ref_cnt--; 
     309    lock_unlock(ucache_lock);  
     310} 
     311 
     312/** Increments the reference count of a particular mtbl. */ 
     313void ucache_inc_ref_cnt(struct mem_table_s * mtbl) 
     314{ 
     315    lock_lock(ucache_lock); 
     316    /* increment ref_cnt of mtbl */ 
     317    mtbl->ref_cnt++; 
     318    lock_unlock(ucache_lock);  
     319} 
     320 
     321/** Dumps all cache related information. */ 
     322void ucache_info( 
     323    FILE *out, 
     324    union user_cache_u *ucache,  
     325    ucache_lock_t *ucache_lock) 
     326{ 
     327    fprintf(out, "\n#defines:\n"); 
     328    /* First, print many of the #define values */ 
     329    fprintf(out, "MEM_TABLE_ENTRY_COUNT = %d\n", MEM_TABLE_ENTRY_COUNT); 
     330    fprintf(out, "FILE_TABLE_ENTRY_COUNT = %d\n", FILE_TABLE_ENTRY_COUNT); 
     331    fprintf(out, "CACHE_BLOCK_SIZE_K = %d\n", CACHE_BLOCK_SIZE_K); 
     332    fprintf(out, "MEM_TABLE_HASH_MAX = %d\n", MEM_TABLE_HASH_MAX); 
     333    fprintf(out, "FILE_TABLE_HASH_MAX = %d\n", FILE_TABLE_HASH_MAX); 
     334    fprintf(out, "MTBL_PER_BLOCK  = %d\n", MTBL_PER_BLOCK ); 
     335    fprintf(out, "GET_KEY_FILE = %s\n", GET_KEY_FILE); 
     336    fprintf(out, "PROJ_ID = %d\n", PROJ_ID); 
     337    fprintf(out, "BLOCKS_IN_CACHE = %d\n", BLOCKS_IN_CACHE); 
     338    fprintf(out, "CACHE_SIZE = %d(B)\t%d(MB)\n", CACHE_SIZE,  
     339                                    (CACHE_SIZE/(1024*1024))); 
     340    fprintf(out, "AT_FLAGS = %d\n", AT_FLAGS); 
     341    fprintf(out, "SVSHM_MODE = %d\n", SVSHM_MODE); 
     342    fprintf(out, "CACHE_FLAGS = %d\n", CACHE_FLAGS); 
     343    fprintf(out, "NIL = %d\n\n", NIL);     
     344 
     345    /* Lock's Shared Memory Info */ 
     346    fprintf(out, "address of ucache_lock ptr:\t0X%X\n",  
     347                            (unsigned int) &ucache_lock); 
     348    fprintf(out, "ucache_lock ptr:\t\t0X%X\n", (unsigned int) ucache_lock); 
     349    /* Lock's Value */ 
     350    int lockValue = 0; 
     351    #if LOCK_TYPE == 0 
     352    ucache_lock_getvalue(ucache_lock, &lockValue); 
     353    #endif 
     354    fprintf(out, "ucache_lock value = %d\n", lockValue); 
     355    /* ucache Shared Memory Info */ 
     356    fprintf(out, "address of ucache ptr:\t0X%X\n", (unsigned int)&ucache); 
     357    fprintf(out, "ucache ptr:\t\t0X%X\n", (unsigned int)ucache); 
     358 
     359    struct file_table_s *ftbl = &(ucache->ftbl); 
     360 
     361    /* FTBL Info */ 
     362    fprintf(out, "ftbl ptr:\t\t0X%X\n", (unsigned int)&(ucache->ftbl)); 
     363    fprintf(out, "free_blk = %d\n", (int32_t)ftbl->free_blk); 
     364    fprintf(out, "free_mtbl_blk = %d\n", (int32_t)ftbl->free_mtbl_blk); 
     365    fprintf(out, "free_mtbl_ent = %d\n", (int16_t)ftbl->free_mtbl_ent); 
     366    fprintf(out, "free_list = %d\n", (int16_t)ftbl->free_list); 
     367 
     368    /* Other Free Blocks */ 
     369    fprintf(out, "\nIterating Over Free Blocks:\n\n"); 
     370    unsigned int i; 
     371    for(i = ftbl->free_blk; (int16_t)i != NIL; i = ucache->b[i].mtbl[0]. 
     372                                                              free_list) 
     373    { 
     374        fprintf(out, "Free Block:\tCurrent: %d\tNext: %d\n", i,  
     375                               ucache->b[i].mtbl[0].free_list); 
     376    } 
     377    fprintf(out, "End of Free Blocks List\n"); 
     378 
     379    /* Iterate Over Free Mtbls */ 
     380    fprintf(out, "\nIterating Over Free Mtbls:\n"); 
     381    uint32_t current_blk = ftbl->free_mtbl_blk; 
     382    uint16_t current_ent = ftbl->free_mtbl_ent; 
     383    while((int16_t)current_blk != NIL) 
     384    { 
     385        fprintf(out, "free mtbl: block = %d\tentry = %d\n",  
     386                (int16_t)current_blk, (int16_t)current_ent); 
     387        current_blk = (uint16_t)ucache->b[current_blk].mtbl[current_ent]. 
     388                                                            free_list_blk; 
     389        current_ent = (uint16_t)ucache->b[current_blk].mtbl[current_ent]. 
     390                                                                free_list; 
     391    } 
     392    fprintf(out, "End of Free Mtbl List\n\n"); 
     393     
     394    /* Iterating Over Free File Entries */ 
     395    fprintf(out, "Iterating Over Free File Entries:\n"); 
     396    uint16_t current_fent;  
     397    for(current_fent = ftbl->free_list; (int16_t)current_fent!=NIL;  
     398                      current_fent = ftbl->file[current_fent].next) 
     399    { 
     400        fprintf(out, "free file entry: index = %d\n", (int16_t)current_fent); 
     401    } 
     402    fprintf(out, "End of Free File Entry List\n\n"); 
     403 
     404    fprintf(out, "Iterating Over File Entries in Hash Table:\n\n"); 
     405    /* iterate over file table entries */ 
     406    for(i = 0; i < FILE_TABLE_HASH_MAX; i++) 
     407    { 
     408        if(((int64_t)ftbl->file[i].tag_handle != NIL) &&  
     409               ((int64_t)ftbl->file[i].tag_handle != 0)) 
     410        { 
     411            /* iterate accross file table chain */ 
     412            int j; 
     413            for(j = i; !file_done(j); j = file_next(ftbl, j)) 
     414            { 
     415                fprintf(out, "FILE ENTRY INDEX %d ********************\n", j); 
     416                struct file_ent_s * fent = &(ftbl->file[j]); 
     417                fprintf(out, "tag_handle = 0X%llX\n",  
     418                            (uint64_t)fent->tag_handle); 
     419                fprintf(out, "tag_id = 0X%X\n", (uint32_t)fent->tag_id); 
     420                fprintf(out, "mtbl_blk = %d\n", (int32_t)fent->mtbl_blk); 
     421                fprintf(out, "mtbl_ent = %d\n", (int16_t)fent->mtbl_ent); 
     422                fprintf(out, "next = %d\n", (int16_t)fent->next); 
     423 
     424                struct mem_table_s * mtbl = &(ucache->b[fent->mtbl_blk]. 
     425                                                    mtbl[fent->mtbl_ent]); 
     426                fprintf(out, "\tMTBL INFO ********************\n"); 
     427                fprintf(out, "\tnum_blocks = %d\n", (int16_t)mtbl->num_blocks); 
     428                fprintf(out, "\tfree_list = %d\n", (int16_t)mtbl->free_list);  
     429                fprintf(out, "\tfree_list_blk = %d\n",  
     430                        (int16_t)mtbl->free_list_blk); 
     431                fprintf(out, "\tlru_first = %d\n", (int16_t)mtbl->lru_first); 
     432                fprintf(out, "\tlru_last = %d\n", (int16_t)mtbl->lru_last); 
     433                fprintf(out, "\tdirty_list = %d\n", (int16_t)mtbl->dirty_list); 
     434                fprintf(out, "\tref_cnt = %d\n\n", (int16_t)mtbl->ref_cnt); 
     435 
     436                /* Iterate Over Memory Entries */ 
     437                int k; 
     438                for(k = 0; k < MEM_TABLE_HASH_MAX; k++) 
     439                { 
     440                    if(((int64_t)mtbl->mem[k].tag != NIL) &&  
     441                            ((int64_t)mtbl->mem[k].tag != 0)) 
     442                    { 
     443                        int l; 
     444                        for(l = k; !ment_done(l); l = ment_next(mtbl, l)){ 
     445                            struct mem_ent_s * ment = &(mtbl->mem[l]); 
     446                            fprintf(out, "\t\tMEMORY ENTRY INDEX %d ***********" 
     447                                                              "*********\n", l); 
     448                            fprintf(out, "\t\ttag = 0X%llX\n",  
     449                                            (uint64_t)ment->tag); 
     450                            fprintf(out, "\t\titem = %d\n",  
     451                                            (int32_t)ment->item); 
     452                            fprintf(out, "\t\tnext = %d\n",  
     453                                            (int16_t)ment->next); 
     454                            fprintf(out, "\t\tdirty_next = %d\n",  
     455                                        (int16_t)ment->dirty_next); 
     456                            fprintf(out, "\t\tlru_next = %d\n",  
     457                                            (int16_t)ment->lru_next); 
     458                            fprintf(out, "\t\tlru_prev = %d\n\n",  
     459                                            (int16_t)ment->lru_prev); 
     460                        }  
     461                    } 
     462                    else 
     463                        if((uint16_t)mtbl->num_blocks != 0) 
     464                        { 
     465                            fprintf(out, "\tvacant memory entry @ index = %d\n", 
     466                                                                             k); 
     467                        } 
     468                } 
     469            } 
     470            fprintf(out, "End of chain @ Hash Table Index %d\n\n", i); 
     471        } 
     472        else 
     473            fprintf(out, "vacant file entry @ index = %d\n", i); 
     474    } 
     475} 
     476/***************************************** End of Externally Visible API */ 
     477 
     478 
     479/* Beginning of internal only (static) functions */ 
     480 
     481/** Initializes the proper lock based on the LOCK_TYPE */ 
     482static int lock_init(ucache_lock_t * lock) 
    235483{ 
    236484    /*  Set pshared (2nd arg) to non-zero value to share semaphore b/w forked  
    237485     *  processes 
    238486     */ 
    239     return sem_init(lock, 1, 1);  
    240 } 
    241  
    242 /*  Returns 0 when lock is locked; otherwise, return -1 and sets errno*/ 
    243 static int ucache_lock_lock(ucache_lock_t * lock) 
    244 { 
     487    /* TODO: ability to disable locking */ 
     488    #if LOCK_TYPE==0 
     489    return sem_init(lock, 1, 1); 
     490    #elif LOCK_TYPE==1 
     491    return pthread_mutex_init(lock, NULL); 
     492    #elif LOCK_TYPE==2 
     493    return pthread_spin_init(lock, 1); 
     494    #endif 
     495} 
     496 
     497/** Returns 0 when lock is locked; otherwise, return -1 and sets errno */ 
     498static int lock_lock(ucache_lock_t * lock) 
     499{ 
     500    #if LOCK_TYPE==0 
    245501    return sem_wait(lock); 
    246 } 
    247  
    248 /*  If successful, return zero; otherwise, return -1 and sets errno */ 
    249 static int ucache_lock_unlock(ucache_lock_t * lock) 
    250 { 
     502    #elif LOCK_TYPE==1 
     503    return pthread_mutex_lock(lock); 
     504    #elif LOCK_TYPE==2 
     505    return pthread_spin_lock(lock); 
     506    #endif    
     507} 
     508 
     509/** If successful, return zero; otherwise, return -1 and sets errno */ 
     510static int lock_unlock(ucache_lock_t * lock) 
     511{ 
     512    #if LOCK_TYPE==0 
    251513    return sem_post(lock); 
    252 } 
    253  
    254 /*  Upon successful completion, returns zero; otherwise, returns and sets errno. 
    255  */ 
    256 static int ucache_lock_getvalue(ucache_lock_t * lock, int *sval) 
     514    #elif LOCK_TYPE==1 
     515    return pthread_mutex_unlock(lock); 
     516    #elif LOCK_TYPE==2 
     517    return pthread_spin_unlock(lock); 
     518    #endif 
     519} 
     520 
     521/** Upon successful completion, returns zero;  
     522 * Otherwise, returns -1 and sets errno. 
     523 */ 
     524#if LOCK_TYPE==0 
     525int ucache_lock_getvalue(ucache_lock_t * lock, int *sval) 
    257526{ 
    258527    return sem_getvalue(lock, sval); 
    259528} 
    260  
    261 /* Upon successful completion, returns zero; otherwise returns 1 and sets errno. 
    262  */ 
    263 static int ucache_lock_destroy(ucache_lock_t * lock) 
    264 { 
     529#endif 
     530 
     531/** Upon successful completion, returns zero. 
     532 * Otherwise, returns 1 and sets errno. 
     533 */ 
     534static int lock_destroy(ucache_lock_t * lock) 
     535{ 
     536    #if LOCK_TYPE==0 
    265537    return sem_destroy(lock);  
    266 } 
    267  
    268 /*  Dirty List Iterator */ 
     538    #elif LOCK_TYPE==1 
     539    return pthread_mutex_destroy(lock); 
     540    #elif LOCK_TYPE==2 
     541    return pthread_spin_destroy(lock); 
     542    #endif 
     543} 
     544 
     545/* Dirty List Iterator */ 
     546/** Returns true if current index is NIL, otherwise, returns 0 */ 
    269547static int dirty_done(uint16_t index) 
    270548{ 
     
    272550} 
    273551 
     552/** Returns the next index in the dirty list for the provided mtbl and index */ 
    274553static int dirty_next(struct mem_table_s *mtbl, uint16_t index) 
    275554{ 
     
    278557 
    279558/*  Memory Entry Chain Iterator */ 
     559/** Returns true if current index is NIL, otherwise, returns 0 */ 
    280560static int ment_done(int index) 
    281561{ 
     
    283563} 
    284564 
     565/** Returns the next index in the memory entry chain for the provided mtbl  
     566 * and index.  
     567 */ 
    285568static int ment_next(struct mem_table_s *mtbl, int index) 
    286569{ 
     
    289572 
    290573/*  File Entry Chain Iterator   */ 
     574/** Returns true if current index is NIL, otherwise, returns 0 */ 
    291575static int file_done(int index) 
    292576{ 
     
    294578} 
    295579 
     580/** Returns the next index in the file entry chain for the provided mtbl  
     581 * and index.  
     582 */ 
    296583static int file_next(struct file_table_s *ftbl, int index) 
    297584{ 
     
    299586} 
    300587 
    301 /*   
    302  *  This function should only be called when the ftbl has no free mtbls.  
     588/**This function should only be called when the ftbl has no free mtbls.  
     589 * It initizializes MTBL_PER_BLOCK additional mtbls in the block provided, 
     590 * meaning this block will no longer be used for storing file data but  
     591 * hash table related data instead. 
    303592 */ 
    304593static void add_free_mtbls(int blk) 
     
    328617} 
    329618 
     619/** Initializes a mtbl which is a hash table of memory entries. 
     620 * The mtbl will be located at the provided entry index within  
     621 * the provided block. 
     622 */ 
    330623static void init_memory_table(int blk, int ent) 
    331624{ 
    332625    int i; 
    333626    struct mem_table_s *mtbl = &(ucache->b[blk].mtbl[ent]); 
    334  
    335627    mtbl->lru_first = NIL; 
    336628    mtbl->lru_last = NIL; 
    337629    mtbl->dirty_list = NIL; 
    338630    mtbl->num_blocks = 0; 
     631    mtbl->ref_cnt = 0; 
    339632    /* set up hash table */ 
    340633    for (i = 0; i < MEM_TABLE_HASH_MAX; i++) 
     
    355648} 
    356649 
     650/** This function asks the file table if a free block is avaialable.  
     651 * If so, returns the block's index; otherwise, returns NIL. 
     652 */ 
    357653static uint16_t get_free_blk(void) 
    358654{ 
     
    361657    if((int16_t)free_blk!=NIL) 
    362658    {    
    363         /* Use zero since free_blks have no ititialized mem tables */ 
     659        /* Use mtbl index zero since free_blks have no ititialized mem tables */ 
    364660        ftbl->free_blk = ucache->b[free_blk].mtbl[0].free_list;  
    365661        return free_blk; 
     
    369665} 
    370666 
     667/** Accepts an index corresponding to a block that is put back on the file  
     668 * table free list. 
     669 */ 
    371670static void put_free_blk(int blk) 
    372671{ 
    373672    if(DBG)fprintf(out, "freeing blk @ index = %d\n", blk); 
    374673    struct file_table_s *ftbl = &(ucache->ftbl); 
     674    /* set the block's next value to the current head of the block free list */ 
    375675    ucache->b[blk].mtbl[0].free_list = ftbl->free_blk; 
     676    /* set this to NIL, since only used when mtbl is on mtbl free list */ 
    376677    ucache->b[blk].mtbl[0].free_list_blk = NIL;  
     678    /* blk is now the head of the ftbl blk free list */ 
    377679    ftbl->free_blk = blk; 
    378680} 
    379681 
     682/** Consults the file table to retrieve an index corresponding to a file entry 
     683 * If available, returns the file entry index, otherwise returns NIL. 
     684 */ 
    380685static int get_free_fent(void) 
    381686{ 
     
    396701} 
    397702 
     703/** Places the file entry located at the provided index back on the file table's 
     704 * free file entry list. If the index is < FILE_TABLE_HASH_MAX, then set next  
     705 * to NIL since this index must remain the head of the linked list. Otherwise, 
     706 * set next to the current head of fent free list and set the free list head to 
     707 * the provided index. 
     708 */ 
    398709static void put_free_fent(int fent) 
    399710{ 
     
    402713    ftbl->file[fent].tag_handle = NIL; 
    403714    ftbl->file[fent].tag_id = NIL; 
    404     /*  Set fent index as the head of the free_list */ 
    405     if(fent>(FILE_TABLE_HASH_MAX-1)) 
    406     { 
     715    if(fent<FILE_TABLE_HASH_MAX) 
     716    { 
     717        ftbl->file[fent].next = NIL; 
     718    } 
     719    else 
     720    { 
     721        /* Set next index to the current head of the free list */ 
    407722        ftbl->file[fent].next = ftbl->free_list; 
     723        /* Set fent index as the head of the free_list */ 
    408724        ftbl->free_list = fent; 
    409725    } 
    410     else 
    411     { 
    412         ftbl->file[fent].next = NIL; 
    413     } 
    414 } 
    415  
     726} 
     727 
     728/** Consults the provided mtbl's memory entry free list to get the index of the 
     729 * next free memory entry. Returns the index if one is available, otherwise  
     730 * returns NIL. 
     731 */ 
    416732static int get_free_ment(struct mem_table_s *mtbl) 
    417733{ 
    418     uint16_t ret = mtbl->free_list; 
    419     if((int16_t)ret!=NIL) 
    420     { 
    421         mtbl->free_list = mtbl->mem[ret].next; 
    422         mtbl->mem[ret].next = NIL; 
    423         mtbl->mem[ret].lru_prev = NIL; 
    424         mtbl->mem[ret].lru_next = NIL; 
    425         return ret; 
    426     } 
    427     return NIL; 
    428 } 
    429  
     734    uint16_t ment = mtbl->free_list; 
     735    if((int16_t)ment!=NIL) 
     736    { 
     737        mtbl->free_list = mtbl->mem[ment].next; 
     738        mtbl->mem[ment].next = NIL; 
     739/*      mtbl->mem[ment].lru_prev = NIL; 
     740        mtbl->mem[ment].lru_next = NIL; */ 
     741    } 
     742    return ment; 
     743} 
     744 
     745/** Puts the memory entry corresponding to the provided mtbl and entry index  
     746 * back on the mtbl's memory entry free list.  
     747 * 
     748 * If the entry index is < MEM_TABLE_HASH_MAX, then set next to NIL since this  
     749 * index must remain the head of the linked list. Otherwise, set next to the  
     750 * current head of ment free list and set the free list head to the provided  
     751 * index. 
     752 */ 
    430753static void put_free_ment(struct mem_table_s *mtbl, int ent) 
    431754{ 
    432755    if(DBG)fprintf(out, "freeing memory entry = %d\n", ent); 
    433     /*  Reset ment values  */ 
     756    /* Reset ment values */ 
    434757    mtbl->mem[ent].tag = NIL; 
    435758    mtbl->mem[ent].item = NIL; 
     
    437760    mtbl->mem[ent].lru_next = NIL; 
    438761    mtbl->mem[ent].lru_prev = NIL; 
    439     /*  Update free list to include this entry  */ 
    440     if(ent>(MEM_TABLE_HASH_MAX-1)) 
    441     { 
     762    if(ent<MEM_TABLE_HASH_MAX) 
     763    { 
     764        mtbl->mem[ent].next = NIL; 
     765    } 
     766    else{ 
     767        /* Set next index to the current head of the free list */ 
    442768        mtbl->mem[ent].next = mtbl->free_list; 
     769        /* Update free list to include this entry */ 
    443770        mtbl->free_list = ent; 
    444771    } 
    445772} 
    446773 
     774/** Perform a file lookup on the ucache using the provided fs_id and handle. 
     775 * 
     776 * Additional parameters (references) may used that will be set to values  
     777 * pertaining to mtbl and file entry location. If NULL is passed in place of  
     778 * these parameters, then they cannot be set. 
     779 * 
     780 * If the file is found, a pointer to the mtbl is returned and the parameter  
     781 * references set accordingly. Otherwise, NIL is returned.  
     782 */ 
    447783static struct mem_table_s *lookup_file( 
    448784    uint32_t fs_id,  
    449785    uint64_t handle, 
    450     uint32_t *file_mtbl_blk,        /* Can be NULL if not desired   */ 
    451     uint16_t *file_mtbl_ent,        /* Can be NULL if not desired   */ 
    452     uint16_t *file_ent_index,   /* Can be NULL if not desired   */ 
    453     uint16_t *file_ent_prev_index   /* Can be NULL if not desired   */ 
     786    uint32_t *file_mtbl_blk, 
     787    uint16_t *file_mtbl_ent, 
     788    uint16_t *file_ent_index, 
     789    uint16_t *file_ent_prev_index 
    454790) 
    455791{ 
    456     int16_t p,c,n;  /*  previous, current, next fent index  */ 
    457792    if(DBG)fprintf(out, "performing lookup...\n"); 
    458     struct file_table_s *ftbl = &(ucache->ftbl); 
    459     struct file_ent_s *current; /* Current ptr for iteration    */ 
    460     /* Index into file hash table   */ 
     793 
     794    /* Index into file hash table */ 
    461795    int index = handle % FILE_TABLE_HASH_MAX; 
    462796    if(DBG)fprintf(out, "\thashed index: %d\n", index); 
    463     current = &(ftbl->file[index]); 
    464     p=NIL; c = index; n = current->next; 
     797 
     798    struct file_table_s *ftbl = &(ucache->ftbl); 
     799    struct file_ent_s *current = &(ftbl->file[index]); 
     800 
     801    /* previous, current, next fent index */ 
     802    uint16_t p = NIL; 
     803    uint16_t c = index; 
     804    uint16_t n = current->next; 
     805 
    465806    while(1) 
    466807    { 
    467         if(DBG)fprintf(out, "\tp=%d\tc=%d\tn=%d\n", (int)p, (int)c, (int)n); 
    468         if(current->tag_id==fs_id && current->tag_handle==handle) 
     808        if(DBG)fprintf(out, "\tp=%d\tc=%d\tn=%d\n", (int16_t)p, (int16_t)c,  
     809                                                                (int16_t)n); 
     810        if((current->tag_id == fs_id) && (current->tag_handle == handle)) 
    469811        { 
    470812            if(DBG)fprintf(out, "\tFile located in chain\n"); 
    471             /*  If params !NULL, set their values  */ 
     813            /* If params !NULL, set their values */ 
    472814            if(file_mtbl_blk!=NULL && file_mtbl_ent!=NULL &&  
    473815                file_ent_index!=NULL && file_ent_prev_index!=NULL) 
     
    478820                    *file_ent_prev_index = p; 
    479821            } 
    480             return (struct mem_table_s *)&(ucache->b[ 
    481                     current->mtbl_blk].mtbl[ 
    482                     current->mtbl_ent]); 
    483         } 
    484         else    /*  No match yet    */ 
     822            return (struct mem_table_s *)&(ucache->b[current->mtbl_blk].mtbl[ 
     823                                                            current->mtbl_ent]); 
     824        } 
     825        /* No match yet */ 
     826        else     
    485827        { 
    486             if((int16_t)current->next==NIL) 
     828            if((int16_t)current->next == NIL) 
    487829            { 
    488830                if(DBG)fprintf(out, "\tlookup failure: mtbl not found\n"); 
     
    502844} 
    503845 
     846/** Function that locates the next free mtbl. 
     847 * On success, Returns 1 and sets reference parameters to proper indexes. 
     848 * On failure, returns NIL;  
     849 */ 
    504850static int get_next_free_mtbl(uint32_t *free_mtbl_blk, uint16_t *free_mtbl_ent) 
    505851{ 
    506852        struct file_table_s *ftbl = &(ucache->ftbl); 
    507         /*  get next free mtbl_blk and ent  */ 
     853 
     854        /* Get next free mtbl_blk and ent from ftbl */ 
    508855        *free_mtbl_blk = ftbl->free_mtbl_blk; 
    509856        *free_mtbl_ent = ftbl->free_mtbl_ent; 
    510         /* is free mtbl_blk available? */ 
    511         if((int32_t)*free_mtbl_blk!=NIL && (int16_t)*free_mtbl_ent!=NIL) 
     857 
     858        /* Is free mtbl_blk available? */ 
     859        if(((int32_t)*free_mtbl_blk == NIL) || ((int16_t)*free_mtbl_ent == NIL)) 
    512860        {  
    513             ftbl->free_mtbl_blk = ucache->b[*free_mtbl_blk]. 
    514                 mtbl[*free_mtbl_ent].free_list_blk; 
    515             ftbl->free_mtbl_ent = ucache->b[*free_mtbl_blk]. 
    516                 mtbl[*free_mtbl_ent].free_list; 
    517             /* Set free info to NIL - NECESSARY? */ 
    518             ucache->b[*free_mtbl_blk]. 
    519                 mtbl[*free_mtbl_ent].free_list = NIL; 
    520             ucache->b[*free_mtbl_blk]. 
    521                 mtbl[*free_mtbl_ent].free_list_blk = NIL; 
    522             return 1; 
    523         } 
    524         return NIL; 
    525 } 
    526  
     861            return NIL; 
     862        } 
     863 
     864        /* Update ftbl to contain new next free mtbl */ 
     865        ftbl->free_mtbl_blk = ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent]. 
     866                                                                free_list_blk; 
     867        ftbl->free_mtbl_ent = ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent]. 
     868                                                                    free_list; 
     869 
     870        /* Set free info to NIL - NECESSARY? */ 
     871        ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent].free_list = NIL; 
     872        ucache->b[*free_mtbl_blk].mtbl[*free_mtbl_ent].free_list_blk = NIL; 
     873        return 1; 
     874} 
     875 
     876/** Removes all memory entries belonging to mtbl and places corresponding blocks  
     877 * back on the ftbl block free list, provided the mtbl->ref_cnt is 0.   
     878 */ 
    527879static void remove_all_memory_entries(struct mem_table_s *mtbl) 
    528880{ 
    529     /*  remove all ments, including their associated blocks */ 
    530     int i = 0; 
    531     for(i=0;i<MEM_TABLE_HASH_MAX;i++) 
     881    /* Don't do anything if this mtbl is referenced.*/ 
     882    if(mtbl->ref_cnt != 0) 
     883    { 
     884        return; 
     885    } 
     886 
     887    int i; 
     888    for(i = 0; i < MEM_TABLE_HASH_MAX; i++) 
    532889    { 
    533890        if(DBG)fprintf(out, "\tremoving memory entry %d\n", i); 
    534891        int j; 
    535         for(j=i;!ment_done(j); j=ment_next(mtbl, j)) 
     892        for(j = i;!ment_done(j); j = ment_next(mtbl, j)) 
    536893        { 
     894            /* Current Memory Entry */ 
    537895            struct mem_ent_s *ment = &(mtbl->mem[j]); 
    538             if(DBG)fprintf(out, "\t(tag, item)=(%lld, %d)\n",\ 
    539                 (int64_t)ment->tag,(int32_t)ment->item); 
     896            if(DBG)fprintf(out, "\t(tag, item)=(%lld, %d)\n",  
     897                    (int64_t)ment->tag,(int32_t)ment->item); 
    540898            /*  Account for empty head of ment chain    */ 
    541             if((int64_t)ment->tag==NIL || (int32_t)ment->item==NIL){ 
     899            if(((int64_t)ment->tag == NIL) || ((int32_t)ment->item == NIL)) 
     900            { 
    542901                break; 
    543902            } 
     
    548907} 
    549908 
     909/** Places the provided mtbl back on the ftbl's mtbl free list provided it  
     910 * isn't currently referenced. 
     911 */ 
    550912static void put_free_mtbl(struct mem_table_s *mtbl, struct file_ent_s *file) 
    551913{ 
    552     /*  remove mtbl */ 
    553     mtbl->num_blocks = NIL; /* number of used blocks in this mtbl */ 
     914    /* Don't do anything if this mtbl is referenced.*/ 
     915    if(mtbl->ref_cnt != 0) 
     916    { 
     917        return; 
     918    } 
     919 
     920    /* Remove mtbl */ 
     921    mtbl->num_blocks = 0;   /* number of used blocks in this mtbl */ 
    554922    mtbl->lru_first = NIL;  /* index of first block on lru list */ 
    555923    mtbl->lru_last = NIL;   /* index of last block on lru list */ 
    556924    mtbl->dirty_list = NIL; /* index of first dirty block */ 
    557     mtbl->ref_cnt = NIL;    /* number of clients using this record */ 
    558     /*  add mem_table back to free list */ 
    559     /*  Temporarily store copy of current head (the new next)   */ 
     925    mtbl->ref_cnt = 0;      /* number of clients using this record */ 
     926 
     927    /* Add mem_table back to free list */ 
     928    /* Temporarily store copy of current head (the new next) */ 
    560929    uint32_t tmp_blk = ucache->ftbl.free_mtbl_blk; 
    561930    uint16_t tmp_ent = ucache->ftbl.free_mtbl_ent; 
    562     /*  newly free mtbl becomes new head of free mtbl list */ 
     931    /* newly free mtbl becomes new head of free mtbl list */ 
    563932    ucache->ftbl.free_mtbl_blk = file->mtbl_blk; 
    564933    ucache->ftbl.free_mtbl_ent = file->mtbl_ent; 
    565     /* Point to the next free mtbl (the former head)    */ 
     934    /* Point to the next free mtbl (the former head) */ 
    566935    mtbl->free_list_blk = tmp_blk; 
    567936    mtbl->free_list = tmp_ent; 
    568937} 
    569938 
     939/** Evict the file entry at the provided index. 
     940 * On Success, returns 1. If file is currently referenced, do not evict and  
     941 * return 0. 
     942 */ 
    570943/*  evict the file @ index, must be less than FILE_TABLE_HASH_MAX   */ 
    571 static void evict_file(unsigned int index) 
     944static int evict_file(unsigned int index) 
    572945{ 
    573946    if(DBG)fprintf(out, "evicting data @ index %d...\n", index); 
     
    575948    struct mem_table_s *mtbl =  
    576949        &(ucache->b[file->mtbl_blk].mtbl[file->mtbl_ent]); 
     950 
     951    if(mtbl->ref_cnt != 0){ 
     952        return 0; 
     953    } 
     954 
    577955    remove_all_memory_entries(mtbl); 
    578956    put_free_mtbl(mtbl, file); 
    579     /*  instead of removing, simply prepare fent for it's next occupant */ 
     957 
     958    /* Prepare fent for its next occupant */ 
    580959    file->tag_handle = NIL; 
    581960    file->tag_id = NIL; 
    582961    file->mtbl_blk = NIL;   /* block index of this mtbl */ 
    583962    file->mtbl_ent = NIL;   /* entry index of this mtbl */ 
    584 } 
    585  
     963    return 1; 
     964} 
     965 
     966/** Insert information about file into ucache (no file data inserted) 
     967 * Returns pointer to mtbl on success. 
     968 *  
     969 * Returns NIL if necessary data structures could not be aquired from the free 
     970 * lists or through an eviction policy (meaning references are held). 
     971 */ 
    586972static struct mem_table_s *insert_file(uint32_t fs_id, uint64_t handle) 
    587973{ 
    588974    if(DBG)fprintf(out, "trying to insert file...\n"); 
    589975    struct file_table_s *ftbl = &(ucache->ftbl); 
    590     struct file_ent_s *current; /* Current ptr for iteration    */ 
    591     uint16_t free_fent; /* Index of next free fent */ 
    592     /*  index into file hash table */ 
     976    struct file_ent_s *current;     /* Current ptr for iteration */ 
     977    uint16_t free_fent = NIL;       /* Index of next free fent */ 
     978    /* index into file hash table */ 
    593979    unsigned int index = handle % FILE_TABLE_HASH_MAX; 
    594980    if(DBG)fprintf(out, "\thashed index: %u\n", index); 
    595981    current = &(ftbl->file[index]); 
    596     /*  Get next free mem_table */ 
    597     uint32_t free_mtbl_blk; 
    598     uint16_t free_mtbl_ent;  
    599     /*  Create free mtbls if none are available */ 
    600     if(get_next_free_mtbl(&free_mtbl_blk, &free_mtbl_ent)!=1) 
     982    /* Get free mtbl */ 
     983    uint32_t free_mtbl_blk = NIL; 
     984    uint16_t free_mtbl_ent = NIL;  
     985    /* Create free mtbls if none are available */ 
     986    if(get_next_free_mtbl(&free_mtbl_blk, &free_mtbl_ent) != 1) 
    601987    {    
    602         if((int16_t)ucache->ftbl.free_blk==NIL)  
     988        if((int16_t)ucache->ftbl.free_blk == NIL)  
    603989        { 
    604             /*  Evict a block from mtbl with most mem entries  */ 
     990            /* Evict a block from mtbl with most mem entries */ 
    605991            struct mem_table_s *max_mtbl; 
    606             int num_blocks = locate_max_mtbl(&max_mtbl); 
    607             if(DBG)fprintf(out, "\tget_free_blk returned NIL, evicting a block from max mtbl which has %d entries\n",max_mtbl->num_blocks); 
     992            locate_max_mtbl(&max_mtbl); 
     993            if(DBG)fprintf(out, "\tget_free_mtbl returned NIL\n"); 
     994            if(DBG)fprintf(out, "\tevicting blk from max mtbl: has %d entries\n" 
     995                                                        ,max_mtbl->num_blocks); 
    608996            evict_LRU(max_mtbl); 
    609997        } 
    610         /*  Intitialize remaining blocks' memory tables */ 
    611         if((int16_t)ucache->ftbl.free_blk!=NIL) 
     998        /* Intitialize remaining blocks' memory tables */ 
     999        if((int16_t)ucache->ftbl.free_blk != NIL) 
    6121000        { 
    6131001            if(DBG)fprintf(out, "\tadding memory tables to free block\n"); 
     
    6161004        } 
    6171005    } 
    618     /*  Insert at index, relocating data @ index if occupied    */ 
    619     if((int32_t)current->mtbl_blk!=NIL && (int16_t)current->mtbl_ent!=NIL)  
     1006 
     1007    /* Insert at index, relocating data @ index if occupied */ 
     1008    if(((int32_t)current->mtbl_blk != NIL) &&  
     1009        ((int16_t)current->mtbl_ent != NIL))  
    6201010    { 
    6211011        if(DBG)fprintf(out, "\tmust relocate head data\n"); 
    622         /*  get free file entry and update ftbl */ 
     1012        /* get free file entry and update ftbl */ 
    6231013        free_fent = get_free_fent(); 
    624         if((int16_t)free_fent!=NIL) 
     1014        if((int16_t)free_fent != NIL) 
    6251015        { 
    626             /*  copy data from 1 struct to the other    */ 
     1016            /* copy data from 1 struct to the other */ 
    6271017            ftbl->file[free_fent] = *current;    
    628  
    629             /*  point new head's "next" to former head  */ 
     1018            /* point new head's "next" to former head */ 
    6301019            current->next = free_fent;   
    6311020        } 
    6321021        else 
    633         {   /*  No free file entries available: policy? */ 
     1022        {   /* No free file entries available: policy? */ 
    6341023            if(DBG)fprintf(out, "\tno free file entries\n"); 
    635             evict_file(index); 
     1024            /* Attempt to evict a file in a chain corresponding to the hashed  
     1025             * index into the ftbl. 
     1026             * Return NIL if it isn't possible. 
     1027             */ 
     1028            /* Stop when the file has been evicted or end of chain reached */ 
     1029            int file_evicted = evict_file(index); 
     1030            int i; 
     1031            for(i = index; !file_done(i) && (!file_evicted); i =  
     1032                                            file_next(ftbl,index)) 
     1033            { 
     1034                i = ftbl->file[i].next; 
     1035                current = &(ftbl->file[i]); 
     1036                file_evicted = evict_file((unsigned int)i); 
     1037            } 
     1038            if(!file_evicted) 
     1039            { 
     1040                /* Could not get file entry */ 
     1041                return (struct mem_table_s *)NIL; 
     1042            } 
    6361043        } 
    6371044    } 
     
    6401047        if(DBG)fprintf(out, "\tno head data @ index\n"); 
    6411048    } 
    642     /*  insert file data @ index    */ 
     1049    /* Insert file data @ index */ 
    6431050    current->tag_id = fs_id; 
    6441051    current->tag_handle = handle; 
    645     /*  Update fent with it's new mtbl: blk and ent */ 
     1052    /* Update fent with it's new mtbl: blk and ent */ 
    6461053    current->mtbl_blk = free_mtbl_blk; 
    6471054    current->mtbl_ent = free_mtbl_ent; 
    648     /*  Initialize Memory Table */ 
     1055    /* Initialize Memory Table */ 
    6491056    init_memory_table(free_mtbl_blk, free_mtbl_ent); 
    6501057    if(DBG)fprintf(out, "\trecieved free memory table: 0X%X\n",  
    651         (unsigned int)&(ucache->b[current->mtbl_blk].mtbl[ 
    652         current->mtbl_ent])); 
    653     return &(ucache->b[current->mtbl_blk].mtbl[ 
    654         current->mtbl_ent]); 
    655 } 
    656  
     1058        (unsigned int)&(ucache->b[current->mtbl_blk].mtbl[current->mtbl_ent])); 
     1059    return &(ucache->b[current->mtbl_blk].mtbl[current->mtbl_ent]); 
     1060} 
     1061 
     1062/** Remove file entry and memory table of file identified by parameters 
     1063 * Returns 1 following removal 
     1064 * Returns NIL if file is referenced or if the file could not be located. 
     1065 */ 
    6571066static int remove_file(uint32_t fs_id, uint64_t handle) 
    6581067{ 
    6591068    if(DBG)fprintf(out, "trying to remove file...\n"); 
     1069    uint32_t file_mtbl_blk = NIL; 
     1070    uint16_t file_mtbl_ent = NIL; 
     1071    uint16_t file_ent_index = NIL; 
     1072    uint16_t file_ent_prev_index = NIL; 
     1073 
    6601074    struct file_table_s *ftbl = &(ucache->ftbl); 
    661     int32_t file_mtbl_blk; 
    662     int16_t file_mtbl_ent; 
    663     int16_t file_ent_index; 
    664     int16_t file_ent_prev_index; 
    665     struct mem_table_s *mtbl = lookup_file(fs_id, handle,  
    666         &file_mtbl_blk, &file_mtbl_ent, &file_ent_index,  
    667         &file_ent_prev_index); 
    668     /*  Verify we've recieved the necessary info    */ 
    669     if((int32_t)file_mtbl_blk==NIL || (int16_t)file_mtbl_ent==NIL) 
     1075    struct mem_table_s *mtbl = lookup_file(fs_id, handle, &file_mtbl_blk,  
     1076                    &file_mtbl_ent, &file_ent_index, &file_ent_prev_index); 
     1077 
     1078    if(mtbl->ref_cnt != 0) 
     1079    { 
     1080        if(DBG)fprintf(out, "\tremoval failure: ref_cnt==%d\n", mtbl->ref_cnt); 
     1081        return NIL; 
     1082    } 
     1083 
     1084    /* Verify we've recieved the necessary info */ 
     1085    if(((int32_t)file_mtbl_blk == NIL) || ((int16_t)file_mtbl_ent == NIL)) 
    6701086    { 
    6711087        if(DBG)fprintf(out, "\tremoval failure: no mtbl matching file\n"); 
    6721088        return NIL; 
    6731089    } 
    674     /*  add mem_table back to free list */ 
    675     /*  Temporarily store copy of current head (the new next)   */ 
    676     uint32_t tmp_blk = ftbl->free_mtbl_blk; 
    677     uint16_t tmp_ent = ftbl->free_mtbl_ent; 
    678     /*  newly free mtbl becomes new head of free mtbl list  */ 
    679     ftbl->free_mtbl_blk = file_mtbl_blk; 
    680     ftbl->free_mtbl_ent = file_mtbl_ent; 
    681     /* Point to the next free mtbl (the former head)    */ 
    682     mtbl->free_list_blk = tmp_blk; 
    683     mtbl->free_list = tmp_ent; 
    684     /*  Free the file entry */ 
     1090 
     1091    /* Free the mtbl */ 
     1092    put_free_mtbl(mtbl, &(ftbl->file[file_ent_index])); 
     1093 
     1094    /* Free the file entry */ 
    6851095    ftbl->file[file_ent_prev_index].next = ftbl->file[file_ent_index].next; 
    6861096    put_free_fent(file_ent_index); 
     1097 
    6871098    if(DBG)fprintf(out, "\tremoval sucessful\n"); 
    6881099    return(1); 
    6891100} 
    6901101 
     1102/** Lookup the memory location of a block of data in cache that is identified  
     1103 * by the mtbl and offset parameters. 
     1104 * 
     1105 * If located, returns a pointer to memory where the desired block of data is  
     1106 * stored. Otherwise, NIL is returned. 
     1107 * 
     1108 * Additional parameters (references) may be used that will be set to values  
     1109 * pertaining to the memory entry's location. If NULLs are passed in place of  
     1110 * these parameters, then they will not be set. 
     1111 */ 
    6911112static void *lookup_mem(struct mem_table_s *mtbl,  
    6921113                    uint64_t offset,  
     
    6961117{ 
    6971118    if(DBG)fprintf(out, "performing ment lookup...\n"); 
    698     /*  index into mem hash table   */ 
     1119 
     1120    /* index into mem hash table */ 
    6991121    unsigned int index = offset % MEM_TABLE_HASH_MAX; 
    700     if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n",\ 
    701         offset, index); 
     1122    if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n", offset,  
     1123                                                              index); 
     1124 
    7021125    struct mem_ent_s *current = &(mtbl->mem[index]); 
    703     /*  previous, current, next memory entry index in mtbl  */ 
    704     int16_t p,c,n;   
    705     p = NIL; c = index; n = current->next; 
     1126 
     1127    /* previous, current, next memory entry index in mtbl */ 
     1128    int16_t p = NIL; 
     1129    int16_t c = index; 
     1130    int16_t n = current->next;   
     1131 
    7061132    while(1) 
    7071133    { 
    708         if(offset==current->tag) 
     1134        if(offset == current->tag) 
    7091135        { 
    710             if(DBG)fprintf(out, "\tmatch located: 0X%llX==0X%llX\n",\ 
    711                 offset, current->tag); 
    712          
    713             /*  If params !NULL, set their values  */ 
    714             if(item_index!=NULL && mem_ent_index!=NULL &&  
    715                 mem_ent_prev_index!=NULL) 
     1136            if(DBG)fprintf(out, "\tmatch located: 0X%llX==0X%llX\n", offset,  
     1137                                                            current->tag); 
     1138 
     1139            /* If parameters !NULL, set their values */ 
     1140            if((item_index != NULL) && (mem_ent_index != NULL) &&  
     1141                                    (mem_ent_prev_index != NULL)) 
    7161142            { 
    7171143                    *item_index = current->item; 
     
    7231149        else 
    7241150        { 
    725             /*  if(DBG)fprintf(out, "\t0X%llX!=0X%llX\n", offset,\  
    726                 current->tag);  */ 
    727             /*  if next available iterate   */ 
    728             if((int16_t)current->next==NIL) 
     1151            if((int16_t)current->next == NIL) 
    7291152            { 
    7301153                if(DBG)fprintf(out, "\tmemory entry not found\n"); 
     
    7331156            else 
    7341157            { 
     1158                /* Iterate */ 
    7351159                current = &(mtbl->mem[current->next]); 
    736                 p=c; c=n; n=current->next; 
     1160                p = c;  
     1161                c = n;  
     1162                n = current->next; 
    7371163            } 
    7381164        } 
     
    7401166} 
    7411167 
     1168/** Update the provided mtbl's LRU doubly-linked list by placing the memory  
     1169 * entry, identified by the provided index, at the head of the list (lru_first). 
     1170 * 
     1171 */ 
    7421172static void update_lru(struct mem_table_s *mtbl, uint16_t index) 
    7431173{ 
    7441174            if(DBG)fprintf(out, "updating lru...\n"); 
    745             if((int16_t)index<MEM_TABLE_HASH_MAX) 
     1175            /* Do not place an entry with index < MEM_TABLE_HASH_MAX because  
     1176             * they must remain the heads of the hash table chains 
     1177             */ 
     1178            if((int16_t)index < MEM_TABLE_HASH_MAX) 
    7461179            { 
    747                 if(DBG)fprintf(out, "\t%d<MEM_TABLE_HASH_MAX, not adding to LRU\n", index); 
     1180                if(DBG)fprintf(out,  
     1181                        "\t%d<MEM_TABLE_HASH_MAX, not adding to LRU\n", index); 
    7481182                return; 
    7491183            } 
    750             /*  update LRU List */ 
    751             if((int16_t)mtbl->lru_first==NIL && (int16_t)mtbl->lru_last==NIL) 
     1184   
     1185            /* First memory entry used becomes the head and tail of the list */ 
     1186            if(((int16_t)mtbl->lru_first == NIL) &&  
     1187                    ((int16_t)mtbl->lru_last == NIL)) 
    7521188            { 
    7531189                if(DBG)fprintf(out, "\tsetting lru first and last\n"); 
     
    7571193                mtbl->mem[index].lru_next = NIL; 
    7581194            } 
    759             else if(mtbl->lru_first==mtbl->lru_last) 
     1195            /* 2nd Memory Entry */ 
     1196            else if(mtbl->lru_first == mtbl->lru_last) 
    7601197            { 
    761                 if(mtbl->lru_first!=index) 
    762                 {   /*  if not already the first and last   */ 
    763                     if(DBG)fprintf(out, "\tinserting second record in   LRU\n"); 
    764                     /*  point tail.prev to new  */ 
     1198                /* Do nothing if this index is already the only entry */ 
     1199                if(mtbl->lru_first == index) 
     1200                { 
     1201                    return; 
     1202                } 
     1203                else 
     1204                {   /* Must be 2nd unique memory entry */ 
     1205                    if(DBG)fprintf(out, "\tinserting second record in LRU\n"); 
     1206                    /* point tail.prev to new */ 
    7651207                    mtbl->mem[mtbl->lru_last].lru_prev = index;  
    766                     /*  point new.prev to nil  */   
     1208                    /* point new.prev to NIL */   
    7671209                    mtbl->mem[index].lru_prev = NIL; 
    768                     /*  point the new.next to the tail */       
     1210                    /* point the new.next to the tail */       
    7691211                    mtbl->mem[index].lru_next = mtbl->lru_last; 
    770                     /*  point the head to the new  */   
     1212                    /* point the head to the new */   
    7711213                    mtbl->lru_first = index;                     
    7721214                } 
    7731215            } 
     1216            /* 3rd+ Memory Entry */ 
    7741217            else 
    7751218            { 
    776                 if(DBG)fprintf(out,"\trepairing previous LRU links and inserting record in LRU\n"); 
    777                 /*  repair links    */   
    778                 if((int16_t)mtbl->mem[index].lru_prev!=NIL) 
     1219                if(DBG)fprintf(out, "\trepairing previous LRU links and " 
     1220                                            "inserting record in LRU\n"); 
     1221                /* repair links */   
     1222                if((int16_t)mtbl->mem[index].lru_prev != NIL) 
    7791223                { 
    7801224                    mtbl->mem[mtbl->mem[index].lru_prev].lru_next =  
    7811225                        mtbl->mem[index].lru_next; 
    7821226                } 
    783                 if((int16_t)mtbl->mem[index].lru_next!=NIL) 
     1227                if((int16_t)mtbl->mem[index].lru_next != NIL) 
    7841228                { 
    7851229                    mtbl->mem[mtbl->mem[index].lru_next].lru_prev =      
    7861230                        mtbl->mem[index].lru_prev; 
    7871231                } 
    788                 /*  update nodes own link  */ 
     1232                /* update nodes own link */ 
    7891233                mtbl->mem[mtbl->lru_first].lru_prev = index;  
    7901234                mtbl->mem[index].lru_next = mtbl->lru_first; 
    7911235                mtbl->mem[index].lru_prev = NIL; 
    792             /*  Finally, establish this entry as the first on lru  */ 
     1236                /* Finally, establish this entry as the first on LRU list */ 
    7931237                mtbl->lru_first = index; 
    7941238            } 
    7951239} 
    7961240 
     1241/** Searches the ftbl for the mtbl with the most entries. 
     1242 * Returns the number of memory entries the max mtbl has. The double ptr  
     1243 * parameter is used to store a reference to the mtbl pointer with the most  
     1244 * memory entries.  
     1245 */ 
    7971246static int locate_max_mtbl(struct mem_table_s **mtbl) 
    7981247{ 
    799  
    8001248    if(DBG)fprintf(out, "locating mtbl with most entries...\n"); 
    8011249    struct file_table_s *ftbl = &(ucache->ftbl); 
    802     uint32_t index_of_max_blk; 
    803     uint16_t index_of_max_ent; 
     1250    uint32_t index_of_max_blk = NIL; 
     1251    uint16_t index_of_max_ent = NIL; 
    8041252    uint16_t value_of_max = 0; 
     1253    /* Iterate over file hash table indices */ 
    8051254    int i; 
    806     for(i=0;i<FILE_TABLE_HASH_MAX;i++) 
     1255    for(i = 0; i < FILE_TABLE_HASH_MAX; i++) 
    8071256    { 
    8081257        if(DBG)fprintf(out, "\texamining ftbl index %d\n", i); 
     1258        /* Iterate over hash table chain */ 
    8091259        int j; 
    810         for(j=i; !file_done(j); j=file_next(ftbl, j)) 
     1260        for(j = i; !file_done(j); j = file_next(ftbl, j)) 
    8111261        { 
    8121262            struct file_ent_s *fent = &(ftbl->file[j]); 
    813             if(DBG)fprintf(out, "\t(blk, ent)=(%d, %d)\n", fent->mtbl_blk,\ 
    814                 (int16_t)fent->mtbl_ent); 
    815             if((int32_t)fent->mtbl_blk==NIL || (int16_t)fent->mtbl_ent==NIL){ 
     1263            if(DBG)fprintf(out, "\t(blk, ent)=(%d, %d)\n", fent->mtbl_blk, 
     1264                                                    (int16_t)fent->mtbl_ent); 
     1265            //TODO: this might can be removed: test it 
     1266            if(((int32_t)fent->mtbl_blk == NIL) ||  
     1267                    ((int16_t)fent->mtbl_ent==NIL)) 
     1268            { 
    8161269                break; 
    8171270            } 
    818             struct mem_table_s *current_mtbl = &(ucache->b[fent->mtbl_blk].\ 
    819                 mtbl[fent->mtbl_ent]); 
    820             if(current_mtbl->num_blocks>value_of_max){ 
     1271            /* Examine the mtbl's value of num_blocks to see if it's the  
     1272             * greatest.  
     1273             */ 
     1274            struct mem_table_s *current_mtbl = &(ucache->b[fent->mtbl_blk]. 
     1275                                                        mtbl[fent->mtbl_ent]); 
     1276            if(current_mtbl->num_blocks > value_of_max) 
     1277            { 
    8211278                if(DBG)fprintf(out, "\tmax updated @ %d\n", j); 
    822                 *mtbl = current_mtbl;    
     1279                *mtbl = current_mtbl; /* Set the parameter to this mtbl */ 
    8231280                index_of_max_blk = fent->mtbl_blk; 
    8241281                index_of_max_ent = fent->mtbl_ent; 
     
    8301287} 
    8311288 
    832 static void evict_LRU(struct mem_table_s *mtbl) 
     1289/** Evicts the LRU memory entry from the tail (lru_last) of the provided  
     1290 * mtbl's LRU list. 
     1291 * Returns 1 on success; 0 on failure, meaning there was no lru 
     1292 */ 
     1293static int evict_LRU(struct mem_table_s *mtbl) 
    8331294{ 
    8341295    if(DBG)fprintf(out, "evicting LRU...\n"); 
    835     if(mtbl->num_blocks!=0) 
     1296    if(mtbl->num_blocks != 0) 
    8361297    { 
    8371298        remove_mem(mtbl, mtbl->mem[mtbl->lru_last].tag); 
     1299        return 1; 
    8381300    } 
    8391301    else 
    8401302    {   /*  Worst Case  */ 
    8411303        if(DBG)fprintf(out, "\tno LRU on this mtbl\n"); 
    842     } 
    843 } 
    844  
    845 /*  Set the block index where data is stored    */ 
     1304        return 0; 
     1305    } 
     1306} 
     1307 
     1308 
     1309/** Used to obtain a block for storage of data identified by the offset  
     1310 * parameter and maintained in the mtbl at the memory entry identified by the  
     1311 * index parameter. 
     1312 * 
     1313 * If a free block could be aquired, returns the memory address of the block  
     1314 * just inserted. Otherwise, returns NIL. 
     1315 */ 
    8461316static void *set_item(struct mem_table_s *mtbl,  
    8471317                    uint64_t offset,  
     
    8491319{    
    8501320        int16_t free_blk = get_free_blk(); 
    851         if(free_blk==NIL) 
     1321        /* No Free Blocks Available */ 
     1322        if(free_blk == NIL) 
    8521323        { 
    853             if(DBG)fprintf(out, "\tget_free_blk returned NIL, attempting removal of LRU\n"); 
    854             evict_LRU(mtbl); 
     1324            if(DBG)fprintf(out, "\tget_free_blk returned NIL, attempting " 
     1325                                                      "removal of LRU\n"); 
     1326            //TODO this probably wont work since we cannot evict a block that is current referenced 
     1327            evict_LRU(mtbl);  
    8551328            free_blk = get_free_blk(); 
    8561329        } 
    8571330         
    858         if(free_blk==NIL)    
     1331        /* After Eviction Routine - No Free Blocks Available, Evict from mtbl  
     1332         * with the most memory entries (and therefore blocks)  
     1333         */ 
     1334        if(free_blk == NIL)    
    8591335        { 
    860             /*  Evict block from mtbl with most memory entries  */ 
    8611336            struct mem_table_s *max_mtbl; 
    862             int num_blocks = locate_max_mtbl(&max_mtbl); 
    863             if(DBG)fprintf(out, "\tget_free_blk returned NIL, evicting a block from max mtbl which has %d entries\n",\ 
    864                 max_mtbl->num_blocks); 
     1337            locate_max_mtbl(&max_mtbl); 
     1338            if(DBG)fprintf(out, "\tget_free_blk returned NIL, evicting a block " 
     1339                  "from max mtbl which has %d entries\n", max_mtbl->num_blocks); 
    8651340            evict_LRU(max_mtbl); 
    8661341            free_blk = get_free_blk(); 
    8671342        } 
    868         if(free_blk!=NIL) 
    869         {   /*  got block   */ 
    870             /*  increment num_blocks used by this mtbl  */ 
     1343        /* A Free Block is Avaiable for Use */ 
     1344        if(free_blk != NIL) 
     1345        { 
    8711346            mtbl->num_blocks++; 
    8721347            update_lru(mtbl, index); 
    873             if(DBG)fprintf(out, "\tsuccessfully inserted memory entry @ blk: %d\n", (int16_t) free_blk); 
    874             /*  set item to block number    */ 
     1348            if(DBG)fprintf(out, "\tsuccessfully inserted memory entry @ blk: " 
     1349                                                  "%d\n", (int16_t) free_blk); 
     1350            /* set item to block number */ 
    8751351            mtbl->mem[index].tag = offset; 
    8761352            mtbl->mem[index].item = free_blk; 
    877             /*  add to dirty list  */ 
     1353            /* add block index to head of dirty list */ 
    8781354            if(DBG)fprintf(out, "\tadding memory entry to dirty list\n"); 
    8791355            mtbl->mem[index].dirty_next = mtbl->dirty_list; 
    8801356            mtbl->dirty_list = index; 
    881             /*  Return the address of the block where data is stored    */ 
     1357            /* Return the address of the block where data is stored */ 
    8821358            return (void *)&(ucache->b[free_blk]);  
    8831359        } 
    884 } 
    885  
     1360    return (void *)(NIL); 
     1361} 
     1362 
     1363/** Requests a location in memory to place the data identified by the mtbl and  
     1364 * offset parameters. Also inserts the necessary info into the mtbl. 
     1365 * 
     1366 */ 
    8861367static void *insert_mem(struct mem_table_s *mtbl, uint64_t offset) 
    8871368{ 
    8881369    if(DBG)fprintf(out, "trying to insert mem...\n"); 
    889     /*  index into mem hash table   */ 
     1370 
     1371    /* Index into mem hash table */ 
    8901372    unsigned int index = offset % MEM_TABLE_HASH_MAX; 
    891     if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n",\ 
    892         offset, index); 
     1373    if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n", 
     1374                                                  offset, index); 
     1375 
    8931376    struct mem_ent_s *current = &(mtbl->mem[index]); 
    894     /*  lookup first    */ 
     1377    /* Lookup first */ 
    8951378    void *returnValue = lookup_mem(mtbl, offset, NULL, NULL, NULL); 
    896     if((int)returnValue!=NIL) 
    897     { 
    898         if(DBG)fprintf(out, "\tblock for this offset already exists @ 0X%X",\ 
    899             (unsigned int)returnValue); 
     1379    if((int)returnValue != NIL) 
     1380    { 
     1381        if(DBG)fprintf(out, "\tblock for this offset already exists @ 0X%X", 
     1382                                                 (unsigned int)returnValue); 
     1383        /* Already exists in mtbl so just return a ptr to the blk */ 
    9001384        return returnValue; 
    9011385    } 
     1386 
     1387    /* Entry doesn't exist, insertion required */ 
    9021388    if(DBG)fprintf(out, "\tlookup returned NIL\n"); 
    903     if((int64_t)mtbl->mem[index].tag!=NIL) 
    904     {   /*  if head occupied, need to get free ment */ 
     1389    if((int64_t)mtbl->mem[index].tag != NIL) 
     1390    { 
     1391        /* If head occupied, need to get free ment */ 
    9051392        int mentIndex = get_free_ment(mtbl); 
    906         if(mentIndex==NIL) 
    907         {   /*  no free memory entry available */ 
     1393        if(mentIndex == NIL) 
     1394        {   /* No free ment available, so attempt eviction, and try again */ 
    9081395            if(DBG)fprintf(out, "\tno ment\n"); 
    9091396            evict_LRU(mtbl); 
    910             mentIndex = get_free_ment(mtbl);    /*  try to get ment again */ 
    911         } 
    912         if(mentIndex!=NIL) 
     1397            mentIndex = get_free_ment(mtbl); 
     1398        } 
     1399        /* Procede with memory insertion if eviction was successful */ 
     1400        if(mentIndex != NIL) 
    9131401        {    
    914             if(DBG)fprintf(out, "\tfound free memory entry @ index = %d\n",\ 
    915                 mentIndex); 
    916             /*  insert after head of chain */ 
     1402            if(DBG)fprintf(out, "\tfound free memory entry @ index = %d\n", 
     1403                                                                mentIndex); 
     1404            /* Insert directly after head of chain */ 
    9171405            uint16_t next_ment = current->next; 
    9181406            current->next = mentIndex; 
     
    9201408            return set_item(mtbl, offset, mentIndex);    
    9211409        } 
    922     } 
    923     else 
    924     {   /*  No need to iterate to next in chain, just use head  */ 
    925         return set_item(mtbl, offset, index);                    
    926     } 
    927 } 
    928  
     1410        /* Eviction Failed */ 
     1411        else 
     1412        { 
     1413            return (void *)NULL; 
     1414        } 
     1415    } 
     1416    /* Head vacant. No need to iterate to next in chain, just use head */ 
     1417    return set_item(mtbl, offset, index); 
     1418} 
     1419 
     1420/** Removes all table info regarding the block identified by the mtbl and 
     1421 * offset, provided the mtbl has a reference count of 0 and the entry exists.  
     1422 * 
     1423 * On success returns 1, on failure returns 0. 
     1424 * 
     1425 */ 
    9291426static int remove_mem(struct mem_table_s *mtbl, uint64_t offset) 
    9301427{ 
    9311428    if(DBG)fprintf(out, "trying to remove memory entry...\n"); 
    932     /*  some indexes    */ 
    933     int32_t item_index; 
    934     int16_t mem_ent_index; 
    935     int16_t mem_ent_prev_index; 
     1429    /* Some Indices */ 
     1430    uint32_t item_index = NIL; 
     1431    uint16_t mem_ent_index = NIL; 
     1432    uint16_t mem_ent_prev_index = NIL; 
     1433 
     1434 
     1435    /* Previous, Current, Next */ 
     1436    uint16_t p = NIL; 
     1437    uint16_t c = NIL; 
     1438    uint16_t n = NIL;    
     1439 
     1440    /* Check reference count */ 
     1441    if(mtbl->ref_cnt != 0) 
     1442    { 
     1443        if(DBG)fprintf(out, "removal failure: ref_cnt==%d\n", mtbl->ref_cnt); 
     1444        return 0; 
     1445    } 
    9361446    void *retValue = lookup_mem(mtbl, offset, &item_index, &mem_ent_index,  
    937         &mem_ent_prev_index); 
    938     /*  Verify we've recieved the necessary info    */ 
    939     if((int)retValue==NIL) 
    940     { 
    941         if(DBG)fprintf(out, "\tremoval failure: memory entry not found matching offset"); 
    942         return NIL; 
    943     } 
    944     /*  Remove from LRU */ 
    945         /*  update each of adjacent nodes' link */ 
    946     if((int16_t)mtbl->mem[mem_ent_index].lru_prev!=NIL) 
     1447                                                     &mem_ent_prev_index); 
     1448    /* Verify we've recieved the necessary info */ 
     1449    if((int)retValue == NIL) 
     1450    { 
     1451        if(DBG)fprintf(out, "\tremoval failure: memory entry not found " 
     1452                                                      "matching offset"); 
     1453        return 0; 
     1454    } 
     1455    /* Remove from LRU */ 
     1456    /* Update each of the adjacent nodes' link */ 
     1457    if((int16_t)mtbl->mem[mem_ent_index].lru_prev != NIL) 
    9471458    { 
    9481459        mtbl->mem[mtbl->mem[mem_ent_index].lru_prev].lru_next =  
    949             mtbl->mem[mem_ent_index].lru_next; 
    950     } 
    951     if((int16_t)mtbl->mem[mem_ent_index].lru_next!=NIL) 
     1460                             mtbl->mem[mem_ent_index].lru_next; 
     1461    } 
     1462    if((int16_t)mtbl->mem[mem_ent_index].lru_next != NIL) 
    9521463    { 
    9531464        mtbl->mem[mtbl->mem[mem_ent_index].lru_next].lru_prev =  
    954             mtbl->mem[mem_ent_index].lru_prev; 
    955     } 
    956     if(mem_ent_index==mtbl->lru_first) 
    957     {   /* is node the head */ 
     1465                             mtbl->mem[mem_ent_index].lru_prev; 
     1466    } 
     1467    if(mem_ent_index == mtbl->lru_first) 
     1468    {    
     1469        /* Is node the head? */ 
    9581470        mtbl->lru_first = mtbl->mem[mem_ent_index].lru_next;     
    9591471    } 
    960     if(mem_ent_index==mtbl->lru_last) 
    961     {   /* is node the tail */ 
     1472    if(mem_ent_index == mtbl->lru_last) 
     1473    {    
     1474        /* Is node the tail? */ 
    9621475        mtbl->lru_last = mtbl->mem[mem_ent_index].lru_prev; 
    9631476    } 
    964     /*  Remove from dirty list if Dirty */ 
     1477    /* Remove from dirty list if Dirty */ 
    9651478    if(DBG)fprintf(out, "\tremoving from dirty list\n"); 
    966     uint16_t p, c, n;   /*  Previous, Current, Next */ 
    967     p = NIL; 
     1479 
    9681480    c = mtbl->dirty_list; 
    9691481    n = mtbl->mem[c].dirty_next; 
    970     while(c!=mem_ent_index) 
    971     { 
    972         /*if(DBG)fprintf(out, "\tp: %d\tc: %d\tn: %d\n",  
    973             (int16_t)p, (int16_t)c, (int16_t)n);*/ 
     1482 
     1483    while(c != mem_ent_index) 
     1484    { 
    9741485        p = c; 
    9751486        c = n; 
    9761487        n = mtbl->mem[c].dirty_next; 
    977         if((int16_t)c == NIL)break; 
     1488        if((int16_t)c == NIL) 
     1489        { 
     1490                break; 
     1491        } 
    9781492    } 
    9791493    if((int16_t)c != NIL) 
    980     {   /*  if memory entry was located on the dirty_list   */ 
     1494    {    
     1495        /* If memory entry was located on the dirty_list */ 
    9811496        mtbl->mem[p].dirty_next = mtbl->mem[c].dirty_next; 
    9821497        mtbl->mem[c].dirty_next = NIL; 
    9831498    } 
    984     /*  add memory block back to free list */ 
     1499    /* Add memory block back to free list */ 
    9851500    put_free_blk(item_index); 
    986     /*  Repair link */ 
    987     if((int16_t)mem_ent_prev_index!=NIL) 
     1501    /* Repair link */ 
     1502    if((int16_t)mem_ent_prev_index != NIL) 
    9881503    { 
    9891504        mtbl->mem[mem_ent_prev_index].next = mtbl->mem[mem_ent_index].next; 
    9901505    } 
    991     /*  newly free mem entry becomes new head of free mem entry list if less  
    992         than hash table max */ 
     1506    /* Newly free mem entry becomes new head of free mem entry list if index  
     1507     * is less than hash table max  
     1508     */ 
    9931509    put_free_ment(mtbl, mem_ent_index); 
    9941510    mtbl->num_blocks--; 
     
    9981514 
    9991515/*  The following two functions are provided for error checking purposes. 
    1000  */ 
    10011516static void print_lru(struct mem_table_s *mtbl) 
    10021517{ 
     
    10251540    } 
    10261541} 
     1542 */ 
     1543 
    10271544/*  End of Internal Only Functions    */ 
    10281545 
  • branches/Orange-Branch/src/client/usrint/ucache.h

    r9001 r9012  
    11/*  
    2  * (C) 2011 Clemson University and The University of Chicago  
     2 * (C) 2011 Clemson University 
    33 * 
    44 * See COPYING in top-level directory. 
    55 */ 
    66 
    7 #ifndef UCACHE_INTERNAL_H 
    8 #define UCACHE_INTERNAL_H 
     7#ifndef UCACHE_H 
     8#define UCACHE_H 
     9 
     10#define UCACHE_ENABLED 
     11#define UCACHE_LOCKING_ENABLED 
    912 
    1013#include <stdio.h> 
     
    1215#include <stdint.h> 
    1316#include <semaphore.h> 
     17#include <pthread.h> 
    1418 
    1519/* The following includes may end up not being needed.  
     
    3640#define NIL (-1) 
    3741 
    38 #define DBG 0 
     42#define DBG 1 
    3943#define INTERNAL_TESTING 0 
     44 
     45 
     46#define LOCK_TYPE 0 /* 0 for Semaphore, 1 for Mutex, 2 for Spinlock */ 
     47#if LOCK_TYPE==0 
    4048#define ucache_lock_t sem_t 
     49#elif LOCK_TYPE==1 
     50#define ucache_lock_t pthread_mutex_t 
     51#elif LOCK_TYPE==2 
     52#define ucache_lock_t pthread_spinlock_t 
     53#endif 
    4154 
    4255typedef uint32_t PVFS_fs_id; 
     
    122135 
    123136/* externally visible API */ 
    124 extern void ucache_initialize(void); 
    125 extern int ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 
    126 extern void *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 
    127 extern void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 
    128 extern int ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 
    129 extern int ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 
    130 extern int ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 
     137void ucache_initialize(void); 
     138int ucache_open_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 
     139void *ucache_lookup(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 
     140void *ucache_insert(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 
     141int ucache_remove(PVFS_fs_id *fs_id, PVFS_object_ref *handle, uint64_t offset); 
     142int ucache_flush(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 
     143int ucache_close_file(PVFS_fs_id *fs_id, PVFS_object_ref *handle); 
     144void ucache_dec_ref_cnt(struct mem_table_s * mtbl); 
     145void ucache_inc_ref_cnt(struct mem_table_s * mtbl); 
     146void ucache_info( 
     147    FILE * out, 
     148    union user_cache_u * ucache,  
     149    ucache_lock_t * ucache_lock 
     150); 
    131151 
    132 /* Internal Only Function Declarations   */ 
    133     /*  Cache Locking Functions */ 
    134 static int ucache_lock_init(ucache_lock_t * lock); 
    135 static int ucache_lock_lock(ucache_lock_t * lock); 
    136 static int ucache_lock_unlock(ucache_lock_t * lock); 
    137 static int ucache_lock_getvalue(ucache_lock_t * lock, int *sval); 
    138 static int ucache_lock_destroy(ucache_lock_t * lock); 
    139  
    140     /*  Dirty List Iterator */ 
    141 static int dirty_done(uint16_t index); 
    142 static int dirty_next(struct mem_table_s *mtbl, uint16_t index); 
    143  
    144     /*  Memory Entry Chain Iterator */ 
    145 static int ment_done(int index); 
    146 static int ment_next(struct mem_table_s *mtbl, int index); 
    147  
    148     /*  File Entry Chain Iterator   */ 
    149 static int file_done(int index); 
    150 static int file_next(struct file_table_s *ftbl, int index); 
    151  
    152 static void add_free_mtbls(int blk); 
    153 static void init_memory_table(int blk, int ent); 
    154 static uint16_t get_free_blk(void); 
    155 static void put_free_blk(int blk); 
    156 static int get_free_fent(void); 
    157 static void put_free_fent(int fent); 
    158 static int get_free_ment(struct mem_table_s *mtbl); 
    159 static void put_free_ment(struct mem_table_s *mtbl, int ent); 
    160 static struct mem_table_s *lookup_file( 
    161     uint32_t fs_id,  
    162     uint64_t handle, 
    163     uint32_t *file_mtbl_blk,        /* Can be NULL if not desired   */ 
    164     uint16_t *file_mtbl_ent,        /* Can be NULL if not desired   */ 
    165     uint16_t *file_ent_index,   /* Can be NULL if not desired   */ 
    166     uint16_t *file_ent_prev_index   /* Can be NULL if not desired   */ 
    167 ); 
    168 static int get_next_free_mtbl(uint32_t *free_mtbl_blk, uint16_t *free_mtbl_ent); 
    169 static void remove_all_memory_entries(struct mem_table_s *mtbl); 
    170 static void put_free_mtbl(struct mem_table_s *mtbl, struct file_ent_s *file); 
    171 static void evict_file(unsigned int index); 
    172 static struct mem_table_s *insert_file(uint32_t fs_id, uint64_t handle); 
    173 static int remove_file(uint32_t fs_id, uint64_t handle); 
    174 static void *lookup_mem(struct mem_table_s *mtbl,  
    175                     uint64_t offset,  
    176                     uint32_t *item_index, 
    177                     uint16_t *mem_ent_index, 
    178                     uint16_t *mem_ent_prev_index 
    179 ); 
    180 static void update_lru(struct mem_table_s *mtbl, uint16_t index); 
    181 static int locate_max_mtbl(struct mem_table_s **mtbl); 
    182 static void evict_LRU(struct mem_table_s *mtbl); 
    183 static void *set_item(struct mem_table_s *mtbl,  
    184                     uint64_t offset,  
    185                     uint16_t index 
    186 ); 
    187 static void *insert_mem(struct mem_table_s *mtbl, uint64_t offset); 
    188 static int remove_mem(struct mem_table_s *mtbl, uint64_t offset); 
    189     /*  list printing functions */ 
    190 static void print_lru(struct mem_table_s *mtbl); 
    191 static void print_dirty(struct mem_table_s *mtbl); 
     152#if LOCK_TYPE==0 
     153int ucache_lock_getvalue(ucache_lock_t * lock, int *sval); 
     154#endif 
    192155/****************************************  End of Internal Only Functions    */ 
    193156#endif 
    194  
    195157/* 
    196158 * Local variables: