home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Storage / Bento / SessHdr.cpp < prev    next >
Encoding:
Text File  |  1996-08-28  |  10.4 KB  |  392 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SessHdr.cpp
  3.  
  4.     Contains:    Implementation of sessionRoutinesMetahandler and its
  5.                         associated handlers.
  6.  
  7.     Owned by:    David McCusker
  8.  
  9.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.          <5>     8/13/96    DM        1362809,1376080: in ODSessionMustHave
  14.                                     CMAllocReserve() check for fatal errors or
  15.                                     disabled containers;  to ODBentoFatalError
  16.                                     add parameter that disallow fatal error
  17.                                     suppression.
  18.          <4>     6/14/96    NP        10020: remove warnings.
  19.          <3>     5/23/96    DH        1344338: Force quit of document when
  20.                                     dragging 'Bad' file or Container. Correctly
  21.                                     signal fatal errors when out of memory.
  22.                                     This will properly signal the fatal error
  23.                                     condition to the Container Suite.
  24.          <2>     3/29/96    DM        1296171: add booleans and ODBentoFatal-
  25.                                     Error() to process fatal container errors
  26.                                     through private API which shows a quitting
  27.                                     alert and exits to shell.
  28.          <6>    10/24/95    jpa        1293441: DM: Bento memory reserve.
  29.          <5>    10/20/95    VL        1293256: THROW kODBentoErr for all Bento
  30.                                     errors.
  31.          <4>     5/26/95    VL        1251403: Multithreading naming support.
  32.          <3>     6/20/94    CC        ODMemoryHeap* changed to ODMemoryHeapID.
  33.          <2>     6/15/94    RR        ODHeap -> ODMemoryHeap
  34.          <1>     5/27/94    VL        first checked in
  35.  
  36.     To Do:
  37.     In Progress:
  38.         
  39. */
  40.  
  41. //==============================================================================
  42. // Theory of Operation
  43. //==============================================================================
  44.  
  45. /*
  46.  
  47.     This file contains a fully documented example of the set of session handlers and its
  48.     metahandler as it would be used by the Container Manager CMStartSession() routine.
  49.  
  50.     When you call CMStartSession() you pass a pointer to a metahandler that is used to get
  51.     the addresses of the error reporting, memory allocator and memory deallocator routines.
  52.     Possibly others might be defined in the future.
  53.     
  54. */
  55.  
  56. #ifndef _SESSHDR_
  57. #include "SessHdr.h"
  58. #endif
  59.  
  60. #ifndef _ODDEBUG_
  61. #include "ODDebug.h"
  62. #endif
  63.  
  64. #ifndef _USERSRCM_
  65. #include "UseRsrcM.h"
  66. #endif
  67.  
  68. #ifndef _DLOGUTIL_
  69. #include "DlogUtil.h"
  70. #endif
  71.  
  72. #ifndef _EXCEPT_
  73. #include "Except.h"
  74. #endif
  75.  
  76. #ifndef __CM_API__
  77. #include "CMAPI.h"
  78. #endif
  79.  
  80. #ifndef _ODMEMORY_
  81. #include "ODMemory.h"
  82. #endif
  83.  
  84. #ifndef _PLFMDEF_
  85. #include "PlfmDef.h"
  86. #endif
  87.  
  88. #ifndef _BENTODEF_
  89. #include "BentoDef.h"
  90. #endif
  91.  
  92. #ifndef _MEMMGR_
  93. #include "MemMgr.h"
  94. #endif
  95.  
  96. #ifndef _STORRSRC_
  97. #include "StorRsrc.h"
  98. #endif
  99.  
  100. #include <stddef.h>
  101. #include <stdlib.h>
  102. #include <stdio.h>
  103. #include <string.h>
  104. #include <stdarg.h>
  105.  
  106. #pragma segment SessHdr
  107.  
  108. //==============================================================================
  109. // Function Prototype
  110. //==============================================================================
  111.  
  112.     CM_CFUNCTIONS
  113.     
  114.  CMHandlerAddr CM_FIXEDARGS sessionRoutinesMetahandler(CMType targetType, CMconst_CMGlobalName operationType);
  115.                                                                 
  116.  static void CM_VARARGS error_Handler(CMErrorNbr errorNumber, ...);
  117.  static void CM_PTR * CM_FIXEDARGS alloc_Handler(CMSize size, CMRefCon sessionRefCon);
  118.  static void CM_FIXEDARGS free_Handler(CMPtr ptr, CMRefCon sessionRefCon);
  119.                                                                  
  120.     CM_END_CFUNCTIONS
  121.  
  122. //------------------------------------------------------------------------------
  123. // sessionRoutinesMetahandler
  124. //------------------------------------------------------------------------------
  125. CMHandlerAddr CM_FIXEDARGS sessionRoutinesMetahandler( CMType targetType,
  126.                                                        CMconst_CMGlobalName operationType )
  127. {
  128.     static char *operationTypes[] = {CMErrorOpType,                    /*  0 */ /*  Operation Types    */
  129.                                      CMAllocOpType,                    /*  1 */
  130.                                      CMFreeOpType,                    /*  2 */
  131.                                      NULL};
  132.     char      **t;
  133.     CMType ignored = targetType;
  134.     
  135.     /* Look up the operation type in the operationTypes table above...                                */
  136.     
  137.     t = operationTypes - 1;
  138.     while (*++t) if (strcmp((char *)operationType, *t) == 0) break;
  139.  
  140.     /* Now that we got it (hopefully), return the appropriate routine address...                    */
  141.     
  142.     switch (t - operationTypes) {
  143.         case  0:    return ((CMHandlerAddr)error_Handler);                        /* CMErrorOpType                 */
  144.         case  1:    return ((CMHandlerAddr)alloc_Handler);                        /* CMAllocOpType                 */
  145.         case  2:    return ((CMHandlerAddr)free_Handler);                        /* CMFreeOpType                 */
  146.         
  147.         default:    return (NULL);                                                /* huh?                            */
  148.     }
  149. }
  150.  
  151. //------------------------------------------------------------------------------
  152. // ODBentoFatalError
  153. //------------------------------------------------------------------------------
  154.  
  155. #if ODDebug
  156. void BREAK( const char[] );
  157. #endif
  158.  
  159. ODBoolean gODBentoFatalErrorHasOccurred = kODFalse;
  160. ODBoolean gODDelayBentoFatalError = kODFalse;
  161. ODBoolean gODSuppressBentoFatalError = kODFalse;
  162.  
  163. void ODBentoFatalError(ODBoolean allowSuppress); // prototype
  164.  
  165. void ODBentoFatalError(ODBoolean allowSuppress)
  166. {
  167.     
  168.     // The allowSuppress parameter was added so that some places, like the
  169.     // shell, can force a fatal error without suppression or delay even if
  170.     // the booleans controlling those conditions have become garbled due to
  171.     // unfortunate flow of control with exceptions.
  172.     
  173.     if ( gODSuppressBentoFatalError && allowSuppress )
  174.     {
  175.         // Do not break here because it is really annoying when
  176.         // suppressing errors associated with IsValidStorageUnitRef():
  177.         
  178. //#if ODDebug
  179. //        BREAK("clipboard Bento error is non-fatal ...");
  180. //#endif
  181.     }
  182.     else
  183.     {
  184.         gODBentoFatalErrorHasOccurred = kODTrue;
  185.  
  186.         if ( gODDelayBentoFatalError && allowSuppress )
  187.         {
  188. #if ODDebug
  189.             BREAK("fatal container error delayed, continuing...");
  190. #endif
  191.         }
  192.         else
  193.         {
  194. #if ODDebug
  195.             BREAK("about to show fatal Bento error alert...");
  196. #endif
  197.             {
  198.                 TRY{
  199.                     CUsingLibraryResources r;
  200.                     InitCursor();
  201.                     ::Alert(kODAlertFatalContainerError, kODNULL);
  202.                 }CATCH_ALL{
  203.                     WARN("cannot show fatal Bento err alert - quitting...");
  204.                 }ENDTRY
  205.             }
  206.             // make sure CUsingLibraryResources goes out of scope first...
  207.             ::ExitToShell(); // bye bye process
  208.         }
  209.     }
  210. }
  211.  
  212. //------------------------------------------------------------------------------
  213. // error_Handler
  214. //------------------------------------------------------------------------------
  215.  
  216. static void CM_VARARGS error_Handler(CMErrorNbr errorNumber, ...)
  217. {
  218.     va_list inserts;
  219.     char errorString[256];
  220.  
  221.     va_start(inserts, errorNumber);
  222.     CMVErrorToFormattedString(errorString, 256, errorNumber, inserts);
  223.     va_end(inserts);
  224.  
  225.     ODBentoFatalError(/*allowSuppress*/ kODTrue);
  226.     THROW(kODErrBentoErr, errorString);
  227. }
  228.  
  229. //------------------------------------------------------------------------------
  230. // ODSession_Trace
  231. //------------------------------------------------------------------------------
  232.  
  233. #ifdef ODDebugBentoSize
  234. static void ODSession_Trace(ODSessionRefCon* session, long size)
  235. {
  236.     ODBoolean reverse = (session->fUp && size < 0) || (!session->fUp && size > 0);
  237.     ODULong oldTotal = session->fTotal;
  238.     
  239.     if ( size < 0 ) // freeing
  240.     {
  241.         if (reverse) // previous total was a local high
  242.             session->fHigh = session->fTotal;
  243.  
  244.         session->fUp = kODFalse;
  245.         long amount = -size;
  246.         if (session->fTotal < amount)
  247.             session->fTotal = amount;
  248.         else
  249.             session->fTotal -= amount;
  250.             
  251.     }
  252.     else //allocating
  253.     {
  254.         if (reverse) // previous total was a local low
  255.             session->fLow = session->fTotal;
  256.  
  257.         session->fUp = kODTrue;
  258.         session->fTotal += size;
  259.     }
  260.     
  261.     if (session->fTotal > session->fHighest)
  262.         session->fHighest = session->fTotal;
  263.     
  264.     long diff = ((long) session->fTotal - (long) session->fMark);
  265.     ODBoolean mark = (diff > 2048 || diff < -2048);
  266.     if (mark)
  267.         session->fMark = session->fTotal;
  268.         
  269.     if (reverse || mark)
  270.     {
  271.         if ( session->fUp )
  272.             somPrintf("•alloc•(%ld) [%lu] : %lu UP FROM %lu\n", 
  273.                 size,  session->fHighest, session->fTotal, session->fLow);
  274.         else
  275.             somPrintf("•free•(%ld) [%lu] : %lu down from %lu\n", 
  276.                 size,  session->fHighest, session->fTotal, session->fHigh);        
  277.     }
  278.     else
  279.     {
  280.         if ( session->fUp )
  281.             somPrintf("/ %ld \\\n", size);
  282.         else 
  283.             somPrintf("\\ %ld /\n", size);
  284.     }
  285. }
  286. #endif
  287.  
  288. //------------------------------------------------------------------------------
  289. // alloc_Handler
  290. //------------------------------------------------------------------------------
  291.  
  292. static void CM_PTR * CM_FIXEDARGS alloc_Handler(CMSize size, CMRefCon sessionRefCon)
  293. {
  294.     ODMemoryHeapID        heap = kDefaultHeapID;
  295.     ODSessionRefCon* sessRc = (ODSessionRefCon*) sessionRefCon;
  296.     
  297.     if (sessionRefCon != kODNULL)
  298.         heap = sessRc->heap;
  299.  
  300.     void* block = MMAllocate(size);
  301.     if ( !block )
  302.     {
  303.         if ( sessRc->cmAllocReserveBlock )
  304.         {
  305.             void* reserve = sessRc->cmAllocReserveBlock;
  306.             sessRc->cmAllocReserveBlock = kODNULL;
  307.             
  308.             MMFree(reserve);
  309.             block = MMAllocate(size);
  310.         }
  311.     }
  312.     if ( !block )
  313.         ODBentoFatalError(/*allowSuppress*/ kODTrue);
  314.         //THROW( kODErrOutOfMemory ); // should be kFatalError
  315.  
  316. #ifdef ODDebugBentoSize
  317.     long blockSize = (long) MMBlockSize(block) + 8;
  318.         
  319.     ODSession_Trace(sessRc, (long) blockSize); 
  320.  
  321.     return block;
  322. #else
  323.  
  324.     // return ODNewPtr(size, heap);
  325.     return block;
  326. #endif
  327.         
  328. }
  329.  
  330. //------------------------------------------------------------------------------
  331. // free_Handler
  332. //------------------------------------------------------------------------------
  333.  
  334.  
  335. static void CM_FIXEDARGS free_Handler(CMPtr ptr, CMRefCon sessionRefCon)
  336. {
  337.  
  338. #ifdef ODDebugBentoSize
  339.     if ( ptr )
  340.     {
  341.         long blockSize = (long) MMBlockSize(ptr) + 8;
  342.         ODSession_Trace((ODSessionRefCon*) sessionRefCon,  - blockSize ); 
  343.     }
  344. #else
  345. ODUnused(sessionRefCon);
  346. #endif
  347.  
  348.     ODDisposePtr(ptr);
  349. }
  350.  
  351. //------------------------------------------------------------------------------
  352. // reserve
  353. //------------------------------------------------------------------------------
  354.  
  355.  
  356. // void*            cmAllocReserveBlock;
  357. // CMSize           cmAllocReserveSize;
  358.  
  359. void ODSessionMustHaveCMAllocReserve(CMContainer cmContainer)
  360. {
  361.     if ( gODBentoFatalErrorHasOccurred )
  362.     {
  363.         // If a fatal error has occurred, then fail on all Bento calls. 
  364.         // Only throw if fatal errors are being suppressed or delayed.
  365.         if ( gODDelayBentoFatalError || gODSuppressBentoFatalError )
  366.             THROW( kODErrFatalContainerError );
  367.         else
  368.             ODBentoFatalError(/*allowSuppress*/ kODTrue);
  369.     }
  370.         
  371.     if (cmContainer)
  372.     {    
  373.         if ( CMIsDisabledContainer(cmContainer) )
  374.             THROW( kODErrBentoErr );
  375.         
  376.         ODSessionRefCon* src = (ODSessionRefCon*) CMGetSessionRefCon(cmContainer);
  377.         if ( src && !src->cmAllocReserveBlock )
  378.             src->cmAllocReserveBlock = ODNewPtr(src->cmAllocReserveSize, src->heap);
  379.     }
  380. }
  381.  
  382. void ODSessionRestoreCMAllocReserve(CMContainer cmContainer)
  383. {
  384.     if (cmContainer)
  385.     {
  386.         ODSessionRefCon* src = (ODSessionRefCon*) CMGetSessionRefCon(cmContainer);
  387.         if ( src && !src->cmAllocReserveBlock )
  388.             src->cmAllocReserveBlock = MMAllocate( src->cmAllocReserveSize );
  389.     }
  390. }
  391.  
  392.