home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osr1.exe / src / CMSesOps.c < prev    next >
C/C++ Source or Header  |  1997-03-21  |  18KB  |  396 lines

  1. /* @(#)Z 1.5 com/src/cm/CMSesOps.c, odstorage, od96os2, odos29712d 97/03/21 17:19:33 (96/10/29 09:17:05) */
  2. /*====START_GENERATED_PROLOG======================================
  3.  */
  4. /*
  5.  *   COMPONENT_NAME: odstorage
  6.  *
  7.  *   CLASSES: none
  8.  *
  9.  *   ORIGINS: 82,27
  10.  *
  11.  *
  12.  *   (C) COPYRIGHT International Business Machines Corp. 1995,1996
  13.  *   All Rights Reserved
  14.  *   Licensed Materials - Property of IBM
  15.  *   US Government Users Restricted Rights - Use, duplication or
  16.  *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  17.  *       
  18.  *   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  19.  *   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20.  *   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21.  *   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  22.  *   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  23.  *   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  24.  *   OR PERFORMANCE OF THIS SOFTWARE.
  25.  */
  26. /*====END_GENERATED_PROLOG========================================
  27.  */
  28.  
  29. /*
  30.     File:          CMSesOps.c  
  31.  
  32.     Contains:    Container Manager Session Operations
  33.  
  34.     Written by:    Ira L. Ruben
  35.  
  36.     Owned by:    Ed Lai
  37.  
  38.     Copyright:    ⌐ 1992-1994 by Apple Computer, Inc., all rights reserved.
  39.  
  40.     Change History (most recent first):
  41.  
  42.          <3>     9/29/94    RA        1189812: Mods for 68K build.
  43.          <2>     8/26/94    EL        #1181622 Ownership update.
  44.          <1>      2/3/94    EL        first checked in
  45.          <3>    11/22/93    EL        Add refcon for alloc and free handers.
  46.          <2>     10/4/93    EL        nextContainer is not used in CMEndSession
  47.  
  48.     To Do:
  49. */
  50.  
  51. /*---------------------------------------------------------------------------*
  52.  |                                                                           |
  53.  |                           <<<   CMSesOps.c   >>>                          |
  54.  |                                                                           |
  55.  |                    Container Manager Session Operations                   |
  56.  |                                                                           |
  57.  |                               Ira L. Ruben                                |
  58.  |                                  7/27/92                                  |
  59.  |                                                                           |
  60.  |                    Copyright Apple Computer, Inc. 1992-1994               |
  61.  |                           All rights reserved.                            |
  62.  |                                                                           |
  63.  *---------------------------------------------------------------------------*
  64.  
  65.  The API routines in theis file handle Container Manager session operations.  All Container
  66.  Manager calls take place in the context of a "session".  A session must be established
  67.  before any other Container Manager calls are performed and the session closed when all
  68.  calls are completed.
  69.  
  70.  Sessions are referenced in terms of session refNum's and passed to various other API
  71.  routines.  Basically a session represents "global information" (data) the Container
  72.  Manager needs to communicate among its internal routines.  This is information global
  73.  to all containers of a session.
  74.  
  75.  There is nothing prohibiting multiple sessions, although there is no reason for it either.
  76.  A session "refCon" is provided to allow the user to add additional information.
  77. */
  78.  
  79.  
  80. #include <stddef.h>
  81. #include <stdio.h>
  82.  
  83. #ifndef __CMVERSION__
  84. #include "CMVers.h"   
  85. #endif
  86. #ifndef __CMTYPES__
  87. #include "CMTypes.h"
  88. #endif
  89. #ifndef __CM_API__
  90. #include "CMAPI.h"
  91. #endif
  92. #ifndef __LISTMGR__
  93. #include "ListMgr.h"
  94. #endif
  95. #ifndef __SESSIONDATA__
  96. #include "Session.h"          
  97. #endif
  98. #ifndef __HANDLERS__
  99. #include "Handlers.h"
  100. #endif
  101. #ifndef __CONTAINEROPS__
  102. #include "Containr.h"  
  103. #endif
  104. #ifndef __BUFFEREDIO__
  105. #include "BufferIO.h"  
  106. #endif
  107. #ifndef __GLOBALNAMES__
  108. #include "GlbNames.h"   
  109. #endif
  110. #ifndef __ERRORRPT__
  111. #include "ErrorRpt.h"      
  112. #endif
  113.  
  114.                                                                     CM_CFUNCTIONS
  115.  
  116. /* The following generates a segment directive for Mac only due to 32K Jump Table             */
  117. /* Limitations.  If you don't know what I'm talking about don't worry about it.  The        */
  118. /* default is not to generate the pragma.  Theoritically unknown pragmas in ANSI won't    */
  119. /* choke compilers that don't recognize them.  Besides why would they be looked at if        */
  120. /* it's being conditionally skipped over anyway?  I know, famous last words!                        */
  121.  
  122. #if CM_MPW
  123. #pragma segment SessionOps
  124. #endif
  125.                                                                                                                                         
  126.  
  127. /*----------------------------------------------------------*
  128.  | Copyright Apple Computer, Inc. 1991-1992 by Ira L. Ruben |
  129.  *----------------------------------------------------------*
  130.  
  131.  This bit of nonsense is to "bury" the copyright notice into a number of places in the
  132.  code.  We define the notice as a string macro so that we can call this routine.  
  133.  The call is done to make sure it is not dead-code-stripped on systems like the Mac MPW
  134.  linker that are smart enough to do such things.
  135.  
  136.  Note, when generating the code using Mac MPW, the call will generate the copyright in the
  137.  code since we compile with the -b2 option in the Mac MPW developement system C compiler.
  138.  
  139.  The actual copyright string macro, called Copyright, is defined in the header CMVersion.h.
  140.  Note, that we repeat the copyright string here as the name of this function just to be
  141.  "wise guys" (it comes from the Copyright_Apple_Computer macro).
  142. */
  143.  
  144. static char CM_PTR * CM_NEAR Copyright_Apple_Computer(char *c)
  145. {
  146.     return (c = Copyright);
  147. }
  148.  
  149.  
  150. /*-----------------------------------------------------------------*
  151.  | CMStartSession - initialize the Container Manager for a session |
  152.  *-----------------------------------------------------------------*
  153.  
  154.  This call is used for all global initialization of a Container Manager session.  It MUST
  155.  be called BEFORE ANY OTHER Container Manager routine.  If not, then every API routine will
  156.  (try to) exit without doing anything (assuming it doesn't blow up before it can detect
  157.  that CMStartSession() wasn't called).
  158.  
  159.  An anonomous non-NULL pointer is returned if initialization is successful.  NULL is 
  160.  returned for failure unless the error reporter (discussed below) aborts execution.  
  161.  
  162.  The returned pointer MUST be passed to every CMOpen[New]Container() that follows.  It
  163.  represents a pointer to private Container Manager data that is global to all open
  164.  containers.  The intent is that this data is unique to the currently running session (or
  165.  task).  The caller may extend this data to include his or her own special per-session
  166.  information.  This is done with the "reference constant" (refCon) passed as the last
  167.  parameter to this routine.  It is saved in the session data.  The refCon can be anything.
  168.  But usually it will be a pointer to the caller's own session data.  
  169.  
  170.  Since the session global data is global to all containers, all containers must have
  171.  accesses to it.  That is why it is passed to CMOpen[New]Container().  Thus all accesses
  172.  to the session data are through container refNums (CMContainer).
  173.  
  174.  Routines are provided to allow the user to set or get the session refCon as a function
  175.  of a container refNum (see CMGetSessionRefCon() and CMSetSessionRefCon()).
  176.  
  177.  CMStartSession() takes as its main parameter the address of a special metahandler. It is 
  178.  similar in function to CMSetMetaHandler() except that here the metahandler is container
  179.  independent and is used to get the address of the error reporting, memory allocator and
  180.  memory deallocator handler routines.  ALL of these handlers MUST be defined.
  181.  
  182.  The metahandler is called with predified operation types for the handlers.  The associated
  183.  handler address is returned.  If any are NULL, NULL will be returned.  If we at least get
  184.  the error handler address, then an error will be reported prior to return.  If we don't
  185.  get it, you're dead!
  186.  
  187.  All three handler routines are available to the user, usually a handler writer through
  188.  the CMMalloc(), CMFree(), and CMError() API calls.
  189.  
  190.  Note that the session data is allocated with the memory allocator returned from the
  191.  metahandler.  Also the session pointer doubles as a switch which is used by all the API
  192.  CM... routines to see if CMStartSession() was indeed called.  If it is NULL, all the
  193.  routines just exit without doing anything.  But there is NO guarantee that the pointer
  194.  was initialized as NULL!  Hence most likely the user will blow up before we ever get a
  195.  chance to get at the session pointer from a container refNum.  It's the best we can do.
  196.  Moral -- Follow the rules and call CMStartSession().
  197. */
  198.  
  199. CMSession CM_FIXEDARGS CMStartSession(CMMetaHandler metaHandler, CMRefCon sessionRefCon)
  200. {
  201.     SessionGlobalDataPtr sessionData;
  202.     
  203.     /* Adkins -- C++ allows static assignment of arrays at compile time only */
  204.     #ifdef __MWERKS__
  205.     char                                 *version = CMVersion;
  206.     #else
  207.     char                                version[] = "CMVersion"; /* Adkins -- kludge to get this to compile 
  208.                                                                                                     tonight */
  209.     #endif
  210.     
  211.     MallocProto                  cmMalloc;
  212.     FreeProto                      cmFree;
  213.     ErrorProto                   cmReportError;
  214.     
  215.     /* Make the Apple lawyers happy.  The following has the effect of burying a copyright    */
  216.     /* notice into the code and, because we're doing a call, stopping any possible dead        */
  217.     /* code stripping.                                                                                                                                      */
  218.     
  219.     Copyright_Apple_Computer(Copyright);
  220.     
  221.     /* Use the provided metahandler to get the routine addresses of the error reporting,    */
  222.     /* malloc, and free handlers.  First the error handler...                                                            */
  223.     
  224.     if (metaHandler == NULL) return (NULL);        /* safety                                                                        */
  225.     
  226.     cmReportError = *(ErrorProto)(*metaHandler)(NULL, (CMGlobalName)CMErrorOpType);
  227.     if (cmReportError == NULL) return (NULL);
  228.     
  229.     /* Now we can go after the other handlers and report errors if we don't get 'em...         */
  230.     
  231.     cmMalloc = *(MallocProto)(*metaHandler)(NULL, (CMGlobalName)CMAllocOpType);
  232.     cmFree      = *(FreeProto)(*metaHandler)(NULL, (CMGlobalName)CMFreeOpType);
  233.     
  234.     if (cmMalloc == NULL || cmFree == NULL) { 
  235.         (*cmReportError)(CM_err_MissingHandler);
  236.         return (NULL);
  237.     }
  238.     
  239.     /* Allocate the space for the session (task) global data area...                                            */
  240.     
  241.     sessionData = (SessionGlobalDataPtr)(*cmMalloc)((CMSize)(sizeof(SessionGlobalData) + strlen(version)), sessionRefCon);
  242.     if (sessionData == NULL) {
  243.         (*cmReportError)(CM_err_NoSession);
  244.         return (NULL);
  245.     }
  246.         
  247.     /* Initialize the session global data...
  248.                                                                                                                      Prime user (client)                    */
  249.     sessionData->cmMalloc                     = cmMalloc;                            /* Handlers.h                                        */
  250.     sessionData->cmFree                         = cmFree;                                /* Handlers.h                                        */
  251.     sessionData->cmReportError          = cmReportError;                /*    ErrorRpt.h                               */
  252.     sessionData->cmTocTblSize             = DefaultIndexTableSize;/*    CMCntOps.c                               */
  253.     sessionData->cmDbgFile                = NULL;                                    /* anywhere                                            */
  254.     sessionData->metaHandlerTable = NULL;                                    /* Handlers.c                                        */
  255.     sessionData->refCon                      = sessionRefCon;                /*   CMHndOps.c                                  */
  256.     sessionData->success                    = true;                                    /* anywhere                                            */
  257.     sessionData->aborting                    = false;                                /*    CMCntOps.c                               */
  258.     cmInitList(&sessionData->openContainers);                            /*    CMCntOps.c                               */
  259.     strcpy(sessionData->cmVersion, version);                            /* actually no one!                            */
  260.     
  261.     #if CMVALIDATE
  262.     sessionData->validate                    = CMDEFAULT_VALIDATE;        /*    ErrorRpt.h                               */
  263.     #endif
  264.     
  265.     return ((CMSession)sessionData);                    /* success                                                                    */
  266. }
  267.  
  268.  
  269. /*------------------------------------------------------*
  270.  | CMEndSession - terminate a Container Manager session |
  271.  *------------------------------------------------------*
  272.  
  273.  This should be called as the LAST call to the Container Manager.  If frees the space
  274.  allocated for the session by CMStartSession() and optionally calls CMCloseContainer() on
  275.  all remaining open containers.
  276.  
  277.  The sessionData specifies the session data pointer returned from CMStartSession().  If
  278.  closeOpenContainers is passed as 0 (i.e., "false"), then an error is reported for each
  279.  container that has NOT been explicitly closed by CMCloseContainer(). If true (non-zero) is
  280.  specified, then the Container Manager will call CMCloseContainer() for you for each
  281.  remaining open container.
  282.  
  283.  The difference between specifying closeOpenContainers as false, as opposed to true, is
  284.  that open containers are NOT formally closed.  They remain in whatever (open) state they
  285.  currently happen to be in when the error is reported.  This is generally true whenever
  286.  any error is reported.  When true is passed, open containers are not treated as an error
  287.  condition, and closed by calling the API CMCloseContainer() routine just as any API caller
  288.  would.  This case can be viewed as a "close all" case.
  289.  
  290.  No further calls should be done once this routine is called.  All memory occupied by the
  291.  containers, as well as the session itself are freed.
  292. */
  293.  
  294. void CM_FIXEDARGS CMEndSession(CMSession sessionData, CMBoolean closeOpenContainers)
  295. {
  296.     SessionGlobalDataPtr session = (SessionGlobalDataPtr)sessionData;
  297.     ContainerPtr container;
  298.  
  299.     if (sessionData == NULL) return;                            /* exit if there is no session to close    */
  300.     
  301.     /* Go through the list of open containers and do what it says above...                                */
  302.     
  303.     container = (ContainerPtr)cmGetListHead(&session->openContainers);
  304.     
  305.     while (container != NULL) {                                        /* look at each open container...                */
  306.         if (closeOpenContainers)                                        /* if user wants US to close it...            */
  307.             CMCloseContainer((CMContainer)container);    /* ...we'll do it for the "lazy" user        */
  308.         else {                                                                            /* if open containers aren't expected...*/
  309.             ERROR1(CM_err_StillOpen, CONTAINERNAME);    /* ...YELL loudly!                                            */
  310.             cmFreeAllGlobalNames(&container->globalNameTable); /* if error reporter returns...*/
  311.             cmFreeAllIOBuffers(container);                                         /* ...free any I/O buffers            */
  312.             cmFreeTOC(container, &container->toc);                         /* ...free container memory        */
  313.             CMfree(cmDeleteListCell(&session->openContainers, container));
  314.         }
  315.         
  316.         /* We always use the container list head because the open container queue could            */
  317.         /* contain embedded containers.  These "go away" implicitly by closing the embedde's*/
  318.         /* parents.  That will remove them from the open queue.  By using the queue head we    */
  319.         /* always get the "next" available truly open container.                                                        */
  320.         
  321.         container = cmGetListHead(&session->openContainers);
  322.     }
  323.     
  324.     /* Now that the containers are disposed of, we can free the session data.  This    */
  325.     /* is the methandler table and the session data itself.  After that the user is on         */
  326.     /* his (or her) own!                                                                                                                                    */
  327.     
  328.     cmFreeAllMetaHandlers(session);                                /* there go the metahandler names                */
  329.     
  330.     SessionFree(session);                                                    /* and there goes the session itself        */
  331. }
  332.  
  333.  
  334. /*----------------------------------*
  335.  | CMAbortSession - abort a session |
  336.  *----------------------------------*
  337.  
  338.  ALL containers are closed WITHOUT further writing to those containers, i.e., as if all
  339.  containers were opened for reading even when opened for writing.  The session is then 
  340.  closed with CMEndSession().  This is intended to be used to abort the session from
  341.  unrecoverable errors.
  342.  
  343.  All memory allocated by ALL the container data structures are freed (if possible) and the
  344.  container close handlers called to physically close the containers.  All dynamic values
  345.  currently in use are released in an attempt to allow them to properly clean up any files
  346.  and memory allocated by their handlers.  No further API calls should be done.
  347.  
  348.  Note: CMAbortSession() is basically a CMAbortContainer() for EACH currently open container
  349.  followed by a CMEndSession().  Also, this routine WILL return to its caller.  It is up to
  350.  the user to actually abort execution if that is required.
  351. */
  352.  
  353. void CM_FIXEDARGS CMAbortSession(CMSession sessionData)
  354. {
  355.     if (sessionData == NULL) return;                                            /* exit if there is no session    */
  356.  
  357.     if (((SessionGlobalDataPtr)sessionData)->aborting)        /* ignore recursive aborts!            */
  358.         return;                                            
  359.     
  360.     ((SessionGlobalDataPtr)sessionData)->aborting = true;    /* throw the deadly switch            */
  361.     
  362.     CMEndSession(sessionData, true);                                            /* abort all containers                 */
  363. }
  364.  
  365.  
  366. /*--------------------------------------------------------*
  367.  | CMGetSessionRefCon - return the current session refCon |
  368.  *--------------------------------------------------------*
  369.  
  370.  This routine can be used to get at the user's session refCon saved as part of the session
  371.  data created by CMStartSession().  The session data is "tied" to each container created by
  372.  CMOpen[New]Container().  Thus the refCon is accessed via a container refNum.
  373. */
  374.  
  375. CMRefCon CM_FIXEDARGS CMGetSessionRefCon(CMContainer container)
  376. {
  377.     return ((container == NULL || SESSION == NULL) ? NULL : SESSION->refCon);
  378. }
  379.  
  380.  
  381. /*-----------------------------------------------------*
  382.  | CMSetSessionRefCon - change the session data refCon |
  383.  *-----------------------------------------------------*
  384.  
  385.  This routine may be called to change the user's session refCon associated with the session
  386.  data.  As with CMGetSessionRefCon() above, the session data is accessed through a
  387.  container refNum.
  388. */
  389.  
  390. void CM_FIXEDARGS CMSetSessionRefCon(CMContainer container, CMRefCon refCon)
  391. {
  392.     SESSION->refCon = (container == NULL || SESSION == NULL) ? NULL : refCon;
  393. }
  394.                                                           
  395.                                                             CM_END_CFUNCTIONS
  396.