dirCache.c

Go to the documentation of this file.
00001 #include "sysincludes.h"
00002 #include "vfat.h"
00003 #include "dirCache.h"
00004 
00005 
00006 void myfree(void *a)
00007 {
00008         free(a);
00009 }
00010 
00011 #define free myfree
00012 
00013 
00014 #define BITS_PER_INT (sizeof(unsigned int) * 8)
00015 
00016 
00017 static inline unsigned int rol(unsigned int arg, int shift)
00018 {
00019         arg &= 0xffffffff; /* for 64 bit machines */
00020         return (arg << shift) | (arg >> (32 - shift));
00021 }
00022 
00023 
00024 static int calcHash(char *name)
00025 {
00026         unsigned long hash;
00027         int i;
00028         unsigned char c;
00029 
00030         hash = 0;
00031         i = 0;
00032         while(*name) {
00033                 /* rotate it */
00034                 hash = rol(hash,5); /* a shift of 5 makes sure we spread quickly
00035                                      * over the whole width, moreover, 5 is
00036                                      * prime with 32, which makes sure that
00037                                      * successive letters cannot cover each 
00038                                      * other easily */
00039                 c = toupper(*name);
00040                 hash ^=  (c * (c+2)) ^ (i * (i+2));
00041                 hash &= 0xffffffff;
00042                 i++, name++;
00043         }
00044         hash = hash * (hash + 2);
00045         /* the following two xors make sure all info is spread evenly over all
00046          * bytes. Important if we only keep the low order bits later on */
00047         hash ^= (hash & 0xfff) << 12;
00048         hash ^= (hash & 0xff000) << 24;
00049         return hash;
00050 }
00051 
00052 static int addBit(unsigned int *bitmap, int hash, int checkOnly)
00053 {
00054         int bit, entry;
00055 
00056         bit = 1 << (hash % BITS_PER_INT);
00057         entry = (hash / BITS_PER_INT) % DC_BITMAP_SIZE;
00058         
00059         if(checkOnly)
00060                 return bitmap[entry] & bit;
00061         else {
00062                 bitmap[entry] |= bit;
00063                 return 1;
00064         }
00065 }
00066 
00067 static int _addHash(dirCache_t *cache, unsigned int hash, int checkOnly)
00068 {
00069         return
00070                 addBit(cache->bm0, hash, checkOnly) &&
00071                 addBit(cache->bm1, rol(hash,12), checkOnly) &&
00072                 addBit(cache->bm2, rol(hash,24), checkOnly);
00073 }
00074 
00075 
00076 static void addNameToHash(dirCache_t *cache, char *name)
00077 {       
00078         _addHash(cache, calcHash(name), 0);
00079 }
00080 
00081 static void hashDce(dirCache_t *cache, dirCacheEntry_t *dce)
00082 {
00083         if(dce->beginSlot != cache->nrHashed)
00084                 return;
00085         cache->nrHashed = dce->endSlot;
00086         if(dce->longName)
00087                 addNameToHash(cache, dce->longName);
00088         addNameToHash(cache, dce->shortName);
00089 }
00090 
00091 int isHashed(dirCache_t *cache, char *name)
00092 {
00093         int ret;
00094 
00095         ret =  _addHash(cache, calcHash(name), 1);
00096         return ret;
00097 }
00098 
00099 void checkXYZ(dirCache_t *cache)
00100 {
00101         if(cache->entries[2])
00102                 printf(" at 2 = %d\n", cache->entries[2]->beginSlot);
00103 }
00104 
00105 
00106 int growDirCache(dirCache_t *cache, int slot)
00107 {
00108         if(slot < 0) {
00109                 fprintf(stderr, "Bad slot %d\n", slot);
00110                 exit(1);
00111         }
00112 
00113         if( cache->nr_entries <= slot) {
00114                 int i;
00115                 
00116                 cache->entries = realloc(cache->entries,
00117                                          (slot+1) * 2 * 
00118                                          sizeof(dirCacheEntry_t *));
00119                 if(!cache->entries)
00120                         return -1;
00121                 for(i= cache->nr_entries; i < (slot+1) * 2; i++) {
00122                         cache->entries[i] = 0;
00123                 }
00124                 cache->nr_entries = (slot+1) * 2;
00125         }
00126         return 0;
00127 }
00128 
00129 dirCache_t *allocDirCache(Stream_t *Stream, int slot)
00130 {       
00131         dirCache_t **dcp;
00132 
00133         if(slot < 0) {
00134                 fprintf(stderr, "Bad slot %d\n", slot);
00135                 exit(1);
00136         }
00137 
00138         dcp = getDirCacheP(Stream);
00139         if(!*dcp) {
00140                 *dcp = New(dirCache_t);
00141                 if(!*dcp)
00142                         return 0;
00143                 (*dcp)->entries = NewArray((slot+1)*2+5, dirCacheEntry_t *);
00144                 if(!(*dcp)->entries) {
00145                         free(*dcp);
00146                         return 0;
00147                 }
00148                 (*dcp)->nr_entries = (slot+1) * 2;
00149                 memset( (*dcp)->bm0, 0, DC_BITMAP_SIZE);
00150                 memset( (*dcp)->bm1, 0, DC_BITMAP_SIZE);
00151                 memset( (*dcp)->bm2, 0, DC_BITMAP_SIZE);
00152                 (*dcp)->nrHashed = 0;
00153         } else
00154                 if(growDirCache(*dcp, slot) < 0)
00155                         return 0;
00156         return *dcp;
00157 }
00158 
00159 static void freeDirCacheRange(dirCache_t *cache, int beginSlot, int endSlot)
00160 {
00161         dirCacheEntry_t *entry;
00162         int clearBegin;
00163         int clearEnd;
00164         int i;
00165 
00166         if(endSlot < beginSlot) {
00167                 fprintf(stderr, "Bad slots %d %d in free range\n", 
00168                         beginSlot, endSlot);
00169                 exit(1);
00170         }
00171 
00172         while(beginSlot < endSlot) {
00173                 entry = cache->entries[beginSlot];
00174                 if(!entry) {
00175                         beginSlot++;
00176                         continue;
00177                 }
00178                 
00179                 clearEnd = entry->endSlot;
00180                 if(clearEnd > endSlot)
00181                         clearEnd = endSlot;
00182                 clearBegin = beginSlot;
00183                 
00184                 for(i = clearBegin; i <clearEnd; i++)
00185                         cache->entries[i] = 0;
00186 
00187                 if(entry->endSlot == endSlot)
00188                         entry->endSlot = beginSlot;
00189                 else if(entry->beginSlot == beginSlot)
00190                         entry->beginSlot = endSlot;
00191                 else {
00192                         fprintf(stderr, 
00193                                 "Internal error, non contiguous de-allocation\n");
00194                         fprintf(stderr, "%d %d\n", beginSlot, endSlot);
00195                         fprintf(stderr, "%d %d\n", entry->beginSlot, 
00196                                 entry->endSlot);
00197                         exit(1);                        
00198                 }
00199 
00200                 if(entry->beginSlot == entry->endSlot) {
00201                         if(entry->longName)
00202                                 free(entry->longName);
00203                         if(entry->shortName)
00204                                 free(entry->shortName);
00205                         free(entry);
00206                 }
00207 
00208                 beginSlot = clearEnd;
00209         }
00210 }
00211 
00212 static dirCacheEntry_t *allocDirCacheEntry(dirCache_t *cache, int beginSlot, 
00213                                            int endSlot,
00214                                            dirCacheEntryType_t type)
00215 {
00216         dirCacheEntry_t *entry;
00217         int i;
00218 
00219         if(growDirCache(cache, endSlot) < 0)
00220                 return 0;
00221 
00222         entry = New(dirCacheEntry_t);
00223         if(!entry)
00224                 return 0;
00225         entry->type = type;
00226         entry->longName = 0;
00227         entry->shortName = 0;
00228         entry->beginSlot = beginSlot;
00229         entry->endSlot = endSlot;
00230 
00231         freeDirCacheRange(cache, beginSlot, endSlot);
00232         for(i=beginSlot; i<endSlot; i++) {
00233                 cache->entries[i] = entry;
00234         }
00235         return entry;
00236 }
00237 
00238 dirCacheEntry_t *addUsedEntry(dirCache_t *cache, int beginSlot, int endSlot, 
00239                               char *longName, char *shortName,
00240                               struct directory *dir)
00241 {
00242         dirCacheEntry_t *entry;
00243 
00244         if(endSlot < beginSlot) {
00245                 fprintf(stderr, 
00246                         "Bad slots %d %d in add used entry\n", 
00247                         beginSlot, endSlot);
00248                 exit(1);
00249         }
00250 
00251 
00252         entry = allocDirCacheEntry(cache, beginSlot, endSlot, DCET_USED);
00253         if(!entry)
00254                 return 0;
00255         
00256         entry->beginSlot = beginSlot;
00257         entry->endSlot = endSlot;
00258         if(longName)
00259                 entry->longName = strdup(longName);
00260         entry->shortName = strdup(shortName);
00261         entry->dir = *dir;
00262         hashDce(cache, entry);
00263         return entry;
00264 }
00265 
00266 static void mergeFreeSlots(dirCache_t *cache, int slot)
00267 {
00268         dirCacheEntry_t *previous, *next;
00269         int i;
00270 
00271         if(slot == 0)
00272                 return;
00273         previous = cache->entries[slot-1];
00274         next = cache->entries[slot];
00275         if(next && next->type == DCET_FREE &&
00276            previous && previous->type == DCET_FREE) {
00277                 for(i=next->beginSlot; i < next->endSlot; i++)
00278                         cache->entries[i] = previous;
00279                 previous->endSlot = next->endSlot;
00280                 free(next);             
00281         }
00282 }
00283 
00284 dirCacheEntry_t *addFreeEntry(dirCache_t *cache, int beginSlot, int endSlot)
00285 {
00286         dirCacheEntry_t *entry;
00287 
00288         if(beginSlot < cache->nrHashed)
00289                 cache->nrHashed = beginSlot;
00290 
00291         if(endSlot < beginSlot) {
00292                 fprintf(stderr, "Bad slots %d %d in add free entry\n", 
00293                         beginSlot, endSlot);
00294                 exit(1);
00295         }
00296 
00297         if(endSlot == beginSlot)
00298                 return 0;
00299         entry = allocDirCacheEntry(cache, beginSlot, endSlot, DCET_FREE);
00300         mergeFreeSlots(cache, beginSlot);
00301         mergeFreeSlots(cache, endSlot);
00302         return cache->entries[beginSlot];
00303 }
00304 
00305 
00306 dirCacheEntry_t *addEndEntry(dirCache_t *cache, int pos)
00307 {
00308         return allocDirCacheEntry(cache, pos, pos+1, DCET_END);
00309 }
00310 
00311 dirCacheEntry_t *lookupInDircache(dirCache_t *cache, int pos)
00312 {
00313         if(growDirCache(cache, pos+1) < 0)
00314                 return 0;
00315         return cache->entries[pos];     
00316 }
00317 
00318 void freeDirCache(Stream_t *Stream)
00319 {
00320         dirCache_t *cache, **dcp;
00321 
00322         dcp = getDirCacheP(Stream);
00323         cache = *dcp;
00324         if(cache) {
00325                 freeDirCacheRange(cache, 0, cache->nr_entries);
00326                 free(cache);
00327                 *dcp = 0;
00328         }
00329 }

Generated on Fri Apr 14 22:56:55 2006 for minix by  doxygen 1.4.6