G:/ScriptBasic/source/extensions/mt/interface.c

Go to the documentation of this file.
00001 /* FILE: mt.c
00002 
00003 This file contains code fot the multi-thread support module.
00004 
00005 For further information read the accopaining documentation that 
00006 I am going to write when I am ready programming this module. Right 
00007 now I just start to write it.
00008 
00009 Peter Verhas March 6, 2001.
00010 
00011 --GNU LGPL
00012 This library is free software; you can redistribute it and/or
00013 modify it under the terms of the GNU Lesser General Public
00014 License as published by the Free Software Foundation; either
00015 version 2.1 of the License, or (at your option) any later version.
00016 
00017 This library 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 GNU
00020 Lesser General Public License for more details.
00021 
00022 You should have received a copy of the GNU Lesser General Public
00023 License along with this library; if not, write to the Free Software
00024 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 NTLIBS:
00027 UXLIBS:
00028 DWLIBS: -init __init
00029 
00030 */
00031 #include <stdio.h>
00032 #include <time.h>
00033 #include "../../basext.h"
00034 
00050 /* This declaraton declares the counter and the mutex protecting it that
00051    counts the number of threads loading this library. Note that only the
00052    first call to LoadLibrary/dlopen loads this library the rest is only
00053    returns the pointer to the already loaded library.
00054 
00055    This library was designed to support multithread implementations so that
00056    it allows different threads to access data stored in memory. However each
00057    thread call FreeLibrary/dlclose to release this library. If there is a point
00058    in time when no thread uses this library then the library is unloaded and all
00059    data allocated is lost.
00060 
00061    To keep the library in memory the function besSUB_KEEP returns zero when the
00062    library would be unloaded. Thus exactly one LoadLibrary/dlopen is not followed
00063    by FreeLibrary/dlclose and thus this library remains in memory so long as long
00064    the process is alive.                                                               */
00065 SUPPORT_MULTITHREAD
00066 
00067 static SymbolTable MtVariables,SessionTable;
00068 static MUTEX mxMTVariables,mxSessionCounter,mxSessionTable;
00069 static unsigned long lSessionCounter;
00070 
00071 /* Information that maintains a session. */
00072 typedef struct _SessionInfo {
00073   SHAREDLOCK lckSession;       /* lock for read when used, lock for write when being deleted */
00074   MUTEX mxSession;             /* lock whenever access session symbol table                  */
00075   void *pMemSeg;               /* memory segment for session related memory allocations      */
00076   SymbolTable stSession;       /* session variables symbol table                             */
00077   unsigned long lPingTime;     /* timestamp when the session was alive last time             */
00078   unsigned long lTimeout;      /* timestamp when the session times out (set by BASIC program)*/
00079   unsigned long lTimeStart;    /* timestamp when the session was started                     */
00080   char *pszId;                 /* pointer into the symbol table to the if of the session     */
00081   struct _SessionInfo *prev,*next;
00082   } SessionInfo, *pSessionInfo;
00083 
00084 static pSessionInfo pSessionRoot;
00085 
00086 typedef struct _MtClass {
00087   pSessionInfo AssignedSession;
00088   char *pszSessionId;
00089   } MtClass, *pMtClass;
00090 
00091 typedef struct _MTVariable{
00092   SHAREDLOCK lckV;
00093   VARIABLE vV;
00094   }MTVariable,*pMTVariable;
00095 
00096 
00097 #define MT_ERROR_NOSESSION 0x00080001
00098 #define MT_ERROR_BAD_PROG  0x00080002
00099 #define MT_ERROR_BAD_SESS  0x00080003
00100 
00101 /* Allocate a new session information structure.
00102    Note that this function is NOT reentrant but is called when the MUTEX mxSessionTable is locked.
00103 */
00104 static pSessionInfo AllocNewSession(pSupportTable pSt,void *p){
00105   pSessionInfo pS;
00106   pS = besPROCALLOC(sizeof(SessionInfo));
00107   if( ! pS )return NULL;
00108   pS->pszId = SymbolName(p);
00109   pS->lTimeStart = time(NULL);
00110   /* hook into the double linked list */
00111   pS->next = pSessionRoot;
00112   pS->prev = NULL;
00113   pSessionRoot = pS;
00114   return pS;
00115   }
00116 
00117 static void ReleaseSession(pSupportTable pSt, pSessionInfo pS){
00118 
00119   besLockMutex(&mxSessionTable);
00120 
00121   /* unhook from the double linked list */
00122   if( pS->prev )pS->prev->next = pS->next; else pSessionRoot = pS->next;
00123   if( pS->next )pS->next->prev = pS->prev;
00124 
00125   besPROCFREE(pS);
00126 
00127   besUnlockMutex(&mxSessionTable);
00128   }
00129 
00130 /*
00131 This function is executed as a separate thread when the module is initialized the first time.
00132 It starts the timeout scripts when their time comes.
00133 */
00134 static void time_out_work_thread(void *p){
00135   pSupportTable pSt;
00136   unsigned long lSleepLen;
00137   pSessionInfo pS;
00138   pSt = p;
00139 
00140   if( besCONFIGEX(pSt->pEo->pConfig,"httpd.mt.sleep",NULL,NULL,&lSleepLen,NULL,NULL) )
00141     lSleepLen = 60;
00142 
00143   while(1){
00144     besSLEEP(lSleepLen);
00145     pS = pSessionRoot;
00146     }
00147 
00148 
00149   }
00150 
00151 #define IsUndef(pVar)  ((pVar) == NULL || (pVar)->vType == VTYPE_UNDEF)
00152 
00153 
00154 besSUB_SHUTDOWN
00155 
00156 besEND
00157 
00158 besSUB_START
00159   pMtClass pMT;
00160 
00161   /* This macro increments the thread counter used to help to keep this library in memory 
00162      even those times when the process is idle and no ScriptBasic threads are running. */
00163   INC_THREAD_COUNTER
00164   /* A process level initialization of the module should take place in this function because
00165      the call-back support functions are not accessible when the  function DllMain or _init is
00166      called. On the other hand it has to initialize only once.
00167   */
00168   INITLOCK /* lock the init mutex */
00169   if( iFirst ){ /* if it was not initialized yet*/
00170 
00171     MtVariables = pSt->NewSymbolTable(pSt->Alloc,besPROCMEMORYSEGMENT);
00172     if( MtVariables == NULL )return COMMAND_ERROR_MEMORY_LOW;
00173 
00174     besInitMutex(&mxMTVariables);
00175 
00176     SessionTable = pSt->NewSymbolTable(pSt->Alloc,besPROCMEMORYSEGMENT);
00177     if( SessionTable == NULL )return COMMAND_ERROR_MEMORY_LOW;
00178     besInitMutex(&mxSessionCounter);
00179     besInitMutex(&mxSessionTable);
00180     /* time is just to introduce some randomity */
00181     lSessionCounter = (unsigned long)time(NULL);
00182 
00183     pSessionRoot = NULL;
00184 
00185     /* create the thread that handles timeout script execution */
00186     /* besCreateThread(&hT,time_out_work_thread,pSt->pEo->pSTI); */
00187 
00188     iFirst = 0;/* successful initialization was done*/
00189     }
00190   INITUNLO /* unlock the init mutex */
00191 
00192   besMODULEPOINTER = besALLOC(sizeof(MtClass));
00193   if( besMODULEPOINTER == NULL )return 0;
00194   pMT = (pMtClass)besMODULEPOINTER;
00195   pMT->AssignedSession = NULL;
00196   pMT->pszSessionId = NULL;
00197 
00198   return COMMAND_ERROR_SUCCESS;
00199 besEND
00200 
00262 besFUNCTION(setsession)
00263   char *pszSession;
00264   pMtClass pMT;
00265   void **p;
00266   VARIABLE Argument;
00267   pSessionInfo pS;
00268   unsigned long i;
00269 
00270   pMT = besMODULEPOINTER;
00271   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
00272 
00273   Argument = besARGUMENT(1);
00274   besDEREFERENCE(Argument);
00275   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
00276   Argument = besCONVERT2STRING(Argument);
00277   /* check that the session ID does not contain zero character inside (for security reasons) */
00278   for( i = 0 ; i < STRLEN(Argument) ; i++ )
00279     if( ! STRINGVALUE(Argument)[i] )return MT_ERROR_BAD_SESS;
00280 
00281   besCONVERT2ZCHAR(Argument,pszSession);
00282   /* if this thread already has a session assigned to it then release the session */
00283   pS = pMT->AssignedSession;
00284   if( pMT->pszSessionId )besFREE(pMT->pszSessionId);
00285   if( pS )besUnlockSharedRead(&(pS->lckSession));
00286   pS = pMT->AssignedSession = NULL; /* pS to NULL also just for safety */
00287 
00288   besLockMutex(&mxSessionTable);
00289   p = pSt->LookupSymbol(pszSession,SessionTable,1,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
00290   if( p == NULL ){
00291     besUnlockMutex(&mxSessionTable);
00292     besFREE(pszSession);
00293     return COMMAND_ERROR_MEMORY_LOW;
00294     }
00295   if( *p == NULL ){/* this is a brand new session, most probably it is */
00296     /* count the creation of the new session */
00297     besLockMutex(&mxSessionCounter);
00298     lSessionCounter++;
00299     besUnlockMutex(&mxSessionCounter);
00300 
00301     *p = AllocNewSession(pSt,p);
00302     if( *p == NULL ){
00303       besUnlockMutex(&mxSessionTable);
00304       return COMMAND_ERROR_MEMORY_LOW;
00305       }
00306     pS = pMT->AssignedSession = *p;
00307     besInitMutex(&(pS->mxSession));
00308     besInitSharedLock(&(pS->lckSession));
00309     besLockSharedRead(&(pS->lckSession));
00310     /* Create a new memory segment for the session. */
00311     pS->pMemSeg = besINIT_SEGMENT(pSt->pEo->pMemorySegment,NULL);
00312     if( pS->pMemSeg == NULL )return COMMAND_ERROR_MEMORY_LOW;
00313     pS->stSession = pSt->NewSymbolTable(pSt->Alloc,pS->pMemSeg);
00314     if( pS->stSession == NULL )return COMMAND_ERROR_MEMORY_LOW;
00315     besUnlockMutex(&mxSessionTable);
00316     }else{/* this is an already existing session */
00317     pS = *p;
00318     besLockSharedRead(&(pS->lckSession));
00319     besUnlockMutex(&mxSessionTable);
00320     }
00321 
00322   /* the session id string should be copied because a program may think that it is executing a session and
00323      another thread deletes the session in the mean time, but can not know that there is a thread using the
00324      session */
00325   pMT->pszSessionId = besALLOC(strlen(SymbolName(p))+1);
00326   if( pMT->pszSessionId == NULL )return COMMAND_ERROR_MEMORY_LOW;
00327   strcpy(pMT->pszSessionId,SymbolName(p));
00328   pMT->AssignedSession = pS;
00329   pS->lPingTime = time(NULL);
00330   besUnlockSharedRead(&(pS->lckSession));
00331 
00332 besEND
00333 
00349 besFUNCTION(chksession)
00350   char *pszSession;
00351   pMtClass pMT;
00352   void **p;
00353   VARIABLE Argument;
00354   pSessionInfo pS;
00355   unsigned long i;
00356 
00357   besRETURNVALUE = NULL;
00358   pMT = besMODULEPOINTER;
00359   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
00360 
00361   Argument = besARGUMENT(1);
00362   besDEREFERENCE(Argument);
00363   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
00364   Argument = besCONVERT2STRING(Argument);
00365   /* check that the session ID does not contain zero character inside (for security reasons) */
00366   for( i = 0 ; i < STRLEN(Argument) ; i++ )
00367     if( ! STRINGVALUE(Argument)[i] )return MT_ERROR_BAD_SESS;
00368 
00369   besCONVERT2ZCHAR(Argument,pszSession);
00370 
00371   pS = pMT->AssignedSession = NULL;
00372   besLockMutex(&mxSessionTable);
00373   p = pSt->LookupSymbol(pszSession,SessionTable,0,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
00374   besUnlockMutex(&mxSessionTable);
00375   besFREE(pszSession);
00376   besALLOC_RETURN_LONG;
00377   LONGVALUE(besRETURNVALUE) = p == NULL ? 0 : -1 ;
00378   return COMMAND_ERROR_SUCCESS;
00379 besEND
00380 
00387 besFUNCTION(sessioncount)
00388   besALLOC_RETURN_LONG;
00389   /* count the creation of the new session */
00390   besLockMutex(&mxSessionCounter);
00391   LONGVALUE(besRETURNVALUE) = lSessionCounter;
00392   besUnlockMutex(&mxSessionCounter);
00393   return COMMAND_ERROR_SUCCESS;
00394 besEND
00395 
00410 besFUNCTION(newsession)
00411   unsigned long lThisSession;
00412   MD5_CTX Context;
00413   unsigned char digest[16];
00414   int i;
00415   pMtClass pMT;
00416   void **p;
00417   pSessionInfo pS;
00418   VARIABLE Argument;
00419 
00420   pMT = besMODULEPOINTER;
00421   Argument = NULL;
00422   if( besARGNR > 0 ){
00423     Argument = besARGUMENT(1);
00424     besDEREFERENCE(Argument);
00425     if( Argument){
00426       Argument = besCONVERT2STRING(Argument);
00427       }
00428     }
00429 
00430   /* count the creation of the new session */
00431   besLockMutex(&mxSessionCounter);
00432   lThisSession = lSessionCounter++;
00433   besUnlockMutex(&mxSessionCounter);
00434 
00435   /* create a new session id */
00436   besMD5INIT(&Context);
00437   besMD5UPDATE(&Context,(unsigned char *)&lThisSession,sizeof(unsigned long));
00438   if( Argument )besMD5UPDATE(&Context,(unsigned char *)STRINGVALUE(Argument),STRLEN(Argument));
00439   besMD5FINAL(digest,&Context);
00440   besALLOC_RETURN_STRING(33);
00441   STRLEN(besRETURNVALUE) = 32;
00442   /* convert the digest to ASCII */
00443   for( i = 0 ; i < 16 ; i++ ){
00444     STRINGVALUE(besRETURNVALUE)[2*i] = 'A' + (digest[i]&0x0F);
00445     digest[i] >>= 4;
00446     STRINGVALUE(besRETURNVALUE)[2*i+1] = 'A' + (digest[i]&0x0F);
00447     }
00448   STRINGVALUE(besRETURNVALUE)[32] = (char)0;/* terminate it to be used in the symbol table */
00449 
00450   pMT->AssignedSession = NULL;
00451   if( pMT->pszSessionId )besFREE(pMT->pszSessionId);
00452   besLockMutex(&mxSessionTable);
00453   p = pSt->LookupSymbol(STRINGVALUE(besRETURNVALUE),SessionTable,1,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
00454   if( p == NULL ){
00455     besUnlockMutex(&mxSessionTable);
00456     return COMMAND_ERROR_MEMORY_LOW;
00457     }
00458   if( *p == NULL ){/* this is a brand new session, most probably it is */
00459     *p = AllocNewSession(pSt,p);
00460     if( *p == NULL ){
00461       besUnlockMutex(&mxSessionTable);
00462       return COMMAND_ERROR_MEMORY_LOW;
00463       }
00464     pS = pMT->AssignedSession = *p;
00465     pS-> lPingTime = time(NULL);
00466     besInitMutex(&(pS->mxSession));
00467     besInitSharedLock(&(pS->lckSession));
00468     besLockSharedRead(&(pS->lckSession));
00469     /* Create a new memory segment for the session. */
00470     pS->pMemSeg = besINIT_SEGMENT(pSt->pEo->pMemorySegment,NULL);
00471     if( pS->pMemSeg == NULL )return COMMAND_ERROR_MEMORY_LOW;
00472     pS->stSession = pSt->NewSymbolTable(pSt->Alloc,pS->pMemSeg);
00473     if( pS->stSession == NULL )return COMMAND_ERROR_MEMORY_LOW;
00474     besUnlockMutex(&mxSessionTable);
00475     }else{
00476     pS = *p;
00477     besLockSharedRead(&(pS->lckSession));
00478     besUnlockMutex(&mxSessionTable);
00479     }
00480   pMT->pszSessionId = besALLOC(strlen(SymbolName(p))+1);
00481   if( pMT->pszSessionId == NULL )return COMMAND_ERROR_MEMORY_LOW;
00482   strcpy(pMT->pszSessionId,SymbolName(p));
00483   pMT->AssignedSession = pS;
00484   pS->lPingTime = time(NULL);
00485   besUnlockSharedRead(&(pS->lckSession));
00486 
00487 besEND
00488 
00489 static void FinishSegmentCallBack(char *SymbolName, void *SymbolValue, void *f){
00490   pSupportTable pSt;
00491   pMTVariable p;
00492 
00493   /* we need this variable to use the bes macros */
00494   pSt = f;
00495   p = SymbolValue;
00496   besFinishSharedLock(&(p->lckV));
00497   }
00498 
00508 besFUNCTION(delsession)
00509   char *pszSession;
00510   void **p;
00511   VARIABLE Argument;
00512   pSessionInfo pS;
00513   pMtClass pMT;
00514   int bSessDef; /* TRUE if the session was the default (actual) session 
00515                    This variable also shows that pszSession should be realeased */
00516 
00517   pMT = besMODULEPOINTER;
00518   pS = pMT->AssignedSession;
00519 
00520   besRETURNVALUE = NULL;
00521 
00522   Argument = besARGUMENT(1);
00523   besDEREFERENCE(Argument);
00524   bSessDef = 0;
00525   if( Argument == NULL ){
00526     /* In this case we delete the actual session. */
00527     bSessDef = 1;
00528     pszSession = pMT->pszSessionId;
00529     if( pszSession == NULL )return MT_ERROR_NOSESSION;
00530     }else{
00531     Argument = besCONVERT2STRING(Argument);
00532     besCONVERT2ZCHAR(Argument,pszSession);
00533     }
00534 
00535   /* if this is the actual session that we delete either because the user
00536      supplied no argument or because the user supplied the id of the actual
00537      session then we have to release the read lock on the session           */
00538   if( bSessDef || (pMT->pszSessionId && !strcmp(pszSession,pMT->pszSessionId)) ){
00539     besUnlockSharedRead(&(pS->lckSession));
00540     pMT->pszSessionId;
00541     pMT->AssignedSession = NULL;
00542     }
00543 
00544   besLockMutex(&mxSessionTable);
00545   p = pSt->LookupSymbol(pszSession,SessionTable,0,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
00546 
00547   /* there is no such session, nothing to delete */
00548   if( p == NULL ){
00549     besUnlockMutex(&mxSessionTable);
00550     if( ! bSessDef )besFREE(pszSession);
00551     return COMMAND_ERROR_SUCCESS;
00552     }
00553   /* store the pointer to the session data */
00554   pS = *p;
00555 
00556   /* delete the symbol and the symbol tabl entry */
00557   pSt->DeleteSymbol(pszSession,SessionTable,pSt->Free,besPROCMEMORYSEGMENT);
00558   besUnlockMutex(&mxSessionTable);
00559 
00560   /* this should not happen. If the session id is in the table it HAS to be initialized */
00561   if( pS == NULL ){
00562     /* note that we check it here after the symbol has been deleted */
00563     if( ! bSessDef )besFREE(pszSession);
00564     return EXE_ERROR_INTERNAL;
00565     }
00566 
00567   /*  This lock waits for all executing read locks. Because we have already deleted
00568       the session symbol from the symbol table no new read locks may start waiting. */
00569   besLockSharedWrite(&(pS->lckSession));
00570 
00571   /* This call releases all locks using besFinishSharedLock. We should do this because some
00572      lock implementation in some operating system may loose some resources if we do not
00573      call the system function releasing a seaphore or mutex but only release the memory.
00574      If an operating system does not loose any resource if we just release the memory
00575      allocated for a mutex/semaphore then this function call may be deleted. */
00576   besTRAVERSESYMBOLTABLE(pS->stSession,FinishSegmentCallBack,pSt);
00577 
00578   /* Delete all memory that was assigned to the session. That is all session variables and their
00579      corresponding locks. */
00580   besFINISH_SEGMENT(pS->pMemSeg);
00581   /* Finish the mutex that has protected the symbol table. */
00582   besFinishMutex(&(pS->mxSession));
00583   /* we may unlock this shared lock (we could do it before, but who cares...) 
00584      there should be no one waiting for it */
00585   besUnlockSharedWrite(&(pS->lckSession));
00586   /* finish the session shard lock */
00587   besFinishSharedLock(&(pS->lckSession));
00588   /* release the session information finally */
00589   ReleaseSession(pSt,pS);
00590 
00591   /* If there was a pszSession allocated then release it. If it was the default then the variable
00592      pszSession already points to a memory location that was released when the session data was
00593      released. */
00594   if( ! bSessDef )besFREE(pszSession);
00595 besEND
00596 
00606 besFUNCTION(getsession)
00607   pMtClass pMT;
00608   char *s;
00609 
00610   pMT = besMODULEPOINTER;
00611   s = pMT->pszSessionId;
00612   besRETURNVALUE = NULL;
00613   if( pMT->AssignedSession == NULL )return COMMAND_ERROR_SUCCESS;
00614   besALLOC_RETURN_STRING(strlen(s));
00615   memcpy(STRINGVALUE(besRETURNVALUE),s,strlen(s));
00616   return COMMAND_ERROR_SUCCESS;
00617 besEND
00618 
00627 besFUNCTION(setsvariable)
00628   VARIABLE Argument;
00629   char *pszVariableName;
00630   pMTVariable *p;
00631   pMtClass pMT;
00632   pSessionInfo pS;
00633 
00634   besRETURNVALUE = NULL;
00635   pMT = besMODULEPOINTER;
00636   pS = pMT->AssignedSession;
00637 
00638   if( besARGNR < 2 )return COMMAND_ERROR_FEW_ARGS;
00639 
00640   Argument = besARGUMENT(1);
00641   besDEREFERENCE(Argument);
00642   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
00643   Argument = besCONVERT2STRING(Argument);
00644   besCONVERT2ZCHAR(Argument,pszVariableName);
00645 
00646   besLockMutex(&(pS->mxSession));
00647   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,pS->stSession,1,pSt->Alloc,pSt->Free,pS->pMemSeg);
00648   besFREE(pszVariableName);
00649   if( p == NULL ){
00650     besUnlockMutex(&(pS->mxSession));
00651     return COMMAND_ERROR_MEMORY_LOW;
00652     }
00653   /* if this is the first call regarding this variable then create it*/
00654   if( *p == NULL ){
00655     *p = pSt->Alloc(sizeof(MTVariable),pS->pMemSeg);
00656     if( *p == NULL ){
00657       besUnlockMutex(&(pS->mxSession));
00658       return COMMAND_ERROR_MEMORY_LOW;
00659       }
00660     besInitSharedLock(&((*p)->lckV));
00661     (*p)->vV = NULL;
00662     }
00663   besUnlockMutex(&(pS->mxSession));
00664 
00665   besLockSharedWrite(&((*p)->lckV));
00666 
00667   Argument = besARGUMENT(2);
00668   besDEREFERENCE(Argument);
00669 
00670   if( (*p)->vV && TYPE((*p)->vV) == VTYPE_STRING && STRINGVALUE((*p)->vV) ){
00671     pSt->Free(STRINGVALUE((*p)->vV),pS->pMemSeg);
00672     STRINGVALUE((*p)->vV) = NULL;
00673     }
00674 
00675   /* we do not need memory to store undef */
00676   if( IsUndef(Argument) ){
00677     if( (*p)->vV )pSt->Free((*p)->vV,pS->pMemSeg);
00678     (*p)->vV = NULL;
00679     besUnlockSharedWrite(&((*p)->lckV));
00680     return COMMAND_ERROR_SUCCESS;
00681     }
00682 
00683   if( (*p)->vV == NULL )(*p)->vV = pSt->Alloc(sizeof(FixSizeMemoryObject),pS->pMemSeg);
00684   if( (*p)->vV == NULL ){
00685     besUnlockSharedWrite(&((*p)->lckV));
00686     return COMMAND_ERROR_MEMORY_LOW;
00687     }
00688 
00689   (*p)->vV->sType = 0;             /* not used */
00690   (*p)->vV->State = STATE_UNKNOWN; /* not used */
00691   (*p)->vV->next = NULL;           /* not used */
00692   (*p)->vV->link.prev = NULL;           /* not used */
00693   (*p)->vV->ArrayHighLimit = 0;
00694   (*p)->vV->ArrayLowLimit  = 1;
00695 
00696   if( TYPE(Argument) == VTYPE_STRING ){
00697     (*p)->vV->Value.pValue = pSt->Alloc(STRLEN(Argument) ? STRLEN(Argument) : 1 ,pS->pMemSeg);
00698     if( (*p)->vV->Value.pValue == NULL ){
00699       pSt->Free((*p)->vV,pS->pMemSeg);
00700       (*p)->vV = NULL;
00701       besUnlockSharedWrite(&((*p)->lckV));
00702       return COMMAND_ERROR_MEMORY_LOW;
00703       }
00704     memcpy((*p)->vV->Value.pValue,STRINGVALUE(Argument),STRLEN(Argument));
00705     (*p)->vV->Size = STRLEN(Argument);
00706     TYPE((*p)->vV) = VTYPE_STRING;
00707     besUnlockSharedWrite(&((*p)->lckV));
00708     return COMMAND_ERROR_SUCCESS;
00709     }
00710 
00711   if( TYPE(Argument) == VTYPE_LONG || TYPE(Argument) == VTYPE_DOUBLE ){
00712     TYPE((*p)->vV) = TYPE(Argument);
00713     (*p)->vV->Size = 0;
00714     (*p)->vV->Value = Argument->Value;
00715     besUnlockSharedWrite(&((*p)->lckV));
00716     return COMMAND_ERROR_SUCCESS;
00717     }
00718   
00719   besUnlockSharedWrite(&((*p)->lckV));
00720   return EXE_ERROR_INTERNAL;
00721 besEND
00722 
00732 besFUNCTION(getsvariable)
00733   VARIABLE Argument;
00734   char *pszVariableName;
00735   pMTVariable *p;
00736   pMtClass pMT;
00737   pSessionInfo pS;
00738 
00739   besRETURNVALUE = NULL;
00740   pMT = besMODULEPOINTER;
00741   pS = pMT->AssignedSession;
00742 
00743   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
00744 
00745   Argument = besARGUMENT(1);
00746   besDEREFERENCE(Argument);
00747   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
00748   Argument = besCONVERT2STRING(Argument);
00749   besCONVERT2ZCHAR(Argument,pszVariableName);
00750 
00751   besLockMutex(&(pS->mxSession));
00752   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,pS->stSession,0,pSt->Alloc,pSt->Free,pS->pMemSeg);
00753   besFREE(pszVariableName);
00754   if( p == NULL ){
00755     besUnlockMutex(&(pS->mxSession));
00756     return COMMAND_ERROR_SUCCESS; /* the value is undef, cause it was not defined */
00757     }
00758 
00759   if( *p == NULL ){
00760     besUnlockMutex(&(pS->mxSession));
00761     return COMMAND_ERROR_SUCCESS; /* the value is undef, cause it was defined to be undef */
00762     }
00763   besUnlockMutex(&(pS->mxSession));
00764 
00765   if( (*p)->vV == NULL )return COMMAND_ERROR_SUCCESS;
00766 
00767   besLockSharedRead(&((*p)->lckV));
00768 
00769   if( TYPE((*p)->vV) == VTYPE_STRING ){
00770     besALLOC_RETURN_STRING(STRLEN( (*p)->vV ));
00771     memcpy(STRINGVALUE(besRETURNVALUE),STRINGVALUE( (*p)->vV ),STRLEN( (*p)->vV) );
00772     besUnlockSharedRead(&((*p)->lckV));
00773     return COMMAND_ERROR_SUCCESS;
00774     }
00775 
00776   if( TYPE((*p)->vV) == VTYPE_LONG ){
00777     besALLOC_RETURN_LONG;
00778     LONGVALUE(besRETURNVALUE) = LONGVALUE((*p)->vV);
00779     besUnlockSharedRead(&((*p)->lckV));
00780     return COMMAND_ERROR_SUCCESS;
00781     }
00782 
00783   if( TYPE((*p)->vV) == VTYPE_DOUBLE ){
00784     besALLOC_RETURN_DOUBLE;
00785     DOUBLEVALUE(besRETURNVALUE) = DOUBLEVALUE((*p)->vV);
00786     besUnlockSharedRead(&((*p)->lckV));
00787     return COMMAND_ERROR_SUCCESS;
00788     }
00789 
00790   return EXE_ERROR_INTERNAL;
00791 besEND
00792 
00803 besFUNCTION(setmtvariable)
00804   VARIABLE Argument;
00805   char *pszVariableName;
00806   pMTVariable *p;
00807   besRETURNVALUE = NULL;
00808 
00809   if( besARGNR < 2 )return COMMAND_ERROR_FEW_ARGS;
00810 
00811   Argument = besARGUMENT(1);
00812   besDEREFERENCE(Argument);
00813   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
00814   Argument = besCONVERT2STRING(Argument);
00815   besCONVERT2ZCHAR(Argument,pszVariableName);
00816 
00817   besLockMutex(&mxMTVariables);
00818   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,MtVariables,1,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
00819   besFREE(pszVariableName);
00820   if( p == NULL ){
00821     besUnlockMutex(&mxMTVariables);
00822     return COMMAND_ERROR_MEMORY_LOW;
00823     }
00824 
00825   /* if this is the first call regarding this variable then create it*/
00826   if( *p == NULL ){
00827     *p = besPROCALLOC(sizeof(MTVariable));
00828     if( *p == NULL ){
00829       besUnlockMutex(&mxMTVariables);
00830       return COMMAND_ERROR_MEMORY_LOW;
00831       }
00832     besInitSharedLock(&((*p)->lckV));
00833     /* make the variable initially undef */
00834     (*p)->vV = NULL;
00835     }
00836   besUnlockMutex(&mxMTVariables);
00837 
00838   besLockSharedWrite(&((*p)->lckV));
00839 
00840   Argument = besARGUMENT(2);
00841   besDEREFERENCE(Argument);
00842 
00843   /* release the old value because we are going to replace that anyway */
00844   if( (*p)->vV && TYPE((*p)->vV) == VTYPE_STRING && STRINGVALUE((*p)->vV) ){
00845     besPROCFREE(STRINGVALUE((*p)->vV));
00846     STRINGVALUE((*p)->vV) = NULL;
00847     }
00848 
00849   /* we do not need memory to store undef */
00850   if( IsUndef(Argument) ){
00851     if( (*p)->vV )besPROCFREE((*p)->vV);
00852     (*p)->vV = NULL;
00853     besUnlockSharedWrite(&((*p)->lckV));
00854     return COMMAND_ERROR_SUCCESS;
00855     }
00856 
00857   if( (*p)->vV == NULL )(*p)->vV = besPROCALLOC(sizeof(FixSizeMemoryObject));
00858   if( (*p)->vV == NULL ){
00859     besUnlockSharedWrite(&((*p)->lckV));
00860     return COMMAND_ERROR_MEMORY_LOW;
00861     }
00862 
00863   (*p)->vV->sType = 0;             /* not used */
00864   (*p)->vV->State = STATE_UNKNOWN; /* not used */
00865   (*p)->vV->next = NULL;           /* not used */
00866   (*p)->vV->link.prev = NULL;           /* not used */
00867   (*p)->vV->ArrayHighLimit = 0;
00868   (*p)->vV->ArrayLowLimit  = 1;
00869 
00870   if( TYPE(Argument) == VTYPE_STRING ){
00871     (*p)->vV->Value.pValue = besPROCALLOC(STRLEN(Argument) ? STRLEN(Argument) : 1 );
00872     if( (*p)->vV->Value.pValue == NULL ){
00873       besUnlockSharedWrite(&((*p)->lckV));
00874       return COMMAND_ERROR_MEMORY_LOW;
00875       }
00876     memcpy((*p)->vV->Value.pValue,STRINGVALUE(Argument),STRLEN(Argument));
00877     (*p)->vV->Size = STRLEN(Argument);
00878     TYPE((*p)->vV) = VTYPE_STRING;
00879     besUnlockSharedWrite(&((*p)->lckV));
00880     return COMMAND_ERROR_SUCCESS;
00881     }
00882 
00883   if( TYPE(Argument) == VTYPE_LONG || TYPE(Argument) == VTYPE_DOUBLE ){
00884     TYPE((*p)->vV) = TYPE(Argument);
00885     (*p)->vV->Size = 0;
00886     (*p)->vV->Value = Argument->Value;
00887     besUnlockSharedWrite(&((*p)->lckV));
00888     return COMMAND_ERROR_SUCCESS;
00889     }
00890   
00891   besUnlockSharedWrite(&((*p)->lckV));
00892   return EXE_ERROR_INTERNAL;
00893 besEND
00894 
00901 besFUNCTION(getmtvariable)
00902   VARIABLE Argument;
00903   char *pszVariableName;
00904   pMTVariable *p;
00905   besRETURNVALUE = NULL;
00906 
00907   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
00908 
00909   Argument = besARGUMENT(1);
00910   besDEREFERENCE(Argument);
00911   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
00912   Argument = besCONVERT2STRING(Argument);
00913   besCONVERT2ZCHAR(Argument,pszVariableName);
00914 
00915   besLockMutex(&mxMTVariables);
00916   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,MtVariables,0,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
00917   besFREE(pszVariableName);
00918   if( p == NULL ){
00919     besUnlockMutex(&mxMTVariables);
00920     return COMMAND_ERROR_SUCCESS; /* the value is undef, cause it was not defined */
00921     }
00922 
00923   if( *p == NULL ){
00924     besUnlockMutex(&mxMTVariables);
00925     return COMMAND_ERROR_SUCCESS; /* the value is undef, cause it was defined to be undef */
00926     }
00927   besUnlockMutex(&mxMTVariables);
00928 
00929   if( (*p)->vV == NULL )return COMMAND_ERROR_SUCCESS;
00930 
00931   besLockSharedRead(&((*p)->lckV));
00932 
00933   if( TYPE((*p)->vV) == VTYPE_STRING ){
00934     besALLOC_RETURN_STRING(STRLEN( (*p)->vV ));
00935     memcpy(STRINGVALUE(besRETURNVALUE),STRINGVALUE( (*p)->vV ),STRLEN( (*p)->vV) );
00936     besUnlockSharedRead(&((*p)->lckV));
00937     return COMMAND_ERROR_SUCCESS;
00938     }
00939 
00940   if( TYPE((*p)->vV) == VTYPE_LONG ){
00941     besALLOC_RETURN_LONG;
00942     LONGVALUE(besRETURNVALUE) = LONGVALUE((*p)->vV);
00943     besUnlockSharedRead(&((*p)->lckV));
00944     return COMMAND_ERROR_SUCCESS;
00945     }
00946 
00947   if( TYPE((*p)->vV) == VTYPE_DOUBLE ){
00948     besALLOC_RETURN_DOUBLE;
00949     DOUBLEVALUE(besRETURNVALUE) = DOUBLEVALUE((*p)->vV);
00950     besUnlockSharedRead(&((*p)->lckV));
00951     return COMMAND_ERROR_SUCCESS;
00952     }
00953 
00954   return EXE_ERROR_INTERNAL;
00955 besEND
00956 
01033 besFUNCTION(lockmtwrite)
01034   VARIABLE Argument;
01035   char *pszVariableName;
01036   pMTVariable *p;
01037   besRETURNVALUE = NULL;
01038 
01039   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
01040 
01041   Argument = besARGUMENT(1);
01042   besDEREFERENCE(Argument);
01043   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
01044   Argument = besCONVERT2STRING(Argument);
01045   besCONVERT2ZCHAR(Argument,pszVariableName);
01046 
01047   besLockMutex(&mxMTVariables);
01048   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,MtVariables,1,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
01049   besFREE(pszVariableName);
01050   if( p == NULL ){
01051     besUnlockMutex(&mxMTVariables);
01052     return COMMAND_ERROR_MEMORY_LOW;
01053     }
01054   /* if this is the first call regarding this variable then create it*/
01055   if( *p == NULL ){
01056     *p = besPROCALLOC(sizeof(MTVariable));
01057     if( *p == NULL ){
01058       besUnlockMutex(&mxMTVariables);
01059       return COMMAND_ERROR_MEMORY_LOW;
01060       }
01061     besInitSharedLock(&((*p)->lckV));
01062     (*p)->vV = NULL;
01063     }
01064   besUnlockMutex(&mxMTVariables);
01065 
01066   besLockSharedWrite(&((*p)->lckV));
01067 
01068   return COMMAND_ERROR_SUCCESS;
01069 besEND
01070 
01081 besFUNCTION(lockmtread)
01082   VARIABLE Argument;
01083   char *pszVariableName;
01084   pMTVariable *p;
01085   besRETURNVALUE = NULL;
01086 
01087   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
01088 
01089   Argument = besARGUMENT(1);
01090   besDEREFERENCE(Argument);
01091   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
01092   Argument = besCONVERT2STRING(Argument);
01093   besCONVERT2ZCHAR(Argument,pszVariableName);
01094 
01095   besLockMutex(&mxMTVariables);
01096   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,MtVariables,1,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
01097   besFREE(pszVariableName);
01098   if( p == NULL ){
01099     besUnlockMutex(&mxMTVariables);
01100     return COMMAND_ERROR_MEMORY_LOW;
01101     }
01102   /* if this is the first call regarding this variable then create it*/
01103   if( *p == NULL ){
01104     *p = besPROCALLOC(sizeof(MTVariable));
01105     if( *p == NULL ){
01106       besUnlockMutex(&mxMTVariables);
01107       return COMMAND_ERROR_MEMORY_LOW;
01108       }
01109     besInitSharedLock(&((*p)->lckV));
01110     (*p)->vV = NULL;
01111     }
01112   besUnlockMutex(&mxMTVariables);
01113 
01114   besLockSharedRead(&((*p)->lckV));
01115 
01116   return COMMAND_ERROR_SUCCESS;
01117 besEND
01118 
01125 besFUNCTION(unlockmtwrite)
01126   VARIABLE Argument;
01127   char *pszVariableName;
01128   pMTVariable *p;
01129   besRETURNVALUE = NULL;
01130 
01131   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
01132 
01133   Argument = besARGUMENT(1);
01134   besDEREFERENCE(Argument);
01135   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
01136   Argument = besCONVERT2STRING(Argument);
01137   besCONVERT2ZCHAR(Argument,pszVariableName);
01138 
01139   besLockMutex(&mxMTVariables);
01140   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,MtVariables,1,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
01141   besFREE(pszVariableName);
01142   if( p == NULL ){
01143     besUnlockMutex(&mxMTVariables);
01144     return COMMAND_ERROR_MEMORY_LOW;
01145     }
01146   /* if this is the first call regarding this variable then create it*/
01147   if( *p == NULL ){
01148     *p = besPROCALLOC(sizeof(MTVariable));
01149     if( *p == NULL ){
01150       besUnlockMutex(&mxMTVariables);
01151       return COMMAND_ERROR_MEMORY_LOW;
01152       }
01153     besInitSharedLock(&((*p)->lckV));
01154     (*p)->vV = NULL;
01155     return COMMAND_ERROR_SUCCESS;
01156     }
01157   besUnlockMutex(&mxMTVariables);
01158 
01159   besUnlockSharedWrite(&((*p)->lckV));
01160 
01161   return COMMAND_ERROR_SUCCESS;
01162 besEND
01163 
01169 besFUNCTION(unlockmtread)
01170   VARIABLE Argument;
01171   char *pszVariableName;
01172   pMTVariable *p;
01173   besRETURNVALUE = NULL;
01174 
01175   if( besARGNR < 1 )return COMMAND_ERROR_FEW_ARGS;
01176 
01177   Argument = besARGUMENT(1);
01178   besDEREFERENCE(Argument);
01179   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
01180   Argument = besCONVERT2STRING(Argument);
01181   besCONVERT2ZCHAR(Argument,pszVariableName);
01182 
01183   besLockMutex(&mxMTVariables);
01184   p = (pMTVariable *)pSt->LookupSymbol(pszVariableName,MtVariables,1,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
01185   besFREE(pszVariableName);
01186   if( p == NULL ){
01187     besUnlockMutex(&mxMTVariables);
01188     return COMMAND_ERROR_MEMORY_LOW;
01189     }
01190   /* if this is the first call regarding this variable then create it*/
01191   if( *p == NULL ){
01192     *p = besPROCALLOC(sizeof(MTVariable));
01193     if( *p == NULL ){
01194       besUnlockMutex(&mxMTVariables);
01195       return COMMAND_ERROR_MEMORY_LOW;
01196       }
01197     besInitSharedLock(&((*p)->lckV));
01198     (*p)->vV = NULL;
01199     return COMMAND_ERROR_SUCCESS;
01200     }
01201   besUnlockMutex(&mxMTVariables);
01202 
01203   besUnlockSharedRead(&((*p)->lckV));
01204 
01205   return COMMAND_ERROR_SUCCESS;
01206 besEND
01207 
01223 besFUNCTION(sessionto)
01224   VARIABLE Argument;
01225   pSessionInfo pS;
01226   pMtClass pMT;
01227 
01228   besRETURNVALUE = NULL;
01229   pMT = besMODULEPOINTER;
01230   pS = pMT->AssignedSession;
01231 
01232   /* if there is no actual session selected */
01233   if( pS == NULL )return MT_ERROR_NOSESSION;
01234 
01235   /* If there is no any argument then it means that the session
01236      timeout should be cancelled. */
01237   if( besARGNR < 1 ){
01238     pS->lTimeout = 0;
01239     return COMMAND_ERROR_SUCCESS;
01240     }
01241 
01242   Argument = besARGUMENT(1);
01243   besDEREFERENCE(Argument);
01244   /* the timeout delay should not be undefined */
01245   if( Argument == NULL )return COMMAND_ERROR_FEW_ARGS;
01246   Argument = besCONVERT2LONG(Argument);
01247   /* convert the delay seconds to absolute GMT time stamp (well timestamp is GMT per def) */
01248   pS->lTimeout= time(NULL) + LONGVALUE(Argument);
01249 
01250   return COMMAND_ERROR_SUCCESS;
01251 besEND
01252 
01262 besFUNCTION(getsesto)
01263   char *pszSession;
01264   void **p;
01265   VARIABLE Argument;
01266   pSessionInfo pS;
01267   pMtClass pMT;
01268   int bSessDef; /* TRUE if the session was the default (actual) session 
01269                    This variable also shows that pszSession should be realeased */
01270 
01271   pMT = besMODULEPOINTER;
01272   pS = pMT->AssignedSession;
01273 
01274   besRETURNVALUE = NULL;
01275 
01276   Argument = besARGUMENT(1);
01277   besDEREFERENCE(Argument);
01278   if( Argument == NULL ){
01279     bSessDef = 1;
01280     pszSession = pMT->pszSessionId;
01281     if( pszSession == NULL )return MT_ERROR_NOSESSION;
01282     }else{
01283     bSessDef = 0;
01284     Argument = besCONVERT2STRING(Argument);
01285     besCONVERT2ZCHAR(Argument,pszSession);
01286     }
01287 
01288   besLockMutex(&mxSessionTable);
01289   p = pSt->LookupSymbol(pszSession,SessionTable,0,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
01290 
01291   /* there is no such session, there is no timeout */
01292   if( p == NULL ){
01293     besUnlockMutex(&mxSessionTable);
01294     if( ! bSessDef )besFREE(pszSession);
01295     besRETURNVALUE = NULL; /* return undef */
01296     if( ! bSessDef )besFREE(pszSession);
01297     return COMMAND_ERROR_SUCCESS;
01298     }
01299   /* store the pointer to the session data */
01300   pS = *p;
01301 
01302   besUnlockMutex(&mxSessionTable);
01303 
01304   /* this should not happen. If the session id is in the table it HAS to be initialized */
01305   if( pS == NULL ){
01306     /* note that we check it here after the symbol has been deleted */
01307     if( ! bSessDef )besFREE(pszSession);
01308     besRETURNVALUE = NULL;
01309     if( ! bSessDef )besFREE(pszSession);
01310     return EXE_ERROR_INTERNAL;
01311     }
01312 
01313   besALLOC_RETURN_LONG;
01314   LONGVALUE(besRETURNVALUE) = pS->lTimeout;
01315   /* If there was a pszSession allocated then release it. If it was the default then the variable
01316      pszSession already points to a memory location that was released when the session data was
01317      released. */
01318   if( ! bSessDef )besFREE(pszSession);
01319 besEND
01320 
01330 besFUNCTION(getsespt)
01331   char *pszSession;
01332   void **p;
01333   VARIABLE Argument;
01334   pSessionInfo pS;
01335   pMtClass pMT;
01336   int bSessDef; /* TRUE if the session was the default (actual) session 
01337                    This variable also shows that pszSession should be realeased */
01338 
01339   pMT = besMODULEPOINTER;
01340   pS = pMT->AssignedSession;
01341 
01342   besRETURNVALUE = NULL;
01343 
01344   Argument = besARGUMENT(1);
01345   besDEREFERENCE(Argument);
01346   if( Argument == NULL ){
01347     bSessDef = 1;
01348     pszSession = pMT->pszSessionId;
01349     if( pszSession == NULL )return MT_ERROR_NOSESSION;
01350     }else{
01351     bSessDef = 0;
01352     Argument = besCONVERT2STRING(Argument);
01353     besCONVERT2ZCHAR(Argument,pszSession);
01354     }
01355 
01356   besLockMutex(&mxSessionTable);
01357   p = pSt->LookupSymbol(pszSession,SessionTable,0,pSt->Alloc,pSt->Free,besPROCMEMORYSEGMENT);
01358 
01359   /* there is no such session, there is no ping time */
01360   if( p == NULL ){
01361     besUnlockMutex(&mxSessionTable);
01362     if( ! bSessDef )besFREE(pszSession);
01363     besRETURNVALUE = NULL; /* return undef */
01364     if( ! bSessDef )besFREE(pszSession);
01365     return COMMAND_ERROR_SUCCESS;
01366     }
01367   /* store the pointer to the session data */
01368   pS = *p;
01369 
01370   besUnlockMutex(&mxSessionTable);
01371 
01372   /* this should not happen. If the session id is in the table it HAS to be initialized */
01373   if( pS == NULL ){
01374     /* note that we check it here after the symbol has been deleted */
01375     if( ! bSessDef )besFREE(pszSession);
01376     besRETURNVALUE = NULL;
01377     if( ! bSessDef )besFREE(pszSession);
01378     return EXE_ERROR_INTERNAL;
01379     }
01380 
01381   besALLOC_RETURN_LONG;
01382   LONGVALUE(besRETURNVALUE) = pS->lPingTime;
01383   /* If there was a pszSession allocated then release it. If it was the default then the variable
01384      pszSession already points to a memory location that was released when the session data was
01385      released. */
01386   if( ! bSessDef )besFREE(pszSession);
01387 besEND
01388 
01447 besFUNCTION(listses)
01448   VARIABLE Argument,*Lval;
01449   long cSessionList;
01450   pSessionInfo pS;
01451   /* Timeout and Ping time min and max crtiteria values */
01452   unsigned long lToMin,lToMax,lPtMin,lPtMax,lStMin,lStMax;
01453   int iError;
01454   long __refcount_;
01455 
01456   Argument = besARGUMENT(1);
01457   besLEFTVALUE(Argument,Lval);
01458   if( ! Lval )return COMMAND_ERROR_ARGUMENT_TYPE;
01459   besRELEASE(*Lval);
01460   iError = besGETARGS "*[iiiiii]" , &lStMin, &lStMax, &lPtMin, &lPtMax, &lToMin, &lToMax besGETARGE
01461 
01462   if( iError )return iError;
01463 
01464 #define SESSION__CONSTRAINT \
01465         ( lToMin < pS->lTimeout )  && \
01466         ( lPtMin < pS->lPingTime)  && \
01467         ( lStMin < pS->lTimeStart) &&\
01468         ( (!lToMax) || lToMax > pS->lTimeout)  && \
01469         ( (!lPtMax) || lPtMax > pS->lPingTime) && \
01470         ( (!lStMax) || lStMax > pS->lTimeStart)
01471 
01472   pS = pSessionRoot;
01473   cSessionList = 0;
01474   besLockMutex(&mxSessionTable);
01475   while( pS ){
01476     if( SESSION__CONSTRAINT )cSessionList ++;
01477     pS = pS->next;
01478     }
01479 
01480   if( cSessionList == 0 ){
01481     *Lval = NULL;
01482     besUnlockMutex(&mxSessionTable);
01483     return COMMAND_ERROR_SUCCESS;
01484     }
01485   *Lval = besNEWARRAY(1,cSessionList);
01486   if( *Lval == NULL ){
01487     besUnlockMutex(&mxSessionTable);
01488     return COMMAND_ERROR_MEMORY_LOW;
01489     }
01490 
01491   pS = pSessionRoot;
01492   cSessionList = 0;
01493   while( pS ){
01494     if( SESSION__CONSTRAINT ){
01495       (*Lval)->Value.aValue[cSessionList] = besNEWSTRING(strlen(pS->pszId));
01496       if( (*Lval)->Value.aValue[cSessionList] == NULL ){
01497         besUnlockMutex(&mxSessionTable);
01498         return COMMAND_ERROR_MEMORY_LOW;
01499         }
01500       memcpy(STRINGVALUE((*Lval)->Value.aValue[cSessionList]),pS->pszId,strlen(pS->pszId));
01501       cSessionList ++;
01502       }
01503     pS = pS->next;
01504     }
01505 
01506   besUnlockMutex(&mxSessionTable);
01507 
01508 
01509 besEND
01510 
01511 
01512 besVERSION_NEGOTIATE
01513 
01514   return (int)INTERFACE_VERSION;
01515 
01516 besEND
01517 
01518 
01519 besSUB_FINISH
01520   pSessionInfo pS;
01521   pMtClass pMT;
01522 
01523   pMT = besMODULEPOINTER;
01524   pS = pMT->AssignedSession;
01525 
01526  /* This macro decrements the thread counter used to help to keep this library in memory 
01527     even those times when the process is idle and no ScriptBasic threads are running. */
01528   DEC_THREAD_COUNTER
01529 
01530   /* Release the session from the read lock (if any) */
01531   if( pS )besUnlockSharedRead(&(pS->lckSession));
01532 
01533 besEND
01534 
01535 besDLL_MAIN
01536 
01537 /* This function is used to tell the ScriptBasic interpreter whether to call FreeLibrary/dlclose
01538    or not. When this function returns TRUE the interpreter unloads the library. If this function
01539    returns FALSE the interpreter does not call FreeLibrary/dlclose and thus the library remains
01540    in memory even when there is no any thread actually using it. */
01541 besSUB_KEEP
01542   long lTC;
01543 
01544   /* get the actual value of the thread counter that counts the number of threads using the library
01545      currently */
01546   GET_THREAD_COUNTER(lTC);
01547   /* if this was the last thread then we will return 0 not to unload the library and therefore
01548      this thread finish should not be counted */
01549   if( lTC == 0 ){
01550     INC_THREAD_COUNTER
01551     }
01552   /* conver the long counter to (int) boolean */
01553   return lTC ? 1 : 0;
01554 besEND
01555 
01556 besSUB_PROCESS_START
01557   INIT_MULTITHREAD
01558   return 1;
01559 besEND
01560 
01561 besSUB_PROCESS_FINISH
01562   FINISH_MULTITHREAD
01563 besEND
01564 
01565 SLFST MT_SLFST[] ={
01566 
01567 { "keepmodu" , keepmodu },
01568 { "shutmodu" , shutmodu },
01569 { "bootmodu" , bootmodu },
01570 { "setsession" , setsession },
01571 { "chksession" , chksession },
01572 { "sessioncount" , sessioncount },
01573 { "newsession" , newsession },
01574 { "delsession" , delsession },
01575 { "getsession" , getsession },
01576 { "setsvariable" , setsvariable },
01577 { "getsvariable" , getsvariable },
01578 { "setmtvariable" , setmtvariable },
01579 { "getmtvariable" , getmtvariable },
01580 { "lockmtwrite" , lockmtwrite },
01581 { "lockmtread" , lockmtread },
01582 { "unlockmtwrite" , unlockmtwrite },
01583 { "unlockmtread" , unlockmtread },
01584 { "sessionto" , sessionto },
01585 { "getsesto" , getsesto },
01586 { "getsespt" , getsespt },
01587 { "listses" , listses },
01588 { "versmodu" , versmodu },
01589 { "finimodu" , finimodu },
01590 { "keepmodu" , keepmodu },
01591 { "_init" , _init },
01592 { "_fini" , _fini },
01593 { NULL , NULL }
01594   };

Generated on Sun Mar 12 23:56:29 2006 for ScriptBasic by  doxygen 1.4.6-NO