示例#1
0
/* Make a duplicate of a string. */
TA_String *TA_StringDup( TA_StringCache *stringCache, TA_String *string )
{
   TA_String *str;

   #if !defined( TA_SINGLE_THREAD )
   TA_RetCode retCode;
   #endif

   TA_StringCachePriv *stringCachePriv;

   if( stringCache == NULL )
      return NULL;

   stringCachePriv = (TA_StringCachePriv *)stringCache;

   if( !string )
      return NULL;

   #if !defined( TA_SINGLE_THREAD )
      /* Get the semaphore for this cache. */
      retCode = TA_SemaWait( &stringCachePriv->sema );
      if( retCode != TA_SUCCESS )
         return NULL;
   #endif

   str = stringDupInternal( string );

   #if !defined( TA_SINGLE_THREAD )
      TA_SemaPost( &stringCachePriv->sema );
   #endif

   return str;
}
示例#2
0
TA_String *TA_StringAlloc_ULong( TA_StringCache *stringCache, unsigned long value )
{
   TA_StringCachePriv *stringCachePriv;
   TA_String *retString;
   #if !defined( TA_SINGLE_THREAD )
   TA_RetCode retCode;
   #endif

   if( stringCache == NULL )
      return NULL;

   stringCachePriv = (TA_StringCachePriv *)stringCache;

   #if !defined( TA_SINGLE_THREAD )
      /* Get the semaphore for this cache. */
      retCode = TA_SemaWait( &stringCachePriv->sema );

      if( retCode != TA_SUCCESS )
         return NULL;
   #endif

   /* The "value" strings are not stored in the cache.
    * (Because they are known of not being copied often in
    *  the context of TA-LIB).
    */
   retString = valueAllocInternal( value );

   #if !defined( TA_SINGLE_THREAD )
      TA_SemaPost( &stringCachePriv->sema );
   #endif

   return retString; 
}
示例#3
0
TA_RetCode TA_SetFatalErrorHandler( TA_FatalHandler handler )
{
   TA_TraceGlobal *global;
   TA_RetCode retCode;

   retCode = TA_GetGlobal(  &TA_TraceGlobalControl, (void **)&global );
   if( retCode != TA_SUCCESS )
       return retCode;

   #if !defined( TA_SINGLE_THREAD )
      retCode = TA_SemaWait( &global->callSema );
      if( retCode != TA_SUCCESS )
         return retCode;
   #endif

   global->userHandler = handler;

   #if !defined( TA_SINGLE_THREAD )
      TA_SemaPost( &global->callSema );
   #endif

   return TA_SUCCESS;
}
示例#4
0
static void internalCheckpoint( TA_TraceGlobal *global,
                                TA_String  *key,
                                const char *funcname,
                                const char *filename,
                                unsigned int lineNb )
{
   #if !defined( TA_SINGLE_THREAD )      
   TA_RetCode retCode;
   #endif

   #ifdef TA_DEBUG
   TA_TracePosition *tracePosition;
   #endif

   /* Make sure there is no tracing while tracing!
    * In rare occasion, this may prevent to record
    * some tracing in a multithread environment.
    * We can live with that compromise.
    */   
   if( !TA_IsTraceEnabled() )
      return;

   #if !defined( TA_SINGLE_THREAD )                   
      retCode = TA_SemaWait( &global->callSema );
      if( retCode != TA_SUCCESS )
         return;   
   #endif

   #ifdef TA_DEBUG
   /* If this position is already in the dictionary, just
    * increment the 'repetition' counter, else create
    * a new entry in the dictionary.
    */
   TA_TraceDisable();
   tracePosition = TA_DictGetValue_S( global->functionCalled, TA_StringToChar(key) );
   TA_TraceEnable();

   if( tracePosition )
      tracePosition->repetition++;
   else
   {
      tracePosition = newTracePosition( funcname, filename, lineNb );

      if( !tracePosition )
      {
         #if !defined( TA_SINGLE_THREAD )
            TA_SemaPost( &global->callSema );
         #endif
         return;
      }
      TA_TraceDisable();
      TA_DictAddPair_S( global->functionCalled, key, (void *)tracePosition );
      TA_TraceEnable();
   }
   /* Trace position are never deleted, until the library is shutdown.
    * Make a copy of it in the circular buffer.
    */
   global->codeTrace[global->posForNextTrace] = *tracePosition;
   #else
      (void)key; /* Used only when doing debug. */
      global->codeTrace[global->posForNextTrace].filename   = filename;
      global->codeTrace[global->posForNextTrace].funcname   = funcname;
      global->codeTrace[global->posForNextTrace].lineNb     = lineNb;
      global->codeTrace[global->posForNextTrace].repetition = 1;
   #endif

   /* Move to the next entry in the circular buffer. */
   global->posForNextTrace++;
   if( global->posForNextTrace >= TA_CODE_TRACE_SIZE )
      global->posForNextTrace = 0;

   #if !defined( TA_SINGLE_THREAD )
   TA_SemaPost( &global->callSema );
   #endif
}
示例#5
0
void TA_PrivError( unsigned int type, const char *str,
                   const char *filename, const char *date,
                   const char *time, int line,
                   unsigned int j, unsigned int k )
{
   TA_RetCode retCode;
   TA_TraceGlobal *global;
   unsigned int length;

   retCode = TA_GetGlobal( &TA_TraceGlobalControl, (void **)&global );
   if( retCode != TA_SUCCESS )
      return;

   /* If a fatal error already got handled, return
    * immediatly.
    */
   if( global->fatalErrorRecorded )
      return;

   #if !defined( TA_SINGLE_THREAD )
      retCode = TA_SemaWait( &global->callSema );
      if( retCode != TA_SUCCESS )
         return;
   #endif

   /* Double-check inside the critical section. */
   if( global->fatalErrorRecorded )
   {
      #if !defined( TA_SINGLE_THREAD )
         TA_SemaPost( &global->callSema );
      #endif
      return;
   }

   global->fatalErrorRecorded = 1;

   /* Log the fatal error. */
   global->fatalError.position.filename = filename;
   global->fatalError.position.funcname = NULL;
   global->fatalError.position.lineNb = line;
   global->fatalError.position.repetition = 1;

   global->fatalError.str = NULL;
   if( str ) 
   {
      length = strlen( str ) + 1;
      if( length != 0 )
      {
         global->fatalError.str = (char *)TA_Malloc( length );
         memcpy( global->fatalError.str, str, length );
      }
   }

   global->fatalError.date = date;
   global->fatalError.time = time;
   global->fatalError.param1 = j;
   global->fatalError.param2 = k;
   global->fatalError.type = type;

   /* Call the user handler. */
   if( global->userHandler )
      global->userHandler();

   #if !defined( TA_SINGLE_THREAD )
   TA_SemaPost( &global->callSema );
   #endif
}
示例#6
0
static TA_RetCode fetchUsingWinInet( TA_NetworkGlobal *global,
                                     TA_WebPage       *webPage )
{
   TA_PROLOG

   TA_RetCode retCode;
   DWORD retDWORD;
   LPCTSTR lpszProxyName;
   TA_WebPageHiddenData *webPageHidden;
   HINTERNET hSession, hWebPage;

   TA_TRACE_BEGIN( fetchUsingWinInet );

   webPageHidden = (TA_WebPageHiddenData *)webPage->hiddenData;   

   retCode = TA_SUCCESS; /* Will change if an error occured. */
   if( !global->connected )
   {
      #if !defined( TA_SINGLE_THREAD )
         TA_SemaWait( &global->mutexSema );
      #endif

         /* Check again if connected within the mutex. To avoid
          * multiple task to initialize at the same time.
          */
         if( !global->connected )
         {                  
            /* Open and verify connection with a known URL. */
            retDWORD = InternetAttemptConnect(0);
            if( retDWORD != ERROR_SUCCESS )
               retCode = TA_NO_INTERNET_CONNECTION;
            else
            {
               /* needed?
                if( InternetCheckConnection((LPCTSTR)NULL, FLAG_ICC_FORCE_CONNECTION, 0 ) != 0 )
                  retCode = TA_INTERNET_ACCESS_FAILED;
                */

               /* Ok.. the last step is to get an handle used for
                * retreiving the Web pages.
                */
               if( webPageHidden->proxyName )
               {           
                  lpszProxyName = TA_Malloc( 100 + strlen( webPageHidden->proxyName ) );
                  if( !lpszProxyName )
                     retCode = TA_ALLOC_ERR;
                  else
                     sprintf( (char *)lpszProxyName, "http=http://%s:%s",
                              webPageHidden->proxyName,
                              webPageHidden->proxyPort? "80":webPageHidden->proxyPort );                      
               }
               else
                  lpszProxyName = NULL;
               
               if( retCode == TA_SUCCESS ) 
               {
                  global->hInternet = InternetOpen( "TA-LIB",
                                                    INTERNET_OPEN_TYPE_PRECONFIG,
                                                     lpszProxyName, NULL, 0 );
               }

               if( lpszProxyName )
                  TA_Free(  (void *)lpszProxyName );

            }

            if( !global->hInternet )
               webPageHidden->finalErrorCode = GetLastError();
            else
            {
               /* Success. Set a variable to avoid to connect again.
                * This variable will also make sure that the hInternet
                * is freed upon shutdown.
                */
               global->connected = 1; /* Success */
            }
         }
      #if !defined( TA_SINGLE_THREAD )
         TA_SemaPost( &global->mutexSema  );
      #endif

      if( retCode != TA_SUCCESS )
      {
         TA_TRACE_RETURN( retCode );
      }            
   }

   if( !global->hInternet )
   {
      /* May be returned in multi-thread situation if
       * the inital thread did not yet complete or succeed
       * to establish the internet access.
       */
      TA_TRACE_RETURN( TA_INTERNET_NOT_OPEN_TRY_AGAIN );
   }
  
   /* Open an internet session. */
   hSession = InternetConnect( global->hInternet,
                               webPageHidden->webSiteAddr,
                               INTERNET_DEFAULT_HTTP_PORT,
                               NULL, NULL,
                               (unsigned long)INTERNET_SERVICE_HTTP,
                               0, 0 );

   if( !hSession )
   {
      /* Did not work.... mmmm.... always try a second time. */
      hSession = InternetConnect( global->hInternet,
                                  webPageHidden->webSiteAddr,
                                  INTERNET_DEFAULT_HTTP_PORT,
                                  NULL, NULL,
                                  (unsigned long)INTERNET_SERVICE_HTTP,
                                  0, 0 );
   }

   if( !hSession )
   {
      TA_TRACE_RETURN( TA_INTERNET_SERVER_CONNECT_FAILED );
   }
   else
   {
      hWebPage = HttpOpenRequest( hSession, "GET",
                                  webPageHidden->webSitePage,
                                  NULL,
                                  NULL,
                                  NULL,
                                  INTERNET_FLAG_NEED_FILE|
                                  INTERNET_FLAG_CACHE_IF_NET_FAIL|                                 
                                  INTERNET_FLAG_NO_UI|
                                  INTERNET_FLAG_NO_COOKIES|
                                  INTERNET_FLAG_RESYNCHRONIZE,
                                  0 );
      if( !hWebPage )
         retCode = TA_INTERNET_OPEN_REQUEST_FAILED;
      else
      {         
         retCode = TA_SetReceiveTimeout( 10000 /* 10 seconds */,
                                         hWebPage );
         if( retCode == TA_SUCCESS )
         {
            if( !HttpSendRequest( hWebPage, 0, 0, 0, 0 ) )
               retCode = TA_INTERNET_SEND_REQUEST_FAILED;
            else
               retCode = buildListDataWinInet( webPage, hWebPage );
         }

         InternetCloseHandle( hWebPage );
      }
      
      InternetCloseHandle( hSession );
   }

   TA_TRACE_RETURN( retCode );
}
示例#7
0
static TA_RetCode fetchUsingLibCurl( TA_NetworkGlobal *global,
                                     TA_WebPage       *webPage )
{
   TA_PROLOG

   TA_RetCode retCode;
   TA_WebPageHiddenData *webPageHidden;
   const char *string1, *string2, *string3;
   unsigned int urlLength;
   char *urlString;
   CURLcode retValue;
   long curlInfo;

   TA_TRACE_BEGIN( fetchUsingLibCurl );

   TA_ASSERT( webPage != NULL );

   webPageHidden = (TA_WebPageHiddenData *)webPage->hiddenData;   
  
   /* Open an internet session. */

   /* Create the URL. */
   string1 = "http://";
   urlLength = strlen( string1 ) + 1;
   if( webPageHidden->webSiteAddr )
   {
      string2 = webPageHidden->webSiteAddr;
      urlLength += strlen( string2 );
   }
   else
      string2 = NULL;

   if( webPageHidden->webSitePage )
   {
      string3 = webPageHidden->webSitePage;
      urlLength += strlen( string3 ) + 1;
   }
   else
      string3 = NULL;

   urlString = TA_Malloc( urlLength );
   if( !urlString )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
   sprintf( urlString, "%s%s%s%s", string1? string1:"",
                             string2? string2:"", 
                             string3 && string3[0] != '/'? "/":"", 
                             string3? string3:"" );
   
   /* Serialize the request until a stress testing 
    * application proove that libcurl is multi-thread safe.
    */
   #if !defined( TA_SINGLE_THREAD )
      retCode = TA_SemaWait( &global->mutexSema );
      if( retCode != TA_SUCCESS )
      {
         TA_Free(  urlString );
         TA_TRACE_RETURN( retCode );
      }
   #endif

   /* Specify URL to get */
   curl_easy_setopt(global->curlHandle, CURLOPT_URL, urlString );
 
   /* Send all data to the callback function  */
   curl_easy_setopt(global->curlHandle, CURLOPT_WRITEFUNCTION,
                    libcurlWriteMemoryCallback);
 
   /* Specify the opaque data ptr for the callback function */
   curl_easy_setopt(global->curlHandle, CURLOPT_FILE, (void *)webPage);

   /* Fetch it. */
   retValue = curl_easy_perform(global->curlHandle);

   if( retValue == CURLE_OK )
      retCode = TA_SUCCESS;
   else
   {
      retValue = curl_easy_getinfo( global->curlHandle, CURLINFO_HTTP_CODE, &curlInfo );
      if( retValue == CURLE_OK )
         retCode = rfc1945StatusToRetCode( curlInfo );
      else
         retCode = TA_HTTP_SC_UNKNOWN;
   }

   #if !defined( TA_SINGLE_THREAD )
      TA_SemaPost( &global->mutexSema  );
   #endif

   /* Free the url. */
   TA_Free(  urlString );

   TA_TRACE_RETURN( retCode );
}
示例#8
0
TA_String *stringAllocNInternal( TA_StringCache *stringCache,
                                 const char *string,
                                 unsigned int maxNbChar,
                                 TA_CharCase caseType )
{
   TA_String *tmp;
   unsigned int hashIndex;
   char *hashEntry;
   TA_StringCachePriv *stringCachePriv;
   unsigned int newStringLength;
   int sameString;
   unsigned int i;

   #if !defined( TA_SINGLE_THREAD )
   TA_RetCode retCode;
   #endif

   if( stringCache == NULL )
      return NULL;

   stringCachePriv = (TA_StringCachePriv *)stringCache;

   if( !string )
      return NULL;

   hashIndex = calcHash( string, caseType );
   TA_ASSERT_RET( hashIndex < NB_CACHE_ENTRY, (TA_String *)NULL );

   /* Evaluate the final length of the new string. */
   newStringLength = strlen( string );
   if( maxNbChar != 0 )
   {
      if( maxNbChar < newStringLength )
         newStringLength = maxNbChar;
   }

   #if !defined( TA_SINGLE_THREAD )
      /* Get the semaphore for this cache. */
      retCode = TA_SemaWait( &stringCachePriv->sema );

      if( retCode != TA_SUCCESS )
         return NULL;
   #endif

   /* Check if already in the hash table. If yes, re-use it. */
   hashEntry = (char *)stringCachePriv->cache[ hashIndex ];
   if( hashEntry && ((unsigned char)hashEntry[0] < 255) )
   {
      /* Check that this is the same string, same size. */
      if( (caseType == NO_CASE) && 
          (!strncmp( string, &hashEntry[1], newStringLength)) &&
          (hashEntry[newStringLength+1] == '\0') )
         sameString = 1;     
      else if( caseType == PATH )
      {
          sameString = 1;
          for( i=0; i <= newStringLength && (sameString == 1); i++ )
          {
             if( hashEntry[i+1] == '\0' )
                sameString = 0;
             if( (string[i] != hashEntry[i+1]) && !TA_IsSeparatorChar(string[i]) )
                sameString = 0;
          }

          if( sameString && (hashEntry[newStringLength+1] != '\0') )
            sameString = 0;
      }
      else if( caseType == UPPER_CASE )
      {
          sameString = 1;
          for( i=0; i <= newStringLength && (sameString == 1); i++ )
          {
             if( hashEntry[i+1] == '\0' )
                sameString = 0;
             if( (toupper(string[i]) != hashEntry[i+1]) )
                sameString = 0;
          }

          if( sameString && (hashEntry[newStringLength+1] != '\0') )
            sameString = 0;
      }
      else
         sameString = 0;

      if( sameString )
      {
         tmp = stringDupInternal( (TA_String *)hashEntry );
         #if !defined( TA_SINGLE_THREAD )
            TA_SemaPost( &stringCachePriv->sema );         
         #endif
         return tmp;
      }
   }

   tmp = stringAllocInternal( string, newStringLength, caseType );

   if( tmp != NULL )
   {
      /* Store in cache. */

      /* Delete previous entry in the same position in the cache. */
      if( hashEntry )
         stringFreeInternal( (TA_String *)hashEntry );

      /* Keep track of this latest allocation. */
      stringCachePriv->cache[hashIndex] = stringDupInternal( tmp );
   }

   #if !defined( TA_SINGLE_THREAD )
      TA_SemaPost( &stringCachePriv->sema );
   #endif

   return tmp;
}
示例#9
0
/* This function return a pointer on the global variable for
 * a particular module.
 * If the global variables are NOT initialized, this function will
 * call the corresponding 'init' function for this module.
 */
