libsrc/multiloaf.cxx

Go to the documentation of this file.
00001 /**********************************************************************
00002  * Copyright 2002 Jeff Rush <jrush@taupro.com>
00003  * Original Copyright 1979-2002 Udanax.com
00004  *
00005  * This file is part of the Udanax xanalogical storage system.
00006  *
00007  * Udanax is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * Udanax is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with Udanax; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  **********************************************************************/
00021 
00030 /* Modification History:
00031  * $Log: multiloaf.cxx,v $
00032  * Revision 1.11  2004/09/11 13:59:21  jrush
00033  * Changed all fprintf's to stderr to use the Nana library L() macro.  Also
00034  * removed a 2-3 minor compiler warnings.
00035  *
00036  * Revision 1.10  2004/09/04 16:02:17  jrush
00037  * Added Doxygen headers before each and every function definition.
00038  *
00039  * Revision 1.9  2002/07/26 04:32:01  jrush
00040  * Replaced gerror() with assert()
00041  *
00042  * Revision 1.8  2002/05/28 04:22:29  jrush
00043  * Adjusted source files to comply with GPL licensing.
00044  *
00045  * Revision 1.7  2002/05/28 02:51:11  jrush
00046  * Made static any functions and global variables private to this source file
00047  * and commented out any unused functions.
00048  *
00049  * Revision 1.6  2002/04/13 13:09:40  jrush
00050  * Convert typedef of struct into just struct, for C++ style.
00051  *
00052  * Revision 1.5  2002/04/12 11:56:43  jrush
00053  * Reorganized include file layout, renamed xanadu.h to udanax.h and
00054  * typecontext/typecrumcontext to C++ class Context/CrumContext.
00055  *
00056  * Revision 1.4  2002/04/06 19:51:30  jrush
00057  * Renamed TRUE/FALSE constant use to the C++ standard of true/false.
00058  *
00059  * Revision 1.3  2002/04/06 15:01:17  jrush
00060  * Changed INT to just 'int'.
00061  *
00062  * Revision 1.2  2002/02/14 09:27:43  jrush
00063  * Cleaned up source:
00064  *
00065  * 1. ran thru the indent tool to achieve a standard look,
00066  * 2. added structured comments at top for use with DOxygen reporting
00067  *    as well as CVS keywords,
00068  * 3. fixed compiler warnings re ambiguous assign/compares,
00069  *    needed casts and unused/uninitialized variables,
00070  * 4. fixed funcs that didn't specify a return type,
00071  * 5. centralized prototypes in protos.h, removing incomplete ones,
00072  * 6. cleaned up use of bool/BOOLEAN type to suit C++ type,
00073  * 7. fixed initializer nesting in tumbler constants,
00074  * 8. renamed vars that conflict with C++ keywords (new, this),
00075  * 9. fixed global/extern confusion re some global vars.
00076  *
00077  */
00078 
00079 #include <stdlib.h>
00080 #include <memory.h>
00081 #include <sys/types.h>
00082 #include <netinet/in.h>
00083 #include "udanax.h"
00084 
00085 struct freediskconscell {
00086     freediskconscell  *next;
00087     freediskentry     *stuff;
00088 };
00089 
00090 #define SIZEOFFREEDISKBUCKET 50
00091 #define NUMBEROFFREEDISKBUCKETS (NUMBYTESINLOAF/SIZEOFFREEDISKBUCKET+1)
00092 static freediskconscell *fdorderedtable[NUMBEROFFREEDISKBUCKETS];
00093 
00094 #define FDHASHTABLESIZE 10000
00095   /* a random prime */
00096 #define FDHASHMULT 723754349
00097 
00098 static freediskconscell *fdhashtable[FDHASHTABLESIZE];
00099 
00107     static void
00108 dumpfreediskentry(
00109     freediskentry *ptr)
00110 {
00111 #ifndef DISTRIBUTION
00112     L("partialdiskblocknumber = %d freespaceinloaf = %d\n", ntohl(ptr->partialdiskblocknumber),
00113             ntohs(ptr->freespaceinloaf));
00114 #endif
00115 }
00116 
00124     static void
00125 dumpfdhashtable()
00126 {
00127 #ifndef DISTRIBUTION
00128     int i;
00129     freediskconscell *ptr;
00130 
00131     L("dumping fdhashtable\n");
00132     for (i = 0; i < FDHASHTABLESIZE; i++) {
00133         if (fdhashtable[i]) {
00134             L("hashtable[%d]\n ", i);
00135             for (ptr = fdhashtable[i]; ptr; ptr = ptr->next)
00136                 dumpfreediskentry(ptr->stuff);
00137         }
00138     }
00139     L("exiting dumping fdhashtable\n");
00140 #endif
00141 }
00142 
00150     static void
00151 dumpfdorderedtable()
00152 {
00153 #ifndef DISTRIBUTION
00154     int i;
00155     freediskconscell *ptr;
00156 
00157     L("dumping fdorderedtable\n");
00158     for (i = 0; i < NUMBEROFFREEDISKBUCKETS; i++) {
00159         if (fdorderedtable[i]) {
00160             L("fdorderedtable[%d] s = %d\n", i, (i + 1) * SIZEOFFREEDISKBUCKET);
00161             for (ptr = fdorderedtable[i]; ptr; ptr = ptr->next) {
00162                 dumpfreediskentry(ptr->stuff);
00163             }
00164         }
00165     }
00166     L("exiting dumping fdorderedtable\n");
00167 #endif
00168 }
00169 
00177     static void
00178 dumpincoretables()
00179 {
00180 #ifndef DISTRIBUTION
00181     dumpfdorderedtable();
00182     dumpfdhashtable();
00183 #endif
00184 }
00185 
00193     void
00194 initincorealloctables()
00195 {                                      /* since these tables are extern i.e. initialized, this routine is just a start 
00196                                         * at restartability */
00197     int i;
00198 
00199     for (i = 0; i < NUMBEROFFREEDISKBUCKETS; i++)
00200         fdorderedtable[i] = NULL;
00201 
00202     for (i = 0; i < FDHASHTABLESIZE; i++)
00203         fdhashtable[i] = NULL;
00204 }
00205 
00213     void
00214 savepartialdiskalloctabletodisk()
00215 {
00216     freediskarray loaf;
00217     int blocknumber, i;
00218     int bucket;
00219     freediskconscell *ptr;
00220     typediskloafptr diskalloc(), dl;
00221 
00222     bucket = 0;
00223     ptr = fdorderedtable[bucket];
00224     blocknumber = PARTIALFREEDISKLOCATION;
00225     for (i = 0;; i++, ptr = ptr->next) {
00226         for (; ptr == 0;) {
00227             bucket++;
00228             if (bucket >= NUMBEROFFREEDISKBUCKETS) {
00229 /* goto endofbuckets; */
00230                 loaf.numberofentrysinthisblock = htonl(i);
00231                 loaf.nextdiskblocknumber = 0;
00232                 actuallywriteloaf((typeuberrawdiskloaf *) & loaf, blocknumber);
00233                 return;
00234             }
00235             ptr = fdorderedtable[bucket];
00236         }
00237         loaf.freeentryarray[i] = *(ptr->stuff);
00238         if (i >= (int) NFREEENTRYS - 1) {
00239             dl = diskalloc();
00240             loaf.nextdiskblocknumber = htonl(dl.diskblocknumber);
00241             loaf.numberofentrysinthisblock = htonl(NFREEENTRYS);
00242             actuallywriteloaf((typeuberrawdiskloaf *) & loaf, blocknumber);
00243             i = 0;
00244             blocknumber = dl.diskblocknumber;
00245         }
00246     }
00247 }
00248 
00256     static int
00257 fdhash(
00258     int diskblocknumber)
00259 {
00260     return abs(diskblocknumber * FDHASHMULT) % FDHASHTABLESIZE;
00261 }
00262 
00270     static void
00271 addtofreediskstructures(
00272     freediskentry *diskentry)
00273 {
00274     freediskconscell *newcons;
00275     freediskentry *newde;
00276     int i;
00277 
00278 /* L("entering addtofreediskstructures\n"); */
00279 /* dumpincoretables(); */
00280     newde = (freediskentry *) malloc(sizeof(freediskentry));
00281     newcons = (freediskconscell *) malloc(sizeof(freediskconscell));
00282     newcons->stuff = newde;
00283     *newde = *diskentry;
00284     i = ntohs(diskentry->freespaceinloaf) / SIZEOFFREEDISKBUCKET;
00285 /* L("orderedtable i = %d\n",i); */
00286     newcons->next = fdorderedtable[i];
00287     fdorderedtable[i] = newcons;
00288 
00289     newcons = (freediskconscell *) malloc(sizeof(freediskconscell));
00290     newcons->stuff = newde;
00291     i = fdhash(ntohl(diskentry->partialdiskblocknumber));
00292 /* L("hashtable i = %d\n",i); */
00293     newcons->next = fdhashtable[i];
00294     fdhashtable[i] = newcons;
00295 
00296 /* dumpincoretables(); */
00297 /* L("exiting addtofreediskstructures\n"); */
00298 }
00299 
00307     void
00308 readpartialdiskalloctablefromdisk()
00309 {
00310     int first = true;
00311 
00312     freediskarray loaf;
00313     int blocknumber;
00314     for (blocknumber = PARTIALFREEDISKLOCATION; blocknumber; blocknumber = ntohl(loaf.nextdiskblocknumber)) {
00315         /* L("readpartialdiskalloctablefromdisk reading block# %d\n",blocknumber); */
00316 
00317         actuallyreadrawloaf((typeuberrawdiskloaf *) &loaf, blocknumber);
00318         if (!first)
00319             diskfree(blocknumber);
00320 
00321         first = false;
00322         if (ntohl(loaf.numberofentrysinthisblock) > NFREEENTRYS)
00323             assert(0); // numberofentrysinthisblock too big!
00324 
00325         int i;
00326         for (i = 0; i < (int) ntohl(loaf.numberofentrysinthisblock); i++)
00327             addtofreediskstructures(&(loaf.freeentryarray[i]));
00328     }
00329 }
00330 
00338     void
00339 addallocatedloaftopartialallocedtables(
00340     typediskloafptr dp,
00341     int             size)
00342 {
00343     freediskentry stuff;
00344 
00345 /* L("addallocatedloaftopartialallocedtables entering\n"); */
00346     stuff.partialdiskblocknumber = htonl(dp.diskblocknumber);
00347     stuff.freespaceinloaf = htons(sizeof(typeuberrawdiskloaf) - size - SIZEOFUBERDISKHEADER);
00348     addtofreediskstructures(&stuff);
00349 /* L("addallocatedloaftopartialallocedtables exiting\n"); */
00350 }
00351 
00352 #define BESTFIT
00353 #ifdef BESTFIT
00354 
00361     static freediskentry *
00362 findfreeenoughloafinbucket(
00363     int size)
00364 {
00365     int i;
00366     freediskconscell *ptr;
00367 
00368     for (i = size / SIZEOFFREEDISKBUCKET + 1; i < (int) NUMBEROFFREEDISKBUCKETS; i++) {
00369         for (ptr = fdorderedtable[i]; ptr; ptr->next) {
00370             if ((int) ntohs(ptr->stuff->freespaceinloaf) >= size)
00371                 return ptr->stuff;
00372         }
00373     }
00374     return NULL;
00375 }
00376 #else                                  /* worst fit */
00377 
00384     static freediskentry *
00385 findfreeenoughloafinbucket(
00386     int size)
00387 {
00388     int i;
00389     freediskconscell *ptr;
00390 
00391     for (i = NUMBEROFFREEDISKBUCKETS - 1; i >= size / SIZEOFFREEDISKBUCKET; i--) {
00392         for (ptr = fdorderedtable[i]; ptr; ptr = ptr->next) {
00393             if (ntohs(ptr->stuff->freespaceinloaf) >= size)
00394                 return ptr->stuff;
00395         }
00396     }
00397     return NULL;
00398 }
00399 #endif
00400 
00408     static void
00409 changefreediskstructures(
00410     freediskentry *diskentry,
00411     int            newsize)
00412 {
00413     int temp;
00414     freediskconscell *ptr, *newptr = NULL, *oldptr;
00415 
00416 /* first change hash table */
00417 /* L("entering changefreediskstructures-----------------\n"); */
00418 /* dumpfdhashtable(); */
00419     temp = fdhash(ntohl(diskentry->partialdiskblocknumber));
00420     oldptr = 0;
00421     for (ptr = fdhashtable[temp]; ptr; ptr = ptr->next) {
00422         if (ptr->stuff->partialdiskblocknumber == diskentry->partialdiskblocknumber) {
00423             newptr = ptr;
00424             break;
00425         }
00426         oldptr = ptr;
00427     }
00428 
00429     if (oldptr == newptr)
00430         assert(0); // in hashfromdiskblock not found
00431 
00432     if (oldptr == 0) {
00433         fdhashtable[temp] = newptr->next;
00434     } else {
00435         oldptr->next = newptr->next;
00436     }
00437 /* next change ordered table */
00438 /* dumpfdhashtable(); */
00439 /* L(" I changefreediskstructures---------------\n"); */
00440 /* dumpfdorderedtable(); */
00441     temp = ntohs(diskentry->freespaceinloaf) / SIZEOFFREEDISKBUCKET;
00442     oldptr = 0;
00443     for (ptr = fdorderedtable[temp]; ptr; ptr = ptr->next) {
00444         if (ptr->stuff->partialdiskblocknumber == diskentry->partialdiskblocknumber) {
00445             newptr = ptr;
00446             break;
00447         }
00448         oldptr = ptr;
00449     }
00450     if (oldptr == 0) {
00451         fdorderedtable[temp] = newptr->next;
00452     } else {
00453         oldptr->next = newptr->next;
00454     }
00455 /* last change size in entry */
00456     newptr->stuff->freespaceinloaf = htons(newsize);
00457     addtofreediskstructures(newptr->stuff);     /* just call standard routine */
00458 /* then delete stuff left lying around do this more efficiently later */
00459     free((char *)newptr->stuff);
00460     free((char *)newptr);
00461 /* dumpfdorderedtable(); */
00462 /* L(" X changefreediskstructures++++++++++++++++++++\n"); */
00463 }
00464 
00472     static int
00473 findandallocateinsidediskblocknumber(
00474     int               diskblocknumber,
00475     int               size,
00476     typeuberdiskloaf *loafp)
00477 {
00478     char *lp;
00479     int number;
00480     int i;
00481     int temp;
00482     short loaftemp;
00483 
00484 /* L("entering findandallocateinsidediskblocknumber\n"); */
00485     lp = /* (char * *)&loafp->fakepartialuberloaf; */ (char *)loafp + 6;
00486 /* zzz 1999** */
00487     number = ntohs(loafp->numberofunterloafs);
00488     for (i = 0; i < number; i++) {
00489         temp = intof((humber) lp);
00490         lp += temp;
00491     }
00492 /* L("2temp = %d lp = %x loafp = %x i = %d n = %d size = %d \n",temp,lp,loafp,i,0,size);
00493  * L("lp - loafp = %d ",lp-(char*)loafp); */
00494     loaftemp = ntohs(loafp->numberofunterloafs) + 1;
00495     loafp->numberofunterloafs = htons(loaftemp);
00496     temp = sizeof(typeuberrawdiskloaf) - (lp - (char *)loafp) - size;
00497 #ifndef DISTRIBUTION
00498     if (temp < 0) {
00499         dumphexstuff(lp);
00500         dumphexstuff((char *) loafp);
00501         L("2temp = %d lp = %x loafp = %x i = %d  size = %d \n", temp, (int) lp, (int) loafp, i, size);
00502         L("lp - loafp = %d ", lp - (char *)loafp);
00503         L("expression = %d diskblocknumber = %d number = %d\n", temp, diskblocknumber, number);
00504         dumpincoretables();
00505         assert(0); // expression negative in findandallocateinsidediskblocknumber
00506         L("expression negative in findandallocateinsidediskblocknumber");
00507         return i;
00508     }
00509 #endif
00510     movmem(lp, lp + size, sizeof(typeuberrawdiskloaf) - (lp - (char *)loafp) - size);
00511 /* L(" B findandallocateinsidediskblocknumber\n"); */
00512 /* dumphexstuff(loafp); */
00513     return i;
00514 }
00515 
00523     typediskloafptr
00524 partialdiskalloc(
00525     int  size,
00526     int *newloafp)
00527 {
00528     freediskentry diskentry, *freeentry;
00529     typediskloafptr dlp;
00530     typeuberdiskloaf loaf;
00531 
00532 #ifndef DISTRIBUTION
00533     if (size != 1010 && size > 990) {
00534         L("partialdiskalloc size = %d\n", size);
00535     }
00536 #endif
00537     freeentry = findfreeenoughloafinbucket(size);
00538 /* L("partialdiskalloc freeentry = %x\n",freeentry); */
00539     if (!freeentry) {
00540         dlp = diskalloc();
00541         dlp.insidediskblocknumber = 0 /* 1 */ ;
00542         diskentry.partialdiskblocknumber = htonl(dlp.diskblocknumber);
00543         diskentry.freespaceinloaf = htons(NUMBYTESINLOAF - size - SIZEOFUBERDISKHEADER);
00544         addtofreediskstructures(&diskentry);
00545 /* L("partialdiskblock returning true with diskblocknumber = %d\n",dlp.diskblocknumber); */
00546         *newloafp = true;
00547         return dlp;
00548     } else {
00549         if (size >= ntohs(freeentry->freespaceinloaf)) {
00550             dumpincoretables();
00551 #ifndef DISTRIBUTION
00552             L("size = %d number = %d\n ", size, ntohl(freeentry->partialdiskblocknumber));
00553             assert(0); // partialdiskalloc  found loaf too small
00554 #else
00555             assert(0);
00556 #endif
00557         }
00558         dlp.diskblocknumber = ntohl(freeentry->partialdiskblocknumber);
00559         actuallyreadrawloaf((typeuberrawdiskloaf *) & loaf, ntohl(freeentry->partialdiskblocknumber));
00560         dlp.insidediskblocknumber = findandallocateinsidediskblocknumber(dlp.diskblocknumber, size, &loaf);
00561 
00562         if (dlp.insidediskblocknumber > 100)
00563             assert(0); // partialdiskalloc insidediskblocknumber >100
00564 
00565         changefreediskstructures(freeentry, (int) (ntohs(freeentry->freespaceinloaf) - size));
00566         *newloafp = false;
00567 /* L("leaving partialdiskalloc o\n"); */
00568         return dlp;
00569     }
00570 }
00571 
00579     int
00580 numberofliveunterloafs(
00581     typeuberdiskloaf *loafp)
00582 {
00583     char *lp;
00584     unsigned int number, n;
00585     int i;
00586     int ret;
00587     unsigned int temp;
00588 
00589     ret = 0;
00590     lp = /* (char *)&loafp->fakepartialuberloaf; */ (char *)loafp + 6;
00591     number = ntohs(loafp->numberofunterloafs);
00592     for (i = 0; i < (int) number; i++) {
00593         n = lengthof((humber) /* loafp */ lp);  /* ECH 8-29-88 */
00594         temp = intof((humber) lp);
00595         if (n >= temp) {
00596             lp += n;
00597         } else {
00598             lp += temp;
00599         }
00600         if (n != temp) {
00601             ret++;
00602         }
00603     }
00604     return ret;
00605 }
00606 
00614     char *
00615 findinsideloaf(
00616     typeuberdiskloaf *loafp,
00617     int               ninsideloaf)
00618 {
00619     char *lp;
00620     unsigned int number, n;
00621     int i;
00622     unsigned int temp;
00623 
00624 /* L("findinsideloaf ninsideloaf = %x \n",ninsideloaf); */
00625 /* L("findinsideloaf loafp = %x \n",loafp); */
00626 /* L("findinsideloaf lp = %x \n",lp); */
00627     lp = /* (char *)&loafp->fakepartialuberloaf; */ (char *)loafp + 6;
00628 
00629     number = ntohs(loafp->numberofunterloafs);
00630 /* L("findinsideloaf number = %x \n",number); */
00631     for (i = 0; i < (int) number; i++) {
00632         n = lengthof((humber) loafp);
00633 /* L("findinsideloaf n = %x \n",n); */
00634         if (i == ninsideloaf) {
00635 /* L("findinsideloaf returning lp = %x \n",lp); */
00636             return lp;
00637         }
00638         temp = intof((humber) lp);
00639         if (n >= temp) {
00640             lp += n;
00641         } else {
00642             lp += temp;
00643         }
00644     }
00645 /* L("findinsideloaf returningNULL substitute\n"); */
00646     return lp;
00647 }

Generated on Sun Aug 21 04:18:14 2005 for Udanax-Green by doxygen1.3.4