tablepack.c

Go to the documentation of this file.
00001 
00002 /*  $Id: tablepack.c 1236 2006-04-09 11:28:08Z andreradke $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "memory.h"
00032 #include "quickdraw.h"
00033 #include "strings.h"
00034 #include "db.h"
00035 #include "langexternal.h"
00036 #include "tablestructure.h"
00037 #include "tableinternal.h"
00038 #include "tableverbs.h"
00039 #include "byteorder.h"  /* 2006-04-08 aradke: endianness conversion macros */
00040 
00041 
00042 
00043 boolean tablepacktable (hdlhashtable htable, boolean flmemory, Handle *hpacked, boolean *flmustsave) {
00044     
00045     /*
00046     10/6/91 dmb: mergehandles now consumes both source handles.
00047     
00048     6.2a15 AR: added flmustsave parameter.
00049     */
00050     
00051     register hdlhashtable ht = htable;
00052     register hdltableformats hf;
00053     Handle hpackedtable, hpackedformats;
00054     register boolean fl;
00055     
00056     if (!hashpacktable (ht, flmemory, &hpackedtable, flmustsave))
00057         return (false);
00058     
00059     hf = (hdltableformats) (**ht).hashtableformats; /*copy into register*/
00060     
00061     if (hf == nil) /*no formats linked in*/
00062         hpackedformats = nil;
00063     
00064     else {
00065         tablepushformats (hf); /*set table.c global*/
00066         
00067         fl = tablepackformats (&hpackedformats);
00068         
00069         tablepopformats ();
00070         
00071         if (!fl) {
00072             
00073             disposehandle (hpackedtable);
00074             
00075             return (false);
00076             }
00077         }
00078     
00079     fl = mergehandles (hpackedtable, hpackedformats, hpacked);
00080     
00081     /*
00082     disposehandle (hpackedtable);
00083     
00084     disposehandle (hpackedformats);
00085     */
00086     
00087     return (fl);
00088     } /*tablepacktable*/
00089 
00090 
00091 boolean tableunpacktable (Handle hpacked, boolean flmemory, hdlhashtable *htable) {
00092     
00093     /*
00094     9/24/91 dmb: don't treat format unpacking failure as a fatal error.
00095     
00096     10/16/91 dmb: clear table's dirty bit after unpacking.
00097     
00098     3.0.4b8 dmb: use scratchport for the duration; port is unknown
00099     
00100     4.0b7 dmb: don't set scratchport while unpacking the table; too many
00101     nested pushports result. Just set it when we care, and leave each table
00102     entry to fend for itself.
00103     
00104     5.0a23 dmb: don't create table formats if none are packed
00105     
00106     5.0a25 dmb: don't clear table's fldirty flag anymore.
00107     */
00108     
00109     Handle hpackedtable = nil;
00110     Handle hpackedformats = nil;
00111     hdlhashtable ht = nil;
00112     hdltableformats hformats = nil;
00113     
00114     if (!unmergehandles (hpacked, &hpackedtable, &hpackedformats)) /*comsumes hpacked*/
00115         return (false);
00116     
00117     if (!newhashtable (htable)) {
00118         
00119         disposehandle (hpackedtable);
00120         
00121         goto error; /*will dispose of everything but hpackedtable*/
00122         }
00123     
00124     ht = *htable; /*move into register*/
00125     
00126     if (!hashunpacktable (hpackedtable, flmemory, ht)) /*always disposes of hpackedtable*/
00127         goto error;
00128     
00129     if (hpackedformats != nil) {
00130     
00131         if (!newtableformats (&hformats))
00132             goto error;
00133         
00134         tablelinkformats (ht, hformats);
00135         
00136         pushscratchport ();
00137         
00138         if (!tableunpackformats (hpackedformats, hformats)) {
00139             
00140         //  tablesetdimension (hformats, false, 0, fixedctcols);
00141             }
00142         
00143         popport ();
00144         
00145         disposehandle (hpackedformats);
00146         
00147         if ((**hformats).fldirty) /*formats were out of date*/
00148             (**ht).fldirty = true;
00149         }
00150     
00151     return (true);
00152     
00153     error: {
00154         
00155         disposehandle (hpackedformats);
00156         
00157         disposetableformats (hformats);
00158         
00159         disposehashtable (ht, false);
00160         
00161         return (false);
00162         }
00163     } /*tableunpacktable*/
00164 
00165 
00166 boolean tableverbmemorypack (hdlexternalvariable h, Handle *hpacked, hdlhashnode hnode) {
00167     
00168     register hdlexternalvariable hv = h;
00169     register hdlhashtable ht;
00170     Handle hpush;
00171     register boolean fl;
00172     boolean fltempload;
00173     boolean fldummy;
00174     
00175     fltempload = !(**hv).flinmemory;
00176     
00177     if (!tableverbinmemory (hv, hnode))
00178         return (false);
00179     
00180     ht = (hdlhashtable) (**hv).variabledata; 
00181     
00182     tablecheckwindowrect (ht); 
00183     
00184     fl = tablepacktable (ht, true, &hpush, &fldummy);
00185     
00186     if (fltempload)
00187         tableverbunload (hv);
00188     
00189     if (fl) {
00190         
00191         fl = pushhandle (hpush, *hpacked);
00192         
00193         disposehandle (hpush);
00194         }
00195     
00196     return (fl);
00197     } /*tableverbmemorypack*/
00198 
00199 
00200 boolean tableverbmemoryunpack (Handle hpacked, long *ixload, hdlexternalvariable *h, boolean flxml) {
00201     
00202     /*
00203     create a new outline variable -- not in memory.
00204     
00205     this is a special entrypoint for the pack and unpack verbs.
00206     */
00207     
00208     Handle hpackedtable;
00209     hdlhashtable htable;
00210     register hdlhashtable ht;
00211     
00212     if (!loadhandleremains (*ixload, hpacked, &hpackedtable))
00213         return (false);
00214     
00215     if (!tableunpacktable (hpackedtable, true, &htable)) /*always disposes of hpackedtable*/
00216         return (false);
00217     
00218     ht = htable; /*move into register*/
00219     
00220     if (!newtablevariable (true, (long) ht, (hdltablevariable *) h, flxml)) {
00221         
00222         tabledisposetable (ht, false);
00223         
00224         return (false);
00225         }
00226     
00227     (**ht).hashtablerefcon = (long) *h; /*we can get from hashtable to variable rec*/
00228     
00229     (**ht).fldirty = true;
00230     
00231     return (true); /*in memory*/
00232     } /*tableverbmemoryunpack*/
00233 
00234 
00235 boolean tableverbpack (hdlexternalvariable h, Handle *hpacked, boolean *flnewdbaddress) {
00236     
00237     /*
00238     12/4/91 dmb: set windowinfo's dirty bit to false after save
00239     
00240     6.2a15 AR: Rely on flsubsdirty flag in hashtable instead of calling tablenosubsdirty.
00241     Set new flnewdbaddress parameter appropriately -- we only guarantee it to be accurate
00242     if the function returns true.
00243     */
00244     
00245     register hdlexternalvariable hv = h;
00246     register hdlhashtable ht;
00247     dbaddress adr;
00248     Handle hpackedtable;
00249     register boolean fl = true;
00250     boolean fltempload = false;
00251     boolean flmustsave = false;
00252     hdlwindowinfo hinfo;
00253     
00254     if (fldatabasesaveas) {
00255         
00256         fltempload = !(**hv).flinmemory;
00257         
00258         if (!tableverbinmemory (hv, HNoNode))
00259             return (false);
00260         
00261         *flnewdbaddress = true; /*it's in another database even*/
00262         }
00263     
00264     if (!(**hv).flinmemory) { /*not in memory, just push the old db address*/
00265         
00266         adr = (dbaddress) (**hv).variabledata;
00267         
00268         *flnewdbaddress = false;
00269 
00270         goto pushaddress;
00271         }
00272         
00273     adr = (**hv).oldaddress;
00274     
00275     ht = (hdlhashtable) (**hv).variabledata;
00276     
00277     tablecheckwindowrect (ht);
00278     
00279     assert (fldatabasesaveas || (((**ht).fldirty || (**ht).flsubsdirty) == !tablenosubsdirty (ht)));
00280     
00281     if (!fldatabasesaveas && !(**ht).flsubsdirty && !(**ht).fldirty) { /*none of our subs are dirty, old address still good*/
00282 
00283         *flnewdbaddress = false;
00284 
00285         goto pushaddress;
00286         }
00287     
00288     /*it's in memory and either the table itself or one of its subs are dirty, so pack the table*/
00289     
00290     fl = tablepacktable (ht, false, &hpackedtable, &flmustsave);
00291     
00292     if (!fl)
00293         goto pushaddress;
00294     
00295     /*only save if we're saving a copy, if the table itself is dirty (i.e. a scalar or the name of an object changed),
00296         or if one of its subs changed in  a way so that the table itself actually needs saving now*/
00297     
00298     if (fldatabasesaveas || (**ht).fldirty || flmustsave)
00299         fl = dbsavehandle (hpackedtable, &adr);
00300     
00301 #if 0
00302     else {
00303         /*
00304         Unfortunately, this debugging code is bogus. The problem is that in hashpackexternal
00305         we previously assigned a random value to the unused byte of the tyexternaldiskrecord.
00306         */
00307         
00308         Handle htemp;
00309         boolean fl;
00310         long ctbytes;
00311         
00312         fl = dbrefhandle ((**hv).oldaddress, &htemp);
00313         
00314         assert (fl);
00315         
00316         pullfromhandle (htemp, 0L, sizeof (long), &ctbytes);
00317         
00318         assert (ctbytes <= gethandlesize (htemp));
00319         
00320         sethandlesize (htemp, ctbytes);
00321         
00322         pullfromhandle (hpackedtable, 0L, sizeof (long), &ctbytes);
00323         
00324         assert (ctbytes <= gethandlesize (hpackedtable));
00325         
00326         sethandlesize (hpackedtable, ctbytes);
00327         
00328         assert (equalhandles (htemp, hpackedtable));
00329         
00330         disposehandle (htemp);
00331         }   
00332 #endif
00333     
00334     disposehandle (hpackedtable);
00335     
00336     if (!fl)
00337         goto pushaddress;
00338     
00339     if (fldatabasesaveas)
00340         goto pushaddress;
00341     
00342     *flnewdbaddress = ((**hv).oldaddress != adr);
00343     
00344     (**hv).oldaddress = adr;
00345     
00346     (**ht).fldirty = false; /*it's been saved to the db*/
00347     
00348     (**ht).flsubsdirty = false;
00349     
00350     if (tablewindowopen (hv, &hinfo))
00351         shellsetwindowchanges (hinfo, false);
00352     
00353     pushaddress:
00354     
00355     if (fltempload)
00356         tableverbunload (hv);
00357     
00358     if (!fl)
00359         return (false);
00360     
00361     memtodisklong (adr);
00362     
00363     return (enlargehandle (*hpacked, sizeof (adr), (ptrchar) &adr));
00364     } /*tableverbpack*/
00365 
00366 
00367 boolean tableverbunpack (Handle hpacked, long *ixload, hdlexternalvariable *h, boolean flxml) {
00368 
00369     dbaddress adr;
00370     
00371     if (!loadlongfromdiskhandle (hpacked, ixload, &adr)) 
00372         return (false);
00373         
00374     return (newtablevariable (false, adr, (hdltablevariable *) h, flxml));
00375     } /*tableverbunpack*/
00376 
00377 
00378 static boolean tablepacktotextvisit (bigstring bsname, hdlhashnode hnode, tyvaluerecord val, ptrvoid refcon) {
00379 #pragma unused (hnode)
00380 
00381     /*
00382     4.0.2b1 dmb: handle fldiskvals. see comment in hashsortedinversesearch
00383     */
00384     
00385     Handle htextscrap = (Handle) refcon;
00386     boolean fl;
00387     
00388     pushchar (chtab, bsname);
00389     
00390     if (!pushtexthandle (bsname, htextscrap))
00391         return (true); /*abort traversal*/
00392     
00393     if (val.fldiskval)
00394         if (!copyvaluerecord (val, &val))
00395             return (true);
00396     
00397     fl = langvaluetotextscrap (val, htextscrap);
00398     
00399     if (exemptfromtmpstack (&val))
00400         disposevaluerecord (val, false);
00401     
00402     if (!fl)
00403         return (true);
00404     
00405     return (false); /*keep going*/
00406     } /*tablepacktotextvisit*/
00407 
00408 
00409 boolean tableverbpacktotext (hdlexternalvariable h, Handle htext) {
00410     
00411     /*
00412     12/23/92 dmb: hashinversesearch now takes table as param; don't push/pop
00413     
00414     12/31/92 dmb: use hashsortedinversesearch so text is in correct order
00415     
00416     5.0.2b20 dmb: unload if just loaded
00417     
00418     5.1.5 dmb: use tablesortedinversesearch for guest databases
00419     */
00420     
00421     register hdlexternalvariable hv = h;
00422     register hdlhashtable ht;
00423     register boolean fl;
00424     boolean fltempload = !(**hv).flinmemory;
00425     
00426     if (!tableverbinmemory (hv, HNoNode))
00427         return (false);
00428     
00429     ht = (hdlhashtable) (**hv).variabledata;
00430     
00431     //htextscrap = htext; /*set for visit routine*/
00432     
00433     //fl = !hashinversesearch (ht, &tablepacktotextvisit, bsname); /*false means complete traversal%/
00434     
00435     fl = !tablesortedinversesearch (ht, &tablepacktotextvisit, htext);
00436     
00437     if (fltempload)
00438         tableverbunload (hv);
00439     
00440     return (fl);
00441     } /*tableverbpacktotext*/
00442 
00443 
00444 boolean tableverbgettimes (hdlexternalvariable h, long *timecreated, long *timemodified, hdlhashnode hnode) {
00445     
00446     register hdlexternalvariable hv = h;
00447     register hdlhashtable ht;
00448     
00449     if (!tableverbinmemory (hv, hnode))
00450         return (false);
00451     
00452     ht = (hdlhashtable) (**hv).variabledata;
00453     
00454     *timecreated = (**ht).timecreated;
00455     
00456     *timemodified = (**ht).timelastsave;
00457     
00458     return (true);
00459     } /*tableverbgettimes*/
00460 
00461 
00462 boolean tableverbsettimes (hdlexternalvariable h, long timecreated, long timemodified, hdlhashnode hnode) {
00463     
00464     register hdlexternalvariable hv = h;
00465     register hdlhashtable ht;
00466     
00467     if (!tableverbinmemory (hv, hnode))
00468         return (false);
00469     
00470     ht = (hdlhashtable) (**hv).variabledata;
00471     
00472     (**ht).timecreated = timecreated;
00473     
00474     (**ht).timelastsave = timemodified;
00475     
00476     return (true);
00477     } /*tableverbsettimes*/
00478 
00479 
00480 static boolean findusedblocksvisit (hdlhashnode hnode, ptrvoid refcon) {
00481     
00482     /*
00483     5.1.5b16: check fldontsave flag to avoid diving into guest databases, etc.
00484     */
00485     
00486     ptrstring bsparent = (ptrstring) refcon;
00487     tyvaluerecord val = (**hnode).val;
00488     bigstring bspath;
00489     
00490 //  if ((**hnode).fldontsave) //never gets saved in the database
00491 //      return (true);
00492     
00493     gethashkey (hnode, bspath);
00494     
00495     if (bsparent != nil) {
00496 
00497         insertchar ('.', bspath);
00498 
00499         insertstring (bsparent, bspath);
00500         }
00501 
00502     if (val.valuetype == externalvaluetype)
00503         return (langexternalfindusedblocks ((hdlexternalvariable) val.data.externalvalue, bspath));
00504     
00505     if (val.fldiskval)
00506         return (statsblockinuse (val.data.diskvalue, bspath));
00507     
00508     return (true); /*continue traversal*/
00509     } /*findusedblocksvisit*/
00510 
00511 
00512 boolean tableverbfindusedblocks (hdlexternalvariable h, bigstring bspath) {
00513     
00514     register hdlexternalvariable hv = h;
00515     register hdlhashtable ht;
00516     register boolean fl;
00517     boolean fltempload;
00518     
00519     fltempload = !(**hv).flinmemory;
00520     
00521     if (!tableverbinmemory (hv, HNoNode))
00522         return (false);
00523     
00524     if (!statsblockinuse ((**hv).oldaddress, bspath))
00525         return (false);
00526     
00527     ht = (hdlhashtable) (**hv).variabledata; 
00528     
00529     if (ht == filewindowtable)
00530         fl = true;
00531     else
00532         fl = hashtablevisit (ht, findusedblocksvisit, bspath);
00533     
00534     if (fltempload)
00535         tableverbunload (hv);
00536     
00537     return (fl);
00538     } /*tableverbfindusedblocks*/
00539 
00540 
00541 
00542 

Generated on Wed May 31 18:20:03 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6