dbstats.c

Go to the documentation of this file.
00001 
00002 /*  $Id: dbstats.c 1207 2006-04-05 23:27:47Z karstenw $    */
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 "cursor.h"
00033 #include "font.h"
00034 #include "kb.h"
00035 #include "quickdraw.h"
00036 #include "resources.h"
00037 #include "strings.h"
00038 #include "frontierwindows.h"
00039 #include "shell.h"
00040 #include "db.h"
00041 #include "dbinternal.h"
00042 
00043 
00044  
00045 #define idstatsstringlist 140
00046 
00047 
00048 enum { /*statsmessage indexes*/
00049     
00050     idwindowtitle = 1,
00051     
00052     idnodesinreleaselist,
00053     idbytesinreleaselist,
00054     idnodesinavaillist,
00055     idbytesinavaillist,
00056     idlargestfreenode,
00057     idnumberinconsistent,
00058     idnodesfreesequentially,
00059     idbytesfreesequentially,
00060     idnodesusedsequentially,
00061     idbytesusedsequentially,
00062     idnodesusedlogically,
00063     idbytesusedlogically,
00064     idnumberbytesorphaned,
00065     
00066     idreadheaderfailed,
00067     idreadusedheaderfailed,
00068     idfreeblockinuse,
00069     idreadavailnodefailed,
00070     idgeteoffailed,
00071     idreadheaderfailed1,
00072     idreadtrailerfailed2,
00073     idheadertrailerdisagree,
00074     idavailshadowoutofsynch
00075     };
00076 
00077 
00078 typedef struct tystatsrecord {
00079     
00080     boolean flstatscomputed;
00081 
00082     long ctreleasenodes, ctreleasebytes;
00083     
00084     long ctavail, cttotalbytes, ctlargestblock;
00085     
00086     long seqctfree, seqctinuse, seqsizefree, seqsizeinuse;
00087     
00088     long logctinuse, logsizeinuse;
00089     
00090     long ctinconsistencies;
00091     
00092     bigstring bsmessage;
00093     
00094     short vstats; /*vertical offset next line is drawn at*/
00095 
00096     short hstats; /*horizontal offset*/
00097 
00098     short statslineheight;
00099     } tystatsrecord, *ptrstatsrecord, **hdlstatsrecord;
00100     
00101 
00102 static WindowPtr statswindow = nil;
00103 
00104 static hdlwindowinfo statswindowinfo = nil;
00105 
00106 static hdlstatsrecord statsdata = nil;
00107 
00108 
00109 
00110 
00111 static void getstatsstring (short id, bigstring bs) {
00112     
00113     getstringlist (idstatsstringlist, id, bs);
00114     } /*getstatsstring*/
00115 
00116 
00117 static void setstatsmessage (short id) {
00118     
00119     bigstring bs;
00120     
00121     getstatsstring (id, bs);
00122     
00123     copystring (bs, (**statsdata).bsmessage);
00124     } /*setstatsmessage*/
00125 
00126 
00127 static void statsline (bigstring bs) {
00128     
00129     register hdlstatsrecord hs = statsdata;
00130     
00131     movepento ((**hs).hstats, (**hs).vstats);
00132     
00133     pendrawstring (bs);
00134     
00135     (**hs).vstats += (**hs).statslineheight;
00136     
00137     //Timothy Paustian 10/5/00
00138     //We need to flush the result to the stats window everytime to see it
00139     //If this is not called the window remains blank.
00140     #if TARGET_API_MAC_CARBON == 1
00141     QDFlushPortBuffer(GetWindowPort(statswindow), nil);
00142     #endif
00143     } /*statsline*/
00144     
00145 
00146 static void statsdisplay (short idstat, long n) {
00147     
00148     bigstring bs;
00149     
00150     getstatsstring (idstat, bs);
00151     
00152     pushstring ((ptrstring) "\x03" " = ", bs);
00153     
00154     pushlong (n, bs);
00155     
00156     statsline (bs);
00157     } /*statsdisplay*/
00158 
00159 
00160 static void statsupdate (void) {
00161     
00162     register hdlstatsrecord hs = statsdata;
00163     register hdlwindowinfo hw = statswindowinfo;
00164     Rect r;
00165     
00166     pushstyle ((**hw).defaultfont, (**hw).defaultsize, (**hw).defaultstyle);
00167     
00168     (**hs).statslineheight = globalfontinfo.ascent + globalfontinfo.descent + 3;
00169     
00170     r = (**hw).contentrect;
00171     
00172     if (!(**hs).flstatscomputed)
00173         eraserect (r);
00174 
00175     else {
00176 
00177         (**hs).vstats = r.top + (**hs).statslineheight;
00178         
00179         (**hs).hstats = r.left + 8;
00180         
00181         statsdisplay (idnodesinreleaselist, (**hs).ctreleasenodes);
00182         
00183         statsdisplay (idbytesinreleaselist, (**hs).ctreleasebytes);
00184         
00185         statsline (zerostring);
00186         
00187         if ((**hs).ctavail >= 0) {
00188             
00189             statsdisplay (idnodesinavaillist, (**hs).ctavail);
00190             
00191             statsdisplay (idbytesinavaillist, (**hs).cttotalbytes);
00192             
00193             statsdisplay (idlargestfreenode, (**hs).ctlargestblock);
00194             
00195             statsdisplay (idnumberinconsistent, (**hs).ctinconsistencies);
00196             
00197             statsline (zerostring);
00198             }
00199         
00200         if ((**hs).seqctinuse > 0) {
00201         
00202             statsdisplay (idnodesfreesequentially, (**hs).seqctfree);
00203             
00204             statsdisplay (idbytesfreesequentially, (**hs).seqsizefree);
00205             
00206             statsdisplay (idnodesusedsequentially, (**hs).seqctinuse);
00207             
00208             statsdisplay (idbytesusedsequentially, (**hs).seqsizeinuse);
00209             
00210             statsline (zerostring);
00211             }
00212         
00213         if ((**hs).logctinuse > 0) {
00214         
00215             statsdisplay (idnodesusedlogically, (**hs).logctinuse);
00216             
00217             statsdisplay (idbytesusedlogically, (**hs).logsizeinuse);
00218             
00219             statsdisplay (idnumberbytesorphaned, (**hs).seqsizeinuse - (**hs).logsizeinuse - (**hs).ctreleasebytes);
00220             }
00221         }
00222     
00223     popstyle ();
00224     } /*statsupdate*/
00225     
00226     
00227 static boolean statscountreleasestack (long *ctreleasenodes, long *ctreleasebytes) {
00228     
00229     /*
00230     release all the chunks accumulated in the database's releasestack.
00231     */
00232     
00233     Handle h = (**databasedata).releasestack;
00234     register long ct;
00235     register long ctreleased = 0;
00236     long ctbytes;
00237     boolean flfree;
00238     tyvariance variance;
00239     #ifdef DATABASE_DEBUG
00240         register tydbreleasestackframe *p;
00241     #else
00242         register ptrdbaddress p;
00243     #endif
00244     
00245     *ctreleasenodes = 0;
00246     
00247     *ctreleasebytes = 0;
00248     
00249     if (h == nil) /*nothing released*/
00250         return (true);
00251     
00252     #ifdef DATABASE_DEBUG
00253         ct = *ctreleasenodes = gethandlesize (h) / sizeof (tydbreleasestackframe);
00254 
00255         p = (tydbreleasestackframe*) *h;
00256         
00257         while (--ct >= 0) {
00258             
00259             if (!dbreadheader ((p++)->adr, &flfree, &ctbytes, &variance)) {
00260                 
00261                 setstatsmessage (idreadheaderfailed);
00262                 
00263                 return (false);
00264                 }
00265             
00266             rollbeachball ();
00267             
00268             ctreleased += ctbytes;
00269             }
00270     #else
00271         ct = *ctreleasenodes = gethandlesize (h) / sizeof (dbaddress);
00272 
00273         p = (ptrdbaddress) *h;
00274         
00275         while (--ct >= 0) {
00276             
00277             if (!dbreadheader (*p++, &flfree, &ctbytes, &variance)) {
00278                 
00279                 setstatsmessage (idreadheaderfailed);
00280                 
00281                 return (false);
00282                 }
00283             
00284             rollbeachball ();
00285             
00286             ctreleased += ctbytes;
00287             }
00288     #endif
00289     
00290     *ctreleasebytes = ctreleased;
00291     
00292     return (true);
00293     } /*statscountreleasestack*/
00294 
00295 
00296 boolean statsblockinuse (dbaddress adr, bigstring bsitem) {
00297 #pragma unused (bsitem)
00298 
00299     /*
00300     called from the EFPs directly as we're doing our content-based 
00301     database scan.
00302 
00303     5.0a25 dmb: added bsitem parameter, keyboardescape check
00304     */
00305     
00306     register hdlstatsrecord hs = statsdata;
00307     boolean flfree;
00308     long ctbytes;
00309     tyvariance variance;
00310     
00311     if (adr == nildbaddress) /*ok to pass nil*/
00312         return (true);
00313     
00314     if (keyboardescape ())
00315         return (false);
00316     
00317     /*
00318     if (bsitem != nil) {
00319         
00320         shellsetwindowmessage (statswindowinfo, bsitem);
00321 
00322         shelldrawwindowmessage (statswindowinfo);
00323         }
00324     */
00325     
00326     if (!dbreadheader (adr, &flfree, &ctbytes, &variance)) {
00327         
00328         setstatsmessage (idreadusedheaderfailed);
00329         
00330         return (false);
00331         }
00332     
00333     if (flfree) {
00334         
00335         setstatsmessage (idfreeblockinuse);
00336         
00337         return (false);
00338         }
00339     
00340     (**hs).logctinuse++;
00341     
00342     (**hs).logsizeinuse += ctbytes;
00343     
00344     return (true);
00345     } /*statsblockinuse*/
00346 
00347 
00348 static boolean statscompute (boolean flincludeusedblocks) {
00349 
00350     /*
00351     the first three statistics are numbers produced by traversing the 
00352     avail list.
00353     
00354     the other numbers are determined by doing a sequential scan of the
00355     database, record by record.
00356     
00357     ctinconsistencies is the result of comparing the trailer with the balancing
00358     header in each block in the database.  if they all agree with each other
00359     then ctinconsistencies is 0, otherwise the number of errors is reported.
00360     
00361     7/8/91 dmb: roll the beach ball
00362     */
00363     
00364     register hdlstatsrecord hs = statsdata;
00365     long ctnodes;
00366     long totalbytes;
00367     long largestblock;
00368     dbaddress nomad;
00369     boolean flfree, fl2;
00370     long ctbytes, ct2;
00371     dbaddress nextnomad;
00372     long ctfree, ctinuse, sizefree, sizeinuse, eof;
00373     long ctincon;
00374     tyvariance variance;
00375     hdlavaillistshadow havailshadow = (hdlavaillistshadow) (**databasedata).u.extensions.availlistshadow.data;
00376     
00377     initbeachball (right);
00378     
00379     clearhandle ((Handle) hs);
00380 
00381     statsupdate ();
00382     
00383     if (!statscountreleasestack (&ctnodes, &totalbytes))
00384         return (false);
00385     
00386     if (keyboardescape ())
00387         return (false);
00388     
00389     (**hs).ctreleasenodes = ctnodes; /*copy returned values*/
00390     
00391     (**hs).ctreleasebytes = totalbytes; /*copy returned values*/
00392     
00393     (**hs).flstatscomputed = true; // something has been computed
00394 
00395     (**hs).ctavail = -1; // not yet calced
00396     
00397     statsupdate ();
00398     
00399     nomad = (**databasedata).availlist;
00400     
00401     ctnodes = 0;
00402     
00403     totalbytes = 0;
00404     
00405     largestblock = 0;
00406     
00407     while (nomad != nildbaddress) {
00408     
00409         if (!dbreadavailnode (nomad, &flfree, &ctbytes, &nextnomad)) {
00410             
00411             setstatsmessage (idreadavailnodefailed);
00412             
00413             return (false);
00414             }
00415         
00416         if ((*havailshadow) [ctnodes].adr != nomad)
00417             setstatsmessage (idavailshadowoutofsynch);
00418         
00419         if ((*havailshadow) [ctnodes].size != ctbytes)
00420             setstatsmessage (idavailshadowoutofsynch);
00421         
00422         ctnodes++;
00423         
00424         totalbytes += ctbytes;
00425         
00426         nomad = nextnomad;
00427         
00428         rollbeachball ();
00429         
00430         if (ctbytes > largestblock)
00431             largestblock = ctbytes;
00432         } /*while*/ 
00433         
00434     (**hs).ctavail = ctnodes; /*copy returned values*/
00435     
00436     (**hs).cttotalbytes = totalbytes;
00437     
00438     (**hs).ctlargestblock = largestblock;
00439     
00440     statsupdate ();
00441     
00442     if (!dbgeteof (&eof)) {
00443     
00444         setstatsmessage (idgeteoffailed);
00445         
00446         return (false);
00447         }
00448     
00449     ctfree = 0; /*initialize loop variables*/
00450     
00451     ctinuse = 0;
00452     
00453     sizefree = 0;
00454     
00455     sizeinuse = 0;
00456     
00457     ctincon = 0;
00458     
00459     (**hs).seqctfree = 0; /*initialize returned values*/
00460     
00461     (**hs).seqctinuse = 0;
00462     
00463     (**hs).seqsizefree = 0;
00464     
00465     (**hs).seqsizeinuse = 0;
00466     
00467     (**hs).ctinconsistencies = 0;
00468     
00469     (**hs).logctinuse = 0;
00470     
00471     (**hs).logsizeinuse = 0;
00472     
00473     nomad = firstphysicaladdress; /*point at first physical record in the database*/
00474     
00475     initbeachball (left); /*reverse direction*/
00476     
00477     while (nomad < eof) { /*scan the database sequentially*/
00478         
00479         if (!dbreadheader (nomad, &flfree, &ctbytes, &variance)) {
00480     
00481             setstatsmessage (idreadheaderfailed1);
00482             
00483             return (false);
00484             }
00485             
00486         if (flfree) {
00487         
00488             ctfree++;
00489             
00490             sizefree += ctbytes;
00491             }
00492         else {
00493             ctinuse++;
00494             
00495             sizeinuse += ctbytes;
00496             }
00497             
00498         nomad += sizeheader + ctbytes; /*point at the trailer*/
00499         
00500         if (!dbreadtrailer (nomad, &fl2, &ct2)) {
00501         
00502             setstatsmessage (idreadtrailerfailed2);
00503                         
00504             return (false);
00505             }
00506             
00507         if ((fl2 != flfree) || (ct2 != ctbytes)) {
00508             
00509             setstatsmessage (idheadertrailerdisagree);
00510                             
00511             ctincon++;
00512             }
00513         
00514         rollbeachball ();
00515         
00516         nomad += sizetrailer; /*advance to next sequential record*/
00517         } /*while*/
00518     
00519     /*finished the sequential scan*/
00520     
00521     (**hs).seqctfree = ctfree; /*copy returned values*/
00522     
00523     (**hs).seqctinuse = ctinuse;
00524     
00525     (**hs).seqsizefree = sizefree;
00526     
00527     (**hs).seqsizeinuse = sizeinuse;
00528     
00529     (**hs).ctinconsistencies = ctincon;
00530     
00531     statsupdate ();
00532     
00533     /*calculate logical block usage*/
00534 
00535     if (!flincludeusedblocks)
00536         return (true);
00537     
00538     #ifdef SMART_DB_OPENING
00539         statsblockinuse ((**databasedata).u.extensions.availlistblock, nil);
00540     #endif
00541     
00542     shellpushrootglobals (statswindow);
00543     
00544     initbeachball (right); /*reverse direction again*/
00545     
00546     (*shellglobals.findusedblocksroutine) (); /*traverses all database structures*/
00547     
00548     shellpopglobals ();
00549     
00550     return (true);
00551     } /*statscompute*/
00552 
00553 
00554 static boolean statsdispose (void) {
00555     
00556     disposehandle ((Handle) statsdata);
00557     
00558     return (true);
00559     } /*statsdispose*/
00560 
00561 
00562 static boolean statsmousedown (Point pt, tyclickflags flags) {
00563 #pragma unused (pt, flags)
00564 
00565     /*
00566     smashrect ((**statswindowinfo).contentrect);
00567     
00568     statscompute ();
00569     */
00570     
00571     return (true);
00572     
00573     } /*statsmousedown*/
00574 
00575 
00576 boolean statsstart (void) {
00577     
00578     /*
00579     set up callback routines record, and link our data into the shell's 
00580     data structure.
00581     */
00582     
00583     ptrcallbacks statscallbacks;
00584     register ptrcallbacks cb;
00585     
00586     shellnewcallbacks (&statscallbacks);
00587     
00588     cb = statscallbacks; /*copy into register*/
00589     
00590     loadconfigresource (idstatsconfig, &(*cb).config);
00591         
00592     (*cb).configresnum = idstatsconfig;
00593         
00594     (*cb).windowholder = &statswindow;
00595     
00596     (*cb).dataholder = (Handle *) &statsdata;
00597     
00598     (*cb).infoholder = &statswindowinfo; 
00599     
00600     (*cb).updateroutine = &statsupdate;
00601     
00602     (*cb).disposerecordroutine = &statsdispose;
00603     
00604     (*cb).mouseroutine = &statsmousedown;
00605     
00606     return (true);
00607     } /*statsstart*/
00608 
00609 
00610 static boolean statsfindwindow (void) {
00611     
00612     register boolean fl;
00613     
00614     fl = shellfindwindow (
00615         
00616         idstatsconfig, &statswindow, &statswindowinfo, 
00617         
00618         (Handle *) &statsdata);
00619         
00620     return (fl);
00621     } /*statsfindwindow*/
00622 
00623 
00624 static boolean statsnewwindow (void) {
00625     
00626     WindowPtr w;
00627     hdlwindowinfo hw;
00628     bigstring bstitle;
00629     Rect rzoom, rwindow;
00630     hdlwindowinfo hparent;
00631     Handle hdata;
00632     
00633     if (!shellgetfrontrootinfo (&hparent)) /*our parent is the frontmost root window*/
00634         return (false);
00635     
00636     shellgetwindowcenter (hparent, &rzoom);
00637     
00638     if (!newclearhandle (sizeof (tystatsrecord), &hdata))
00639         return (false);
00640     
00641     rwindow.top = -1; /*accept default*/
00642     
00643     getstatsstring (idwindowtitle, bstitle);
00644     
00645     if (!newchildwindow (idstatsconfig, hparent, &rwindow, &rzoom, bstitle, &w)) {
00646         
00647         disposehandle ((Handle) hdata);
00648         
00649         return (false);
00650         }
00651         
00652     getwindowinfo (w, &hw);
00653     
00654     (**hw).hdata = hdata;
00655     
00656     /*ccnewsubwindow (messagewindowinfo, ixmsginfo);*/
00657     
00658 //  shellpushglobals (statswindow); 
00659     
00660     #if TARGET_API_MAC_CARBON == 1
00661     
00662         SetThemeWindowBackground (w, kThemeBrushModelessDialogBackgroundActive, false);
00663         
00664     #endif
00665 
00666     windowzoom (w);
00667     
00668 //  shellpopglobals ();
00669     
00670     statswindow = w;
00671 
00672     return (true);
00673     } /*statsnewwindow*/
00674          
00675     
00676 boolean dbstatsmessage (hdldatabaserecord hdb, boolean flincludeusedblocks) {
00677     
00678     if (!statsfindwindow ()) {
00679         
00680         if (!statsnewwindow ()) /*sets dbstats.c globals if it worked*/
00681             return (false);
00682         }
00683     
00684     if (optionkeydown ())   
00685         windowbringtofront (statswindow);
00686     
00687     shellpushglobals (statswindow);
00688     
00689     smashrect ((**statswindowinfo).contentrect);
00690     
00691     if (hdb != nil)
00692         dbpushdatabase (hdb);
00693 
00694     statscompute (flincludeusedblocks);
00695     
00696     if (hdb != nil)
00697         dbpopdatabase ();
00698 
00699     shellpopglobals ();
00700     
00701     return (true);
00702     } /*dbstatsmessage*/
00703     
00704     

Generated on Wed May 31 18:19:46 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6