libsrc/corediskout.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: corediskout.cxx,v $
00032  * Revision 1.12  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.11  2004/09/04 16:02:17  jrush
00037  * Added Doxygen headers before each and every function definition.
00038  *
00039  * Revision 1.10  2004/08/28 13:57:00  jrush
00040  * Further syncing of local copies to CVS; builds but I haven't run it yet.
00041  *
00042  * Revision 1.9  2002/07/26 04:30:29  jrush
00043  * Replaced gerror() with assert()
00044  *
00045  * Revision 1.8  2002/05/28 04:22:29  jrush
00046  * Adjusted source files to comply with GPL licensing.
00047  *
00048  * Revision 1.7  2002/05/28 02:49:42  jrush
00049  * Made static any functions and global variables private to this source file
00050  * and commented out any unused functions.
00051  *
00052  * Revision 1.6  2002/04/12 11:56:42  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.5  2002/04/06 19:51:30  jrush
00057  * Renamed TRUE/FALSE constant use to the C++ standard of true/false.
00058  *
00059  * Revision 1.4  2002/04/06 17:05:57  jrush
00060  * Switched from referring to 'task' for a client connection to 'session',
00061  * and converted the typetask typedef/struct into a Session C++ class.
00062  *
00063  * Revision 1.3  2002/04/06 15:01:17  jrush
00064  * Changed INT to just 'int'.
00065  *
00066  * Revision 1.2  2002/02/14 09:27:43  jrush
00067  * Cleaned up source:
00068  *
00069  * 1. ran thru the indent tool to achieve a standard look,
00070  * 2. added structured comments at top for use with DOxygen reporting
00071  *    as well as CVS keywords,
00072  * 3. fixed compiler warnings re ambiguous assign/compares,
00073  *    needed casts and unused/uninitialized variables,
00074  * 4. fixed funcs that didn't specify a return type,
00075  * 5. centralized prototypes in protos.h, removing incomplete ones,
00076  * 6. cleaned up use of bool/BOOLEAN type to suit C++ type,
00077  * 7. fixed initializer nesting in tumbler constants,
00078  * 8. renamed vars that conflict with C++ keywords (new, this),
00079  * 9. fixed global/extern confusion re some global vars.
00080  *
00081  */
00082 
00083 #include <memory.h>
00084 #include <stdlib.h>
00085 #include "udanax.h"
00086 
00087 extern int noishouldbother;
00088 extern int notakenephewnd;
00089 extern int noeatbrosnd;
00090 
00091 typegranf granf;
00092 typespanf spanf;
00093 
00094 typediskloaf zzzeroloaf;
00095 typeuberdiskloaf zzzerouberloaf;
00096 
00097 static void subtreewriterecurs(Session *sess, typecuc *father);
00098 static void orglwritepart2(Session *sess, typecbc *orglcbcptr);
00099 
00100 extern bool decrementusers(); //FIXME: remove ref to function in server/ backends
00101 
00109 /* make sure file is up to date when exitting program */
00110     static void
00111 indiskexit()
00112 {
00113     if (decrementusers())
00114         return;
00115 
00116     writeenfilades();
00117     closediskfile();
00118 
00119     exit(0);
00120 }
00121 
00129     void
00130 diskexit()
00131 {
00132     indiskexit();
00133 }
00134 
00142 /* Update disk copy of all enfilades, and reset core versions for multiuser */
00143     void
00144 diskflush()
00145 {
00146     writeenfilades();
00147     initkluge((typecuc **) &granf, (typecuc **) &spanf);
00148 }
00149 
00157 /* Write entire granfilade and spanfilade to disk and flag as unmodified in core */
00158     void
00159 writeenfilades()
00160 {
00161     L("entering writeenfilades()\n");
00162 
00163     typecbc temporgl;
00164 
00165     temporgl.leftbroorfather                                             = NULL;
00166     temporgl.modified                                                    = true;
00167     temporgl.cinfo.granstuff.orglstuff.orglincore                        = true;
00168     temporgl.cinfo.granstuff.orglstuff.diskorglptr.diskblocknumber       = GRANFDISKLOCATION;
00169     temporgl.cinfo.granstuff.orglstuff.diskorglptr.insidediskblocknumber = 0;
00170     temporgl.cinfo.granstuff.orglstuff.orglptr                           = (typecuc *) granf;
00171     ((typecuc *) granf)->leftbroorfather                                 = (typecorecrum *) &temporgl;
00172 
00173     L("about to orglwrite() GRANF\n");
00174     orglwrite(&temporgl);
00175     L("returned from orglwrite() GRANF\n");
00176 
00177     temporgl.modified                                                    = true;
00178     temporgl.cinfo.granstuff.orglstuff.orglincore                        = true;
00179     temporgl.cinfo.granstuff.orglstuff.diskorglptr.diskblocknumber       = SPANFDISKLOCATION;
00180     temporgl.cinfo.granstuff.orglstuff.diskorglptr.insidediskblocknumber = 0;
00181     temporgl.cinfo.granstuff.orglstuff.orglptr                           = (typecuc *) spanf;
00182     ((typecuc *) spanf)->leftbroorfather                                 = (typecorecrum *) &temporgl;
00183 
00184     L("about to orglwrite() SPANF\n");
00185     orglwrite(&temporgl);
00186     L("returned from orglwrite() SPANF\n");
00187 
00188     L("leaving writeenfilades()\n");
00189 }
00190 
00191 #define hputinloaf(hp,lp,tp) ((void)humberput((int)(hp),(humber)(lp),(unsigned int *)(tp)),(lp)=((char*)lp)+*(tp))
00192 /* #define hputwisp(wp,lp,tp)
00193  * ((tp)=tumblerfixedtoptr((lp),&(wp.dsas[0])),((char*)lp)+=(tp),(tp)=tumblerfixedtoptr((lp),&(wp.dsas[1])),((char
00194  * *)lp)+=(tp)) */
00195 
00203     static void
00204 hputwiddsp(
00205     typecuc  *ptr,
00206     char    **loafptrptr)
00207 {
00208     unsigned int temp;
00209 
00210     int nstreams = widsize(ptr->cenftype);
00211     typewid *wptr = &ptr->cdsp;
00212 
00213     int i;
00214     for (i = 0; i < nstreams; ++i) {
00215         temp = tumblerfixedtoptr(&wptr->dsas[i], (humber) *loafptrptr);
00216         *loafptrptr += temp;
00217     }
00218 
00219     wptr = &ptr->cwid;
00220 
00221     for (i = 0; i < nstreams; ++i) {
00222         temp = tumblerfixedtoptr(&wptr->dsas[i], (humber) *loafptrptr);
00223         *loafptrptr += temp;
00224     }
00225 }
00226 
00227 /* 
00228  * #define hputinloaf(hp,lp,tp)
00229  * (humberput((hp),(lp),(tp)),(lp)=((char*)lp)+*(tp)) */
00230 
00238     static void
00239 hputinfo(
00240     typecbc  *ptr,
00241     char    **loafptrptr)
00242 {
00243     unsigned int temp;
00244 
00245     if (!is2dcrum((typecorecrum *) ptr)) {
00246         (void)humberput(ptr->cinfo.infotype, (humber) * loafptrptr, &temp);
00247         *loafptrptr += temp;
00248         if (ptr->cinfo.infotype == GRANTEXT) {
00249             (void)humberput((int) ptr->cinfo.granstuff.textstuff.textlength, (humber) * loafptrptr, &temp);
00250             *loafptrptr += temp;
00251 /* hputinloaf(ptr->cinfo.granstuff.textstuff.textlength,(*loafptrptr),&temp); */
00252             movmem(ptr->cinfo.granstuff.textstuff.textstring, (*loafptrptr), ptr->cinfo.granstuff.textstuff.textlength);
00253             *loafptrptr += ptr->cinfo.granstuff.textstuff.textlength;
00254             return;
00255         } else if (ptr->cinfo.infotype == GRANORGL) {
00256             (void)humberput(ptr->cinfo.granstuff.orglstuff.diskorglptr.diskblocknumber, (humber) * loafptrptr, &temp);
00257             *loafptrptr += temp;
00258             (void)humberput(ptr->cinfo.granstuff.orglstuff.diskorglptr.insidediskblocknumber, (humber) * loafptrptr,
00259                             &temp);
00260             *loafptrptr += temp;
00261 /* hputinloaf(ptr->cinfo.granstuff.orglstuff.diskorglptr,(*loafptrptr),&temp); */
00262             return;
00263         } else if (ptr->cinfo.infotype == GRANNULL) {
00264             return;
00265         } else {
00266             L("weird infotype in hputinfo %d \n", ptr->cinfo.infotype);
00267             assert(0); // weird infotype in hputinfo
00268             return;
00269         }
00270     } else {
00271         if (ptr->height) {
00272 /* looks like we got this all */
00273         } else {
00274             temp = tumblerfixedtoptr(&((type2dcbc *) ptr)->c2dinfo.homedoc, (humber) * loafptrptr);
00275             (*loafptrptr) += temp;
00276         }
00277     }
00278 }
00279 
00280 /* hdump(n,ptr) int n; char *ptr; { #ifndef DISTRIBUTION int i; for (i = 0; i < n; i++) { L("%x ", *(ptr+i)); } #endif } */
00281 
00289     static int
00290 varpackloaf(
00291     typecuc      *father,
00292     typediskloaf *xloafptr,
00293     int           refcount,
00294     int           flag)
00295 {
00296     typecorecrum *ptr;
00297     int ret;
00298     unsigned int temp;
00299 
00300     char *loafptr = (char *) xloafptr;
00301 
00302     if (!flag) {
00303         if (!father || father->height == 0 || !loafptr) {
00304             dump((typecorecrum *) father);
00305             assert(0); // bad packloaf call
00306         }
00307 
00308         assert(!father->leftson || !toomanysons(father)); // ERROR: Too many sons in packloaf
00309         
00310 /* tempptr = loafptr; */
00311         loafptr += 3;                  /* make room for loaflength */
00312         hputinloaf(false, loafptr, &temp);
00313         hputinloaf(father->height - 1, loafptr, &temp);
00314         hputinloaf(father->cenftype, loafptr, &temp);
00315         hputinloaf(father->numberofsons, loafptr, &temp);
00316         hputinloaf(refcount, loafptr, &temp);
00317 
00318     } else {
00319 /* tempptr = loafptr; */
00320         loafptr += 3;                  /* make room for loaflength */
00321         hputinloaf(true, loafptr, &temp);
00322         hputinloaf(father->height, loafptr, &temp);
00323         hputinloaf(father->cenftype, loafptr, &temp);
00324         hputinloaf(1, loafptr, &temp);
00325         hputinloaf(refcount, loafptr, &temp);
00326 
00327         hputwiddsp(father, &loafptr);
00328         hputinloaf(father->sonorigin.diskblocknumber, loafptr, &temp);
00329         hputinloaf(father->sonorigin.insidediskblocknumber, loafptr, &temp);
00330 
00331         if (father->sonorigin.diskblocknumber == 0) {
00332             // dump (ptr);
00333             assert(0); // trying to write 0 block
00334         }
00335         if (father->sonorigin.diskblocknumber == DISKPTRNULL) {
00336             /* dump (ptr); */
00337             assert(0); // trying to write DSKPTRNULL block
00338         }
00339 
00340         return (int) loafptr - (int) xloafptr;
00341     }
00342 
00343     for (ptr = (typecorecrum *) findleftson(father); ptr; ptr = ptr->rightbro) {
00344         hputwiddsp((typecuc *) ptr, (char **)&loafptr);
00345         if (ptr->height != 0) {
00346             hputinloaf(((typecuc *) ptr)->sonorigin.diskblocknumber, loafptr, &temp);
00347             hputinloaf(((typecuc *) ptr)->sonorigin.insidediskblocknumber, loafptr, &temp);
00348 
00349             if (((typecuc *) ptr)->sonorigin.diskblocknumber == 0) {
00350                 dump(ptr);
00351                 assert(0); // trying to write 0 block
00352             }
00353 
00354             if (((typecuc *) ptr)->sonorigin.diskblocknumber == DISKPTRNULL) {
00355                 dump(ptr);
00356                 assert(0); // trying to write DISKPTRNULL block
00357             }
00358         } else
00359             hputinfo((typecbc *) ptr, &loafptr);
00360     }
00361 
00362     ret = (int) loafptr - (int) xloafptr;
00363     humber3put(ret, (humber) xloafptr, &temp);
00364     return ret;
00365 }
00366 
00374     static int
00375 packloaf(
00376     typecuc      *father,
00377     typediskloaf *loafptr,
00378     int           refcount,
00379     int           flag)
00380 {
00381     return varpackloaf(father, loafptr, refcount, flag);
00382 }
00383 
00391     static void
00392 uniqueoutloaf(
00393     typecuc *father,
00394     int      refcount)
00395 {
00396     assert(father->modified);
00397 
00398     typeuberdiskloaf loaf = zzzerouberloaf;
00399     if ((!father->leftson) && father->sonorigin.diskblocknumber != DISKPTRNULL) {
00400         findleftson(father);     /* get it in so we know numberof sons zzz KLUGE is this right aug 15 86 */
00401         /* father->numberofsons = findnumberofdamnsons(father); */
00402     }
00403 
00404     int size = packloaf(father, (typediskloaf *) &loaf, refcount, 0);
00405 
00406     int newloaf;
00407     father->sonorigin = partialdiskalloc(size, &newloaf);
00408 
00409     unsigned int temp;
00410     humber3put(size, (humber) &loaf, &temp);
00411 
00412     /* loaf.numberofunterloafs = 1; */
00413 
00414     if (false && newloaf) {
00415         addallocatedloaftopartialallocedtables(father->sonorigin, size);
00416     }
00417 
00418     writeloaf((typediskloaf *) &loaf, father->sonorigin, newloaf);
00419     father->modified = false;
00420 }
00421 
00429     static void
00430 checkmodifiednotthere(
00431     typecuc *father,
00432     char    *string)
00433 {
00434     return;
00435 
00436 #ifndef DISTRIBUTION
00437 #ifdef UnDeFineD
00438     if (father->modified && (!father->leftson) /* &&father->sonor.diskblocknumber== * DISKPTRNULL */ ) {
00439         dump(father);
00440         L("in %s subtreewrite", string);
00441         assert(0); // in   subtreewriterecurs bad crum
00442     }
00443 #endif
00444 #endif
00445 }
00446 
00454     static void
00455 subtreewriterecurs(
00456     Session *sess,          
00457     typecuc *father)
00458 {
00459     if (!father || !father->height)
00460         assert(0); // Bad subtreewrite call
00461 
00462     /* this, of course, assumes modified is set right */
00463     if (!father->modified) {
00464         if (father->sonorigin.diskblocknumber == DISKPTRNULL) {
00465             L("insubtreewriterecurs sonorigin == -1\n");
00466             dumpsubtree(father);
00467             assert(0); // in subtreewriterecurs
00468         }
00469         loaffree(father);
00470         return;
00471     }
00472 
00473     // in order to guarantee integrity of disk, it's important to write out or increment sons before father
00474 
00475     checkmodifiednotthere(father, "A");
00476     typecbc *ptr;
00477     for (ptr = (typecbc *) father->leftson; ptr; ptr = (typecbc *) ptr->rightbro) {
00478         if (ptr->height == 0 && ptr->cenftype == GRAN && ptr->cinfo.infotype != GRANTEXT && ptr->cinfo.infotype != GRANORGL && ptr->cinfo.infotype != GRANORGL && ptr->cinfo.infotype != GRANNULL) {
00479             L("bad infotypein subtreewriterecursive  = %d\n", ptr->cinfo.infotype);
00480             dump((typecorecrum *) ptr);
00481             assert(0); // subtreewriterecurs
00482         }
00483 
00484         if (ptr->height != 0)
00485             subtreewriterecurs(sess, (typecuc *) ptr);
00486         else if (ptr->cenftype == GRAN && ptr->height == 0 && ((typecbc *) ptr)->cinfo.infotype == GRANORGL)
00487             orglwritepart2(sess, ptr);
00488 
00489         ptr->modified = false;
00490     }
00491 
00492     if (father->modified) {
00493         checkmodifiednotthere(father, "B");
00494 
00495         for (ptr = (typecbc *) father->leftson; ptr; ptr = (typecbc *) ptr->rightbro) {
00496             if (ptr->height > 0 && ((typecuc *) ptr)->sonorigin.diskblocknumber != DISKPTRNULL)
00497                 changerefcount(((typecuc *) ptr)->sonorigin, 1);
00498         }
00499 
00500         checkmodifiednotthere(father, "C");
00501         uniqueoutloaf(father, 0);
00502     }
00503 
00504     /* rejuvinate(father); */
00505     loaffree(father);
00506 }
00507 
00515     static void
00516 deletewithgarbageddescendents(
00517     typediskloafptr diskptr,
00518     typecuc *father,
00519     bool deletefullcrumflag);
00520 
00528     static void
00529 deletefullcrumandgarbageddescendents(
00530     typediskloafptr  diskptr,
00531     bool             deletefullcrumflag,
00532     typediskloaf    *loafp,
00533     typediskloafptr  newdiskptr)
00534 {
00535     if (diskptr.diskblocknumber == DISKPTRNULL)
00536         return;
00537 
00538 /* kluge up a bottum crum, use it to read in granf, similarly for spanf */
00539 /* tempcbc = (typecbc *)createcrum(0,GRAN); */
00540 
00541     typecbc crum;
00542     typecbc *tempcbc = &crum;
00543     initcrum(0, GRAN, (typecorecrum *) &crum);
00544 
00545     tempcbc->cinfo.infotype                        = GRANORGL;
00546     tempcbc->cinfo.granstuff.orglstuff.diskorglptr = diskptr;
00547 
00548     typeuberrawdiskloaf crum2;
00549     if (deletefullcrumflag) {
00550         inorglinternal(tempcbc, &crum2);
00551         /* reserve(tempcbc); */
00552     } else {
00553         inorglinternal(tempcbc, &crum2);
00554         /* reserve(tempcbc); */
00555         diskset(newdiskptr.diskblocknumber);
00556         writeloaf(loafp, newdiskptr, false);
00557     }
00558 
00559     tempcbc->cinfo.granstuff.orglstuff.orglptr->leftbroorfather = NULL;
00560     deletewithgarbageddescendents(diskptr, (typecuc *) tempcbc, deletefullcrumflag);
00561     /* kluge SKIMP reserve and rejuvinate added 11-23-86 */
00562 }
00563 
00571     static void
00572 deletewithgarbageddescendents(
00573     typediskloafptr diskptr,
00574     typecuc        *father,
00575     bool            deletefullcrumflag)
00576 {
00577     typecbc *ptr;
00578     typediskloafptr ignoreddiskptr;
00579 
00580     if (father->height > 0)
00581         ptr = (typecbc *) findleftson(father);
00582 
00583 /* if !flag changerefcount and then possibly recurse */
00584     if (!deletefullcrumflag || !changerefcount(diskptr, -1)) {
00585         if (father->height > 0) {
00586             for (; ptr; ptr = (typecbc *) findrightbro((typecorecrum *) ptr)) {
00587                 if (ptr->height > 0)
00588                     deletewithgarbageddescendents(((typecuc *) ptr)->sonorigin, (typecuc *) ptr, true);
00589             }
00590         } else if (father->cenftype == GRAN && ((typecbc *) father)->cinfo.infotype == GRANORGL
00591                    && ((typecbc *) father)->cinfo.granstuff.orglstuff.orglincore
00592                    && ((typecbc *) father)->cinfo.granstuff.orglstuff.diskorglptr.diskblocknumber != GRANFDISKLOCATION
00593                    && ((typecbc *) father)->cinfo.granstuff.orglstuff.diskorglptr.diskblocknumber !=
00594                    SPANFDISKLOCATION) {
00595             deletefullcrumandgarbageddescendents(((typecbc *) father)->cinfo.granstuff.orglstuff.diskorglptr, true,     /* ECH 
00596                                                                                                                          * 8-28-88ignoreddiskptr, */
00597                                                  (typediskloaf *) NULL, ignoreddiskptr);
00598         }
00599     }
00600 /* subtreefree(ptr); *//*12/04/86 */
00601 }
00602 
00610     static void
00611 orglwritepart2(
00612     Session *sess,          
00613     typecbc *orglcbcptr)
00614 {
00615     L("beginning orglwritepart2()\n");
00616     assert(orglcbcptr != NULL);
00617 
00618     typediskloaf loaf = zzzeroloaf;
00619 
00620     typegranbottomcruminfo *infoptr = &orglcbcptr->cinfo;
00621     typecuc                *orglptr = infoptr->granstuff.orglstuff.orglptr;
00622 
00623     if (!orglcbcptr->modified && orglptr) {
00624         orglfree(orglptr);
00625         return;
00626     }
00627 
00628     if (infoptr->granstuff.orglstuff.orglincore) {
00629         L("orglincore\n");
00630 
00631         L("calling reserve()\n");
00632         reserve((typecorecrum *) orglcbcptr);
00633         L("returned from calling reserve()\n");
00634 
00635         typediskloafptr olddiskptr = infoptr->granstuff.orglstuff.diskorglptr;
00636         L("calling subtreewriterecurs()\n");
00637         subtreewriterecurs(sess, orglptr);
00638         L("returned from calling subtreewriterecurs()\n");
00639 
00640         //writefullcrum(orgl);
00641 
00642         int size = packloaf(orglptr, &loaf, 1, 1);
00643         unsigned int dummy;
00644         humber3put(size, (humber) &loaf, &dummy);
00645 
00646         if (orglptr->cenftype == POOM) {
00647             L("cenftype == POOM\n");
00648 
00649             int newloaf;
00650             typediskloafptr temploaf = partialdiskalloc(size, &newloaf);
00651             writeloaf(&loaf, temploaf, newloaf);
00652             changerefcount(temploaf, 1);
00653 
00654             infoptr->granstuff.orglstuff.diskorglptr = temploaf;
00655             // in below, olddiskptr is just a placeholder
00656             deletefullcrumandgarbageddescendents(olddiskptr, true, (typediskloaf *) NULL, olddiskptr);
00657             //writeloaf(&loaf, infoptr->granstuff.orglstuff.diskorglptr, true);
00658         } else {
00659             L("cenftype != POOM\n");
00660 
00661             if (diskheader.hasenftops) {
00662                 deletefullcrumandgarbageddescendents(olddiskptr, false, &loaf, infoptr->granstuff.orglstuff.diskorglptr);
00663                 //writeloaf(&loaf, infoptr->granstuff.orglstuff.diskorglptr, true);
00664             } else {
00665                 writeloaf(&loaf, infoptr->granstuff.orglstuff.diskorglptr, true);
00666             }
00667         }
00668 
00669         /* NULL EFFECT HERE */
00670         /* ptr->modified = false; */
00671         rejuvinate((typecorecrum *) orglcbcptr);
00672         orglfree(orglptr);
00673     }
00674 }
00675 
00683     void
00684 orglwrite(
00685     typecbc *orglcbcptr)
00686 {
00687     assert(orglcbcptr != NULL); // in orglwrite passed NULL
00688 
00689     //now done via a ctor:: inittask(&sess);
00690     Session sess;          
00691     orglwritepart2(&sess, orglcbcptr);
00692     sess.free();
00693 }
00694 
00702     void
00703 subtreewrite(
00704     typecuc *father)
00705 {
00706     Session sess;          
00707 
00708     //Now done via a ctor:: inittask(&sess);
00709     subtreewriterecurs(&sess, father);
00710 /* decrementandfreedisk (top); */
00711     sess.free();
00712 }

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