TA_RetCode TA_GetGlobal( const TA_GlobalControl * const control,
                         void **global )
{
    /* Note: Keep that function simple.
     *       No tracing, no stdio and no assert.
     */

    TA_GlobalModuleId id;
    TA_RetCode retCode, finalRetCode;
    const TA_GlobalControl * const locControl = control;

    /* Validate parameters */
    if( !control || !global )
        return TA_FATAL_ERR;

    *global = NULL;

    id = control->id;
    if( id >= TA_NB_GLOBAL_ID )
        return TA_FATAL_ERR;

    if( TA_Globals->moduleControl[id].initialize )
    {
        /* This module is already initialized, just return the global. */
        *global = TA_Globals->moduleControl[id].global;
        return TA_SUCCESS;
    }

    /* This module did not yet get its global initialized. Let's do it. */

    /* Will change if anything happen in the following critical section. */
    finalRetCode = TA_SUCCESS;

#if !defined( TA_SINGLE_THREAD )
    if( !(TA_Globals->moduleControl[id].sema.flags&TA_SEMA_INITIALIZED) )
        return TA_FATAL_ERR;

    retCode = TA_SemaWait( &(TA_Globals->moduleControl[id].sema) );
    if( retCode != TA_SUCCESS )
        return TA_FATAL_ERR;

    /* Check again if initialize AFTER we got the semaphore. */
    if( !TA_Globals->moduleControl[id].initialize )
    {
#endif

        /* The module needs to be initialized. Call the corresponding
         * 'init' function.
         */
        if( !TA_Globals->moduleControl[id].control )
            TA_Globals->moduleControl[id].control = locControl;

        if( locControl->init )
        {
            retCode = (*locControl->init)( &(TA_Globals->moduleControl[id].global) );

            if( retCode != TA_SUCCESS )
                finalRetCode = retCode;
            else
                TA_Globals->moduleControl[id].initialize = 1;
        }

#if !defined( TA_SINGLE_THREAD )
    }
    retCode = TA_SemaPost( &(TA_Globals->moduleControl[id].sema) );
    if( retCode != TA_SUCCESS )
        finalRetCode = TA_FATAL_ERR;
#endif

    /* Verify if an error occured inside the critical section. */
    if( finalRetCode != TA_SUCCESS )
        return finalRetCode;

    if( TA_Globals->moduleControl[id].initialize )
    {
        /* Ok, everything is now alloc/initialized at this point, simply
         * return the pointer on the "global variable" for this module.
         */
        *global = TA_Globals->moduleControl[id].global;
    }
    else
        return TA_FATAL_ERR;

    return TA_SUCCESS;
}