SBlog.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:44k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  23. #include "SBlogInternal.h"
  24. #include <cstring>                  // For memset()
  25. #include <ctime>                    // For time_t
  26. #include <vector>                   // For STL vector template class
  27. #define SBLOG_EXPORTS
  28. #include "SBlog.h"                  // Header for these functions
  29. #include "SBlogOSUtils.h"           // for SBlogGetTime(), SBlogVswprintf()
  30. #ifdef __THREADED
  31. #include "VXItrd.h"                 // for VXItrdMutex
  32. #endif
  33. static const VXIunsigned MAX_LOG_BUFFER  = 4096 * 2;
  34. static const VXIunsigned TAG_ARRAY_SIZE = (((SBLOG_MAX_TAG) + 1) / 8 + 1);
  35. #define SBLOG_ERR_OUT_OF_MEMORY 100, L"SBlog: Out of memory", NULL
  36. #define SBLOG_ERR_ALREADY_INITIALIZED 104, L"SBlog: Already initialized", NULL
  37. #define SBLOG_ERR_NOT_INITIALIZED 105, L"SBlog: Not initialized", NULL
  38. #ifndef MODULE_PREFIX
  39. #define MODULE_PREFIX  COMPANY_DOMAIN L"."
  40. #endif
  41. #define MODULE_NAME MODULE_PREFIX L"SBlog"
  42. // Global variable to track whether this is initialized
  43. static bool gblInitialized = false;
  44. struct myAPI {
  45.   SBlogInterface intf;
  46.   void *impl_;
  47. };
  48. struct SBlogErrorCallbackData {
  49.   SBlogErrorListener *callback;
  50.   void *userdata;
  51.   bool operator==(struct SBlogErrorCallbackData &other)
  52.   { return (callback == other.callback && userdata == other.userdata); }  
  53.   bool operator!=(struct SBlogErrorCallbackData &other)
  54.   { return !operator==(other); }
  55. };
  56. struct SBlogDiagCallbackData {
  57.   SBlogDiagnosticListener *callback;
  58.   void *userdata;
  59.   bool operator==(struct SBlogDiagCallbackData &other)
  60.   { return (callback == other.callback && userdata == other.userdata); }
  61.   bool operator!=(struct SBlogDiagCallbackData &other)
  62.   { return !operator==(other); }
  63. };
  64. struct SBlogEventCallbackData{
  65.   SBlogEventListener *callback;
  66.   void *userdata;
  67.   bool operator==(struct SBlogEventCallbackData &other)
  68.   { return (callback == other.callback && userdata == other.userdata); }
  69.   bool operator!=(struct SBlogEventCallbackData &other)
  70.   { return !operator==(other); }
  71. };
  72. struct SBlogContentCallbackData{
  73.   SBlogContentListener *callback;
  74.   void *userdata;
  75.   bool operator==(struct SBlogContentCallbackData &other)
  76.   { return (callback == other.callback && userdata == other.userdata); }
  77.   bool operator!=(struct SBlogContentCallbackData &other)
  78.   { return !operator==(other); }
  79. };
  80. // Our definition of the opaque VXIlogStream
  81. extern "C" {
  82. struct VXIlogStream {
  83.   // Linked list of underlying SBlogListener content streams
  84.   typedef std::vector<SBlogStream *> STREAMS;
  85.   STREAMS streams;
  86. };
  87. }
  88. class SBlog {
  89. public:
  90.   SBlog(SBlogInterface *pThis);
  91.   virtual ~SBlog();
  92.   
  93.   bool DiagnosticIsEnabled(VXIunsigned tagID);
  94.   VXIlogResult DiagnosticLog(VXIunsigned    tagID,
  95.                              const VXIchar* subtag,
  96.                              const VXIchar* format,
  97.                              va_list arguments) const;
  98.   
  99.   VXIlogResult EventLog(VXIunsigned            eventID,
  100.                         const VXIchar*         format,
  101.                         va_list arguments) const;
  102.   VXIlogResult EventLog(VXIunsigned            eventID,
  103.                         const VXIVector*       keys,
  104. const VXIVector*       values) const;
  105.   VXIlogResult ErrorLog(const VXIchar*         moduleName,
  106.                         VXIunsigned            errorID,
  107.                         const VXIchar*         format,
  108.                         va_list arguments) const;  
  109.   VXIlogResult ContentOpen(const VXIchar*      moduleName,
  110.    const VXIchar*      contentType,
  111.    VXIString**         logKey,
  112.    VXIString**         logValue,
  113.    VXIlogStream**      stream) const;
  114.   VXIlogResult ContentClose(VXIlogStream**     stream) const;
  115.   VXIlogResult ContentWrite(const VXIbyte*     buffer,
  116.     VXIulong           buflen,
  117.     VXIulong*          nwritten,
  118.     VXIlogStream*      stream) const;
  119.   
  120.   VXIlogResult ControlDiagnosticTag(VXIunsigned tagID,
  121.                                     VXIbool     state);
  122.   // ----- Register/Unregister callback functions
  123.   VXIlogResult RegisterErrorListener(SBlogErrorCallbackData *info);
  124.   SBlogErrorCallbackData*
  125.     UnregisterErrorListener(SBlogErrorCallbackData *info);
  126.   
  127.   VXIlogResult RegisterDiagnosticListener(SBlogDiagCallbackData *info);
  128.   SBlogDiagCallbackData*
  129.     UnregisterDiagnosticListener(SBlogDiagCallbackData *info);
  130.   VXIlogResult RegisterEventListener(SBlogEventCallbackData *info);
  131.   SBlogEventCallbackData*
  132.     UnregisterEventListener(SBlogEventCallbackData *info);  
  133.   VXIlogResult RegisterContentListener(SBlogContentCallbackData *info);
  134.   SBlogContentCallbackData*
  135.     UnregisterContentListener(SBlogContentCallbackData *info);  
  136.   // ----- Internal error logging functions
  137.   VXIlogResult Error(VXIunsigned errorID, const VXIchar *errorIDText,
  138.      const VXIchar *format, ...) const;
  139.   static VXIlogResult GlobalError(VXIunsigned errorID, 
  140.   const VXIchar *errorIDText,
  141.   const VXIchar *format, ...);
  142. private:
  143.   // Internal methods
  144.   static unsigned testbit(unsigned char num, int bitpos);
  145.   static void setbit(unsigned char *num, int bitpos);
  146.   static void clearbit(unsigned char *num, int bitpos);
  147.   bool Convert2Index(VXIunsigned tagID,
  148.      VXIunsigned *index, 
  149.      VXIunsigned *bit_pos) const;
  150.   VXIlogResult ParseKeyValue(const VXIchar *format,
  151.      va_list args,
  152.      VXIVector *keys,
  153.      VXIVector *values) const;
  154.   
  155. #ifdef __THREADED
  156.   inline bool Lock( ) const { 
  157.     bool rc = (VXItrdMutexLock(_callbackLock) == VXItrd_RESULT_SUCCESS); 
  158.     if (! rc) Error(102, L"SBlog: Mutex lock failed", NULL);
  159.     return rc;
  160.   }
  161.   inline bool Unlock( ) const {
  162.     bool rc = (VXItrdMutexUnlock(_callbackLock) == VXItrd_RESULT_SUCCESS); 
  163.     if (! rc) Error(103, L"SBlog: Mutex unlock failed", NULL);
  164.     return rc;
  165.   }
  166.   inline VXIthreadID GetThreadID( ) const {
  167.     return VXItrdThreadGetID();
  168.   }
  169. #else
  170.   inline bool Lock( ) const { return true; }
  171.   inline bool Unlock( ) const { return true; }
  172.   inline VXIthreadID GetThreadID( ) const { return (VXIthreadID) 1; }
  173. #endif
  174. private:
  175.   typedef std::vector<SBlogDiagCallbackData *> DIAGCALLBACKS;
  176.   DIAGCALLBACKS diagCallbacks;
  177.   typedef std::vector<SBlogErrorCallbackData *> ERRORCALLBACKS;
  178.   ERRORCALLBACKS errorCallbacks;
  179.   typedef std::vector<SBlogEventCallbackData *> EVENTCALLBACKS;
  180.   EVENTCALLBACKS eventCallbacks;
  181.   typedef std::vector<SBlogContentCallbackData *> CONTENTCALLBACKS;
  182.   CONTENTCALLBACKS contentCallbacks;
  183. #ifdef __THREADED
  184.   VXItrdMutex *_callbackLock;
  185.   VXItrdMutex *_internalErrorLoggingLock;
  186. #endif
  187.   SBlogInterface *_pThis;
  188.   VXIthreadID _internalErrorLoggingThread;
  189.   unsigned char _tagIDs[TAG_ARRAY_SIZE];
  190. };
  191. SBlog::SBlog(SBlogInterface *pThis) : 
  192. #ifdef __THREADED
  193.   _callbackLock(NULL), 
  194.   _internalErrorLoggingLock(NULL), 
  195. #endif
  196.   _pThis(pThis),
  197.   _internalErrorLoggingThread((VXIthreadID) -1)
  198. {
  199.   // reset TAG ID range
  200.   memset(_tagIDs, 0, TAG_ARRAY_SIZE);
  201. #ifdef __THREADED
  202.   // Create the mutexes
  203.   if ((VXItrdMutexCreate(&_callbackLock) != VXItrd_RESULT_SUCCESS) ||
  204.       (VXItrdMutexCreate(&_internalErrorLoggingLock) != VXItrd_RESULT_SUCCESS))
  205.     Error(101, L"OSBlog: Mutex create failed", NULL);
  206. #endif
  207. }
  208. SBlog::~SBlog() 
  209. {
  210. #ifdef __THREADED
  211.   // Destroy the mutexes
  212.   VXItrdMutexDestroy(&_callbackLock);
  213.   VXItrdMutexDestroy(&_internalErrorLoggingLock);
  214. #endif
  215. }
  216. /**
  217.  * testbit
  218.  * testbit returns the value of the given bit
  219.  * 1 is set, 0 is clear
  220.  */
  221. unsigned SBlog::testbit(unsigned char num, int bitpos)
  222.   return (num >> bitpos) & ~(~0 << 1); 
  223. }
  224. /**
  225.  * setbit sets a given bit
  226.  */
  227. void SBlog::setbit(unsigned char *num, int bitpos)
  228. {
  229.   *num |= (1 << bitpos);
  230. }
  231. /**
  232.  * clearbit clears a given bit
  233.  */
  234. void SBlog::clearbit(unsigned char *num, int bitpos)
  235. {
  236.   *num &= ~(1 << bitpos);
  237. }
  238. bool SBlog::Convert2Index(VXIunsigned tagID,
  239.   VXIunsigned *index, 
  240.   VXIunsigned *bit_pos) const
  241. {
  242.   // check for overflow TAG ID
  243.   if (tagID > SBLOG_MAX_TAG) {
  244.     Error(300, L"SBlog: Tag ID is too large", L"%s%u", L"tagID", tagID);
  245.     return false;
  246.   }
  247.   // retrieving index for char array
  248.   *index = tagID/8;  // 8 bits per char
  249.   // retrieving bit position (bit range from 0-7)
  250.   *bit_pos = tagID%8;
  251.   return true;  // done
  252. }
  253. VXIlogResult SBlog::ControlDiagnosticTag(VXIunsigned tagID,
  254.                                          VXIbool state)
  255. {
  256.   VXIunsigned bindex, bpos;
  257.   if(!Convert2Index(tagID, &bindex, &bpos))
  258.     return VXIlog_RESULT_INVALID_ARGUMENT;
  259.   if(state)
  260.     setbit(&_tagIDs[bindex], bpos);
  261.   else
  262.     clearbit(&_tagIDs[bindex], bpos);
  263.     
  264.   return VXIlog_RESULT_SUCCESS;
  265. }
  266. VXIlogResult SBlog::RegisterErrorListener(SBlogErrorCallbackData *info)
  267. {
  268.    if (info == NULL) {
  269.      Error(200, L"SBlog: Internal error in RegisterErrorListener(), NULL "
  270.    L"callback data", NULL);
  271.      return VXIlog_RESULT_INVALID_ARGUMENT;
  272.    }
  273.    if (! Lock( )) {
  274.      return VXIlog_RESULT_SYSTEM_ERROR;
  275.    } else {
  276.      errorCallbacks.push_back(info);
  277.      if (! Unlock( ))
  278.        return VXIlog_RESULT_SYSTEM_ERROR;
  279.    }
  280.    return VXIlog_RESULT_SUCCESS;  
  281. }
  282. SBlogErrorCallbackData*
  283. SBlog::UnregisterErrorListener(SBlogErrorCallbackData *info)
  284. {
  285.   if (info == NULL) {
  286.     Error(201, L"SBlog: Internal error in UnregisterErrorListener(), NULL "
  287.   L"callback data", NULL);
  288.     return NULL;
  289.   }
  290.   SBlogErrorCallbackData *status = NULL;
  291.   if (! Lock( )) {
  292.     return NULL;
  293.   } else {
  294.     for (ERRORCALLBACKS::iterator i = errorCallbacks.begin();
  295.  i != errorCallbacks.end(); ++i)
  296.       {
  297. if (*info != *(*i)) continue;
  298. status = *i;
  299. errorCallbacks.erase(i);
  300. break;
  301.       }
  302.     if (! Unlock( ))
  303.       return NULL;
  304.   }
  305.   return status; 
  306. }
  307. VXIlogResult SBlog::RegisterDiagnosticListener(SBlogDiagCallbackData *info)
  308. {
  309.    if (info == NULL) {
  310.      Error(202, L"SBlog: Internal error in RegisterDiagnosticListener(), NULL "
  311.    L"callback data", NULL);
  312.      return VXIlog_RESULT_INVALID_ARGUMENT;
  313.    }
  314.    if (! Lock( )) {
  315.      return VXIlog_RESULT_SYSTEM_ERROR;
  316.    } else {
  317.      diagCallbacks.push_back(info);
  318.      if (! Unlock( ))
  319.        return VXIlog_RESULT_SYSTEM_ERROR;
  320.    }
  321.    return VXIlog_RESULT_SUCCESS;  
  322. }
  323. SBlogDiagCallbackData*
  324. SBlog::UnregisterDiagnosticListener(SBlogDiagCallbackData *info)
  325. {
  326.   if (info == NULL) {
  327.     Error(203, L"SBlog: Internal error in UnregisterDiagnosticListener(), "
  328.   L"NULL callback data", NULL);
  329.     return NULL;
  330.   }
  331.   SBlogDiagCallbackData *status = NULL;
  332.   if (! Lock( )) {
  333.     return NULL;
  334.   } else {
  335.     for (DIAGCALLBACKS::iterator i = diagCallbacks.begin();
  336.  i != diagCallbacks.end(); ++i)
  337.       {
  338. if (*info != *(*i)) continue;
  339. status = *i;
  340. diagCallbacks.erase(i);
  341. break;
  342.       }
  343.     if (! Unlock( ))
  344.       return NULL;
  345.   }
  346.   return status; 
  347. }
  348. VXIlogResult SBlog::RegisterEventListener(SBlogEventCallbackData *info)
  349. {
  350.    if (info == NULL) {
  351.      Error(204, L"SBlog: Internal error in RegisterEventListener(), NULL "
  352.    L"callback data", NULL);
  353.      return VXIlog_RESULT_INVALID_ARGUMENT;
  354.    }
  355.    if (! Lock( )) {
  356.      return VXIlog_RESULT_SYSTEM_ERROR;
  357.    } else {
  358.      eventCallbacks.push_back(info);
  359.      if (! Unlock( ))
  360.        return VXIlog_RESULT_SYSTEM_ERROR;
  361.    }
  362.    return VXIlog_RESULT_SUCCESS;  
  363. }
  364. SBlogEventCallbackData*
  365. SBlog::UnregisterEventListener(SBlogEventCallbackData *info)
  366. {
  367.   if (info == NULL) {
  368.     Error(205, L"SBlog: Internal error in UnregisterEventListener(), NULL "
  369.   L"callback data", NULL);
  370.     return NULL;
  371.   }
  372.   SBlogEventCallbackData *status = NULL;
  373.   if (! Lock( )) {
  374.     return NULL;
  375.   } else {
  376.     for (EVENTCALLBACKS::iterator i = eventCallbacks.begin();
  377.  i != eventCallbacks.end(); ++i)
  378.       {
  379. if (*info != *(*i)) continue;
  380. status = *i;
  381. eventCallbacks.erase(i);
  382. break;
  383.       }
  384.     
  385.     if (! Unlock( ))
  386.       return NULL;
  387.   }
  388.   return status; 
  389. }
  390. VXIlogResult SBlog::RegisterContentListener(SBlogContentCallbackData *info)
  391. {
  392.    if (info == NULL) {
  393.      Error(206, L"SBlog: Internal error in RegisterContentListener(), NULL "
  394.   L"callback data", NULL);
  395.      return VXIlog_RESULT_INVALID_ARGUMENT;
  396.    }
  397.    if (! Lock( )) {
  398.      return VXIlog_RESULT_SYSTEM_ERROR;
  399.    } else {
  400.      contentCallbacks.push_back(info);
  401.      if (! Unlock( ))
  402.        return VXIlog_RESULT_SYSTEM_ERROR;
  403.    }
  404.    return VXIlog_RESULT_SUCCESS;  
  405. }
  406. SBlogContentCallbackData*
  407. SBlog::UnregisterContentListener(SBlogContentCallbackData *info)
  408. {
  409.   if (info == NULL) {
  410.     Error(207, L"SBlog: Internal error in RegisterContentListener(), NULL "
  411.   L"callback data", NULL);
  412.     return NULL;
  413.   }
  414.   SBlogContentCallbackData *status = NULL;
  415.   if (! Lock( )) {
  416.     return NULL;
  417.   } else {
  418.     for (CONTENTCALLBACKS::iterator i = contentCallbacks.begin();
  419.  i != contentCallbacks.end(); ++i)
  420.       {
  421. if (*info != *(*i)) continue;
  422. status = *i;
  423. contentCallbacks.erase(i);
  424. break;
  425.       }
  426.     
  427.     if (! Unlock( ))
  428.       return NULL;
  429.   }
  430.   return status; 
  431. }
  432. VXIlogResult SBlog::ParseKeyValue(const VXIchar *format,
  433.                                   va_list args,
  434.                                   VXIVector *keys,
  435.                                   VXIVector *values) const
  436. {
  437.   const VXIchar SEP[] = L"{*}";
  438.   const int SEP_LEN = 3;  
  439.   if (( format == NULL ) || ( keys == NULL ) || ( values == NULL )) {
  440.     Error(208, L"SBlog: Internal error in ParseKeyValue(), invalid argument",
  441.   NULL);
  442.     return VXIlog_RESULT_INVALID_ARGUMENT;
  443.   }
  444.   // Insert delimiters into a revised format string, this does
  445.   // validation as well as letting us split it into key/values later
  446.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  447.   bool hadFreeformText = false;
  448.   int replacementStart = -1, fieldCount = 0;
  449.   size_t resultFormatLen = 0;
  450.   VXIchar resultFormat[MAX_LOG_BUFFER];
  451.   resultFormat[0] = L'';
  452.   for (int i = 0; (format[i] != L'') && (rc == VXIlog_RESULT_SUCCESS); i++) {
  453.     if (format[i] == '%') {
  454.       if (replacementStart > -1)
  455. replacementStart = -1; // double %%
  456.       else
  457. replacementStart = i;
  458.     } else if ((replacementStart > -1) && (SBlogIsAlpha(format[i])) &&
  459.        (format[i] != L'l') && (format[i] != L'L') && 
  460.        (format[i] != L'h')) {
  461.       if ((fieldCount % 2 == 0) && (format[i] != L's') && 
  462.   (format[i] != L'S')) {
  463. // Keys must be a %s or %S, truncate from here
  464. Error(301, L"SBlog: Invalid format string for VXIlog API call, "
  465.       L"replacements for key names must be %s", L"%s%s", L"format",
  466.       format);
  467. rc = VXIlog_RESULT_NON_FATAL_ERROR;
  468.       } else {
  469. // Insert the replacement expression and the seperator
  470. size_t index = resultFormatLen;
  471. resultFormatLen += (i - replacementStart) + 1 + SEP_LEN;
  472. if (resultFormatLen < MAX_LOG_BUFFER) {
  473.   wcsncpy(&resultFormat[index], &format[replacementStart],
  474.   (i - replacementStart) + 1);
  475.   index += (i - replacementStart) + 1;
  476.   wcscpy(&resultFormat[index], SEP);
  477. } else {
  478.   // Overflow, truncate the format string from here
  479.   rc = VXIlog_RESULT_NON_FATAL_ERROR;
  480. }
  481. replacementStart = -1;
  482. fieldCount++;
  483.       }
  484.     } else if (replacementStart == -1) {
  485.       // Shouldn't have free-form text, skip it. Proceeding allows us
  486.       // to gracefully handle things like "%s0x%p".
  487.       hadFreeformText = true;
  488.     }
  489.   }
  490.   // if key/value is not even truncate the field and return an error,
  491.   // but proceed with the other fields. If there was free form text,
  492.   // we skipped it and return an error, but proceed with logging.
  493.   if (fieldCount % 2 != 0) {
  494.     Error(302, L"SBlog: Invalid format string for VXIlog API call, "
  495.   L"missing value for a key", L"%s%s", L"format", format);
  496.     rc = VXIlog_RESULT_NON_FATAL_ERROR;
  497.     fieldCount--;
  498.   } else if (hadFreeformText) {
  499.     Error(303, L"SBlog: Invalid format string for VXIlog API call, "
  500.   L"must be a list of format strings for key/value pairs", 
  501.   L"%s%s", L"format", format);
  502.     rc = VXIlog_RESULT_NON_FATAL_ERROR;
  503.   }
  504.   // get the values
  505.   VXIchar result[MAX_LOG_BUFFER];
  506.   result[0] = L'';
  507.   SBlogVswprintf(result, MAX_LOG_BUFFER-1, resultFormat, args);
  508.   // parse the key/value based on the inserted separators
  509.   long fieldNum = 0;
  510.   const VXIchar *start = result, *end;
  511.   while ((fieldNum < fieldCount) && ((end = wcsstr(start, SEP)) != NULL)) {
  512.     // Insert into key/value vector
  513.     fieldNum++;
  514.     if (fieldNum % 2) // odd is key
  515.       VXIVectorAddElement(keys,(VXIValue*)VXIStringCreateN(start,end-start));
  516.     else
  517.       VXIVectorAddElement(values,(VXIValue*)VXIStringCreateN(start,end-start));
  518.     // Advance
  519.     start = &end[SEP_LEN];
  520.   }
  521.   if (fieldNum != fieldCount) {
  522.     // parse error
  523.     Error(304, L"SBlog: Internal error, parse failure after key/value "
  524.   L"insertions", L"%s%s%s%s", L"format", format, L"result", result);
  525.     rc = VXIlog_RESULT_NON_FATAL_ERROR;
  526.   }
  527.   return rc;
  528. }
  529. VXIlogResult SBlog::Error(VXIunsigned errorID, const VXIchar *errorIDText,
  530.   const VXIchar *format, ...) const
  531. {
  532.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  533.   // Avoid recursively reporting logging errors
  534.   if (_internalErrorLoggingThread == GetThreadID())
  535.     return VXIlog_RESULT_FAILURE;
  536.   if (VXItrdMutexLock(_internalErrorLoggingLock) != VXItrd_RESULT_SUCCESS) {
  537.     return VXIlog_RESULT_SYSTEM_ERROR;
  538.   } else {
  539.     VXIthreadID *loggingThread = 
  540.       const_cast<VXIthreadID *>(&_internalErrorLoggingThread);
  541.     *loggingThread = GetThreadID();
  542.     va_list args;
  543.     va_start(args, format);
  544.     rc = ErrorLog(MODULE_NAME, errorID, format, args);
  545.     if ( rc != VXIlog_RESULT_SUCCESS )
  546.       SBlogVLogErrorToConsole(MODULE_NAME, errorID, errorIDText, format, args);
  547.     va_end(args);
  548.     *loggingThread = (VXIthreadID) -1;
  549.     if (VXItrdMutexUnlock(_internalErrorLoggingLock) != VXItrd_RESULT_SUCCESS)
  550.       return VXIlog_RESULT_SYSTEM_ERROR;
  551.   }
  552.   return rc;
  553. }
  554. VXIlogResult SBlog::GlobalError(VXIunsigned errorID, 
  555. const VXIchar *errorIDText,
  556. const VXIchar *format, ...)
  557. {
  558.   va_list args;
  559.   va_start(args, format);
  560.   VXIlogResult rc = SBlogVLogErrorToConsole(MODULE_NAME, errorID, errorIDText,
  561.     format, args);
  562.   va_end(args);
  563.   return rc;
  564. }
  565. bool SBlog::DiagnosticIsEnabled(VXIunsigned tagID)
  566. {
  567.   VXIunsigned bindex, bpos;
  568.   if (!Convert2Index(tagID, &bindex, &bpos))
  569.     return false;
  570.   // if this tag is not turned on, just return
  571.   if (!testbit(_tagIDs[bindex],bpos))
  572.     return false;
  573.   return true;
  574. }
  575. VXIlogResult SBlog::DiagnosticLog(VXIunsigned     tagID,
  576.                                   const VXIchar*  subtag,
  577.                                   const VXIchar*  format,
  578.                                   va_list arguments) const
  579. {
  580.   VXIunsigned bindex, bpos;
  581.   if (!Convert2Index(tagID, &bindex, &bpos))
  582.     return VXIlog_RESULT_INVALID_ARGUMENT;
  583.   // if this tag is not turned on, just return
  584.   if (!testbit(_tagIDs[bindex],bpos))
  585.     return VXIlog_RESULT_SUCCESS;
  586.   time_t timestamp;
  587.   VXIunsigned timestampMsec;
  588.   SBlogGetTime (&timestamp, &timestampMsec);
  589.   wchar_t printmsg[MAX_LOG_BUFFER];
  590.   printmsg[0] = L'';
  591.   if (format != NULL)
  592.     SBlogVswprintf(printmsg, MAX_LOG_BUFFER-1, format, arguments);
  593.   
  594.   if (subtag == NULL)
  595.     subtag = L"";
  596.   
  597.   // Get a temporary callback vector copy to traverse, allows
  598.   // listeners to unregister from within the listener, also increases
  599.   // parallelism by allowing multiple threads to be calling the
  600.   // callbacks at once
  601.   VXIlogResult rc = VXIlog_RESULT_FAILURE;
  602.   if (! Lock( )) {
  603.     return VXIlog_RESULT_SYSTEM_ERROR;
  604.   } else {
  605.     DIAGCALLBACKS tempDiag = diagCallbacks;
  606.     if (! Unlock( ))
  607.       return VXIlog_RESULT_SYSTEM_ERROR;
  608.     
  609.     for (DIAGCALLBACKS::iterator i = tempDiag.begin(); i != tempDiag.end();++i)
  610.       {
  611. (*i)->callback(_pThis, tagID, subtag, timestamp, timestampMsec, 
  612.        printmsg, (*i)->userdata);
  613. rc = VXIlog_RESULT_SUCCESS;
  614.       }
  615.   }
  616.   
  617.   return rc;
  618. }
  619. VXIlogResult SBlog::EventLog(VXIunsigned     eventID,
  620.                              const VXIchar*  format,
  621.                              va_list args) const
  622. {
  623.   time_t timestamp;
  624.   VXIunsigned timestampMsec;
  625.   SBlogGetTime (&timestamp, &timestampMsec);
  626.   // Create key/value pairs
  627.   VXIVector *keys = VXIVectorCreate();
  628.   VXIVector *values = VXIVectorCreate();
  629.   if ((! keys) || (! values)) {
  630.     Error(SBLOG_ERR_OUT_OF_MEMORY);
  631.     return VXIlog_RESULT_OUT_OF_MEMORY;
  632.   }
  633.   
  634.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  635.   if (format) {
  636.     rc = ParseKeyValue(format, args, keys, values);
  637.     if (rc < VXIlog_RESULT_SUCCESS) {
  638.       VXIVectorDestroy(&keys);
  639.       VXIVectorDestroy(&values);
  640.       return rc;
  641.     }
  642.   }
  643.   
  644.   // Get a temporary callback vector copy to traverse, allows
  645.   // listeners to unregister from within the listener, also increases
  646.   // parallelism by allowing multiple threads to be calling the
  647.   // callbacks at once
  648.   if (rc == VXIlog_RESULT_SUCCESS)
  649.     rc = VXIlog_RESULT_FAILURE;
  650.   if (! Lock( )) {
  651.     return VXIlog_RESULT_SYSTEM_ERROR;
  652.   } else {
  653.     EVENTCALLBACKS tempEvent = eventCallbacks;
  654.     if (! Unlock( ))
  655.       return VXIlog_RESULT_SYSTEM_ERROR;
  656.   
  657.     for (EVENTCALLBACKS::iterator i = tempEvent.begin();
  658.  i != tempEvent.end(); ++i)
  659.       {
  660. (*i)->callback(_pThis, eventID, timestamp, timestampMsec, keys, values,
  661.        (*i)->userdata);
  662. if (rc == VXIlog_RESULT_FAILURE)
  663.   rc = VXIlog_RESULT_SUCCESS;
  664.       }
  665.   }
  666.   
  667.   VXIVectorDestroy(&keys);
  668.   VXIVectorDestroy(&values);
  669.   return rc;
  670. }
  671. VXIlogResult SBlog::EventLog(VXIunsigned      eventID,
  672.      const VXIVector* keys,
  673.      const VXIVector* values) const
  674. {
  675.   time_t timestamp;
  676.   VXIunsigned timestampMsec;
  677.   SBlogGetTime (&timestamp, &timestampMsec);
  678.   // Get a temporary callback vector copy to traverse, allows
  679.   // listeners to unregister from within the listener, also increases
  680.   // parallelism by allowing multiple threads to be calling the
  681.   // callbacks at once
  682.   VXIlogResult rc = VXIlog_RESULT_FAILURE;
  683.   if (! Lock( )) {
  684.     return VXIlog_RESULT_SYSTEM_ERROR;
  685.   } else {
  686.     EVENTCALLBACKS tempEvent = eventCallbacks;
  687.     if (! Unlock( ))
  688.       return VXIlog_RESULT_SYSTEM_ERROR;
  689.   
  690.     for (EVENTCALLBACKS::iterator i = tempEvent.begin();
  691.  i != tempEvent.end(); ++i)
  692.       {
  693. (*i)->callback(_pThis, eventID, timestamp, timestampMsec, keys, values,
  694.        (*i)->userdata);
  695. rc = VXIlog_RESULT_SUCCESS;
  696.       }
  697.   }
  698.   return rc;
  699. }
  700. VXIlogResult SBlog::ErrorLog(const VXIchar*   moduleName,
  701.                              VXIunsigned      errorID,
  702.                              const VXIchar*   format,
  703.                              va_list          args) const
  704. {
  705.   time_t  timestamp;
  706.   VXIunsigned timestampMsec;
  707.   SBlogGetTime (&timestamp, &timestampMsec);
  708.   // Create key/value pairs
  709.   VXIVector *keys = VXIVectorCreate();
  710.   VXIVector *values = VXIVectorCreate();
  711.   if ((! keys) || (! values)) {
  712.     Error(SBLOG_ERR_OUT_OF_MEMORY);
  713.     return VXIlog_RESULT_OUT_OF_MEMORY;
  714.   }
  715.   
  716.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  717.   if (format) {
  718.     rc = ParseKeyValue(format, args, keys, values);
  719.     if (rc < VXIlog_RESULT_SUCCESS) {
  720.       VXIVectorDestroy(&keys);
  721.       VXIVectorDestroy(&values);
  722.       return rc;
  723.     }
  724.   }
  725.   
  726.   // Get a temporary callback vector copy to traverse, allows
  727.   // listeners to unregister from within the listener, also increases
  728.   // parallelism by allowing multiple threads to be calling the
  729.   // callbacks at once
  730.   if (rc == VXIlog_RESULT_SUCCESS)
  731.     rc = VXIlog_RESULT_FAILURE;
  732.   if (! Lock( )) {
  733.     return VXIlog_RESULT_SYSTEM_ERROR;
  734.   } else {
  735.     ERRORCALLBACKS tempError = errorCallbacks;
  736.     if (! Unlock( ))
  737.       return VXIlog_RESULT_SYSTEM_ERROR; 
  738.     for (ERRORCALLBACKS::iterator i = tempError.begin();
  739.  i != tempError.end(); ++i)
  740.       {
  741. (*i)->callback(_pThis, 
  742.        (moduleName && moduleName[0] ? moduleName : L"UNKNOWN"),
  743.        errorID, timestamp, timestampMsec, keys, values, 
  744.        (*i)->userdata);
  745. if (rc == VXIlog_RESULT_FAILURE)
  746.   rc = VXIlog_RESULT_SUCCESS;
  747.       }
  748.   }
  749.   
  750.   VXIVectorDestroy(&keys);
  751.   VXIVectorDestroy(&values); 
  752.   // Want to warn the caller that NULL moduleName really isn't OK, but
  753.   // logged it anyway
  754.   if ((! moduleName) || (! moduleName[0])) {
  755.     Error(305, L"SBlog: Empty module name passed to VXIlog API call", NULL);
  756.     rc = VXIlog_RESULT_INVALID_ARGUMENT;
  757.   }
  758.   
  759.   return rc;
  760. }
  761. VXIlogResult SBlog::ContentOpen(const VXIchar*      moduleName,
  762. const VXIchar*      contentType,
  763. VXIString**         logKey,
  764. VXIString**         logValue,
  765. VXIlogStream**      stream) const
  766. {
  767.   if ((! contentType) || (! contentType[0]) || (! logKey) || (! logValue) ||
  768.       (! stream)) {
  769.     Error(306, L"SBlog: Invalid argument to VXIlog::ContentOpen()", NULL);
  770.     return VXIlog_RESULT_INVALID_ARGUMENT;
  771.   }
  772.   *logKey = *logValue = NULL;
  773.   *stream = NULL;
  774.   const VXIchar *finalModuleName = L"UNKNOWN";
  775.   if ((! moduleName) || (! moduleName[0])) {
  776.     Error(305, L"SBlog: Empty module name passed to VXIlog API call", NULL);
  777.   } else {
  778.     finalModuleName = moduleName;
  779.   }
  780.   VXIlogResult rc = VXIlog_RESULT_FAILURE;
  781.   // Get a temporary callback vector copy to traverse, allows
  782.   // listeners to unregister from within the listener, also increases
  783.   // parallelism by allowing multiple threads to be calling the
  784.   // callbacks at once
  785.   if (! Lock( )) {
  786.     return VXIlog_RESULT_SYSTEM_ERROR;
  787.   } else {
  788.     CONTENTCALLBACKS tempContent = contentCallbacks;
  789.     if (! Unlock( ))
  790.       return VXIlog_RESULT_SYSTEM_ERROR; 
  791.     VXIlogStream *finalStream = NULL;
  792.     for (CONTENTCALLBACKS::iterator i = tempContent.begin();
  793.         i != tempContent.end(); ++i)
  794.     {
  795.       VXIString *logKey_    = NULL;
  796.       VXIString *logValue_  = NULL;
  797.       SBlogStream *stream_  = NULL;
  798.       VXIlogResult rc2 = (*i)->callback(_pThis, 
  799. finalModuleName,
  800. contentType, 
  801. (*i)->userdata,
  802. &logKey_,
  803. &logValue_,
  804. &stream_);
  805.       if ((rc2 == VXIlog_RESULT_SUCCESS) && (stream_)) {
  806. // Return the key and value of only the first listener
  807. if ( rc != VXIlog_RESULT_SUCCESS ) {
  808.   finalStream = new VXIlogStream;
  809.   if (! finalStream) {
  810.     VXIStringDestroy(&logKey_);       
  811.     VXIStringDestroy(&logValue_);
  812.     stream_->Close(&stream_);
  813.     Error(SBLOG_ERR_OUT_OF_MEMORY);
  814.     return VXIlog_RESULT_OUT_OF_MEMORY;
  815.   }
  816.   rc = VXIlog_RESULT_SUCCESS;
  817.   *logKey = logKey_;
  818.   *logValue = logValue_;
  819.   *stream = (VXIlogStream *) finalStream;
  820. } else {
  821.   VXIStringDestroy(&logKey_);       
  822.   VXIStringDestroy(&logValue_);
  823. }
  824. // Store the stream
  825. finalStream->streams.push_back(stream_);
  826.       } else if ((rc != VXIlog_RESULT_SUCCESS) &&
  827.  (((rc < 0) && (rc2 < rc)) ||
  828.   ((rc > 0) && (rc2 > rc)))) {
  829. // Return success if any listener returns success but keep the
  830. // worst error otherwise
  831. rc = rc2;
  832.       }
  833.     }
  834.   }
  835.   return rc;
  836. }
  837. VXIlogResult SBlog::ContentClose(VXIlogStream**     stream) const
  838. {
  839.   if ((! stream) || (! *stream)) {
  840.     Error(307, L"SBlog: Invalid argument to VXIlog::ContentClose()", NULL);
  841.     return VXIlog_RESULT_INVALID_ARGUMENT;
  842.   }
  843.   
  844.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  845.   // Close each of the underlying listener streams
  846.   for (VXIlogStream::STREAMS::iterator vi = (*stream)->streams.begin( );
  847.        vi != (*stream)->streams.end( ); vi++) {
  848.     SBlogStream *s = *vi;
  849.     VXIlogResult rc2 = s->Close (&s);
  850.     if ((rc == VXIlog_RESULT_SUCCESS) || ((rc < 0) && (rc2 < rc)) ||
  851. ((rc > 0) && (rc2 > rc)))
  852.       rc = rc2;
  853.   }
  854.   delete *stream;
  855.   *stream = NULL; 
  856.   return rc;
  857. }
  858. VXIlogResult SBlog::ContentWrite(const VXIbyte*     buffer,
  859.  VXIulong           buflen,
  860.  VXIulong*          nwritten,
  861.  VXIlogStream*      stream) const
  862. {
  863.   if ((! buffer) || (buflen < 1) || (! nwritten) || (! stream)) {
  864.     Error(308, L"SBlog: Invalid argument to VXIlog::ContentWrite()", NULL);
  865.     return VXIlog_RESULT_INVALID_ARGUMENT;
  866.   }
  867.   
  868.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  869.   *nwritten = 0;
  870.   // Write to each of the underlying listener streams
  871.   for (VXIlogStream::STREAMS::iterator vi = stream->streams.begin( );
  872.        vi != stream->streams.end( ); vi++) {
  873.     SBlogStream *s = *vi;
  874.     VXIulong nw = 0;
  875.     VXIlogResult rc2 = s->Write (s, buffer, buflen, &nw);
  876.     if (rc == VXIlog_RESULT_SUCCESS) {
  877.       if (nw > *nwritten)
  878. *nwritten = nw;
  879.     } else if ((rc == VXIlog_RESULT_SUCCESS) || ((rc < 0) && (rc2 < rc)) ||
  880.        ((rc > 0) && (rc2 > rc))) {
  881.       rc = rc2;
  882.     }
  883.   }
  884.   return rc;
  885. }
  886.   
  887. /***********************************************************************/
  888. VXIlogResult SBlogControlDiagnosticTag(SBlogInterface *pThis,
  889.                                        VXIunsigned tagID,
  890.                                        VXIbool     state)
  891. {
  892.   if (pThis == NULL)
  893.     return VXIlog_RESULT_INVALID_ARGUMENT;
  894.   myAPI *temp = (myAPI *) pThis; 
  895.   SBlog *me = (SBlog *)temp->impl_;
  896.   return (me->ControlDiagnosticTag(tagID, state));
  897. }
  898. VXIlogResult SBlogRegisterErrorListener(SBlogInterface *pThis,
  899.                                         SBlogErrorListener* alistener,
  900.                                         void* userdata)
  901. {
  902.   if ((pThis == NULL) || (alistener == NULL))
  903.     return VXIlog_RESULT_INVALID_ARGUMENT;
  904.   myAPI *temp = (myAPI *) pThis; 
  905.   SBlog *me = (SBlog *)temp->impl_;
  906.   SBlogErrorCallbackData *info = new SBlogErrorCallbackData;
  907.   if (info == NULL) {
  908.     me->Error(SBLOG_ERR_OUT_OF_MEMORY);
  909.     return VXIlog_RESULT_OUT_OF_MEMORY;
  910.   }
  911.  
  912.   info->callback = alistener;
  913.   info->userdata = userdata;
  914.   return ( me->RegisterErrorListener(info));
  915. VXIlogResult SBlogUnregisterErrorListener(SBlogInterface *pThis,
  916.                                           SBlogErrorListener* alistener,
  917.                                           void* userdata)
  918. {
  919.   if ((pThis == NULL) || (alistener == NULL))
  920.     return VXIlog_RESULT_INVALID_ARGUMENT;
  921.   myAPI *temp = (myAPI *) pThis; 
  922.   SBlog *me = (SBlog *)temp->impl_;
  923.   SBlogErrorCallbackData info = { alistener, userdata };
  924.   SBlogErrorCallbackData *p = me->UnregisterErrorListener(&info);
  925.   if (p) delete p;
  926.   return VXIlog_RESULT_SUCCESS;
  927. VXIlogResult SBlogRegisterDiagnosticListener(SBlogInterface *pThis,
  928.                                              SBlogDiagnosticListener*alistener,
  929.                                              void* userdata)
  930. {
  931.   if ((pThis == NULL) || (alistener == NULL))
  932.     return VXIlog_RESULT_INVALID_ARGUMENT;
  933.   myAPI *temp = (myAPI *) pThis; 
  934.   SBlog *me = (SBlog *)temp->impl_;
  935.   SBlogDiagCallbackData *info = new SBlogDiagCallbackData;
  936.   if (info == NULL) {
  937.     me->Error(SBLOG_ERR_OUT_OF_MEMORY);
  938.     return VXIlog_RESULT_OUT_OF_MEMORY;
  939.   }
  940.  
  941.   info->callback = alistener;
  942.   info->userdata = userdata;
  943.   return ( me->RegisterDiagnosticListener(info));
  944. VXIlogResult SBlogUnregisterDiagnosticListener(
  945.                                      SBlogInterface *pThis,
  946.                                      SBlogDiagnosticListener* alistener,
  947.                                      void* userdata)
  948. {
  949.   if ((pThis == NULL) || (alistener == NULL))
  950.     return VXIlog_RESULT_INVALID_ARGUMENT;
  951.   myAPI *temp = (myAPI *) pThis; 
  952.   SBlog *me = (SBlog *)temp->impl_;
  953.   SBlogDiagCallbackData info = { alistener, userdata };
  954.   SBlogDiagCallbackData *p = me->UnregisterDiagnosticListener(&info);
  955.   if (p) delete p;
  956.   return VXIlog_RESULT_SUCCESS;
  957. VXIlogResult SBlogRegisterEventListener(SBlogInterface *pThis,
  958.                                         SBlogEventListener* alistener,
  959.                                         void* userdata)
  960. {
  961.   if ((pThis == NULL) || (alistener == NULL))
  962.     return VXIlog_RESULT_INVALID_ARGUMENT;
  963.   
  964.   myAPI *temp = (myAPI *) pThis; 
  965.   SBlog *me = (SBlog *)temp->impl_;
  966.   SBlogEventCallbackData *info = new SBlogEventCallbackData;
  967.   if (info == NULL) {
  968.     me->Error(SBLOG_ERR_OUT_OF_MEMORY);
  969.     return VXIlog_RESULT_OUT_OF_MEMORY;
  970.   }
  971.  
  972.   info->callback = alistener;
  973.   info->userdata = userdata;
  974.   return ( me->RegisterEventListener(info));
  975. VXIlogResult SBlogUnregisterEventListener(SBlogInterface *pThis,
  976.                                           SBlogEventListener* alistener,
  977.                                           void*  userdata)
  978. {
  979.   if ((pThis == NULL) || (alistener == NULL))
  980.     return VXIlog_RESULT_INVALID_ARGUMENT;
  981.   myAPI *temp = (myAPI *) pThis; 
  982.   SBlog *me = (SBlog *)temp->impl_;
  983.   SBlogEventCallbackData info = { alistener, userdata };
  984.   SBlogEventCallbackData *p = me->UnregisterEventListener(&info);
  985.   if (p) delete p;
  986.   return VXIlog_RESULT_SUCCESS;
  987. VXIlogResult SBlogRegisterContentListener(SBlogInterface *pThis,
  988.   SBlogContentListener* alistener,
  989.   void* userdata)
  990. {
  991.   if ((pThis == NULL) || (alistener == NULL))
  992.     return VXIlog_RESULT_INVALID_ARGUMENT;
  993.   
  994.   myAPI *temp = (myAPI *) pThis; 
  995.   SBlog *me = (SBlog *)temp->impl_;
  996.   SBlogContentCallbackData *info = new SBlogContentCallbackData;
  997.   if (info == NULL) {
  998.     me->Error(SBLOG_ERR_OUT_OF_MEMORY);
  999.     return VXIlog_RESULT_OUT_OF_MEMORY;
  1000.   }
  1001.  
  1002.   info->callback = alistener;
  1003.   info->userdata = userdata;
  1004.   return ( me->RegisterContentListener(info));
  1005. VXIlogResult SBlogUnregisterContentListener(SBlogInterface *pThis,
  1006.     SBlogContentListener* alistener,
  1007.     void*  userdata)
  1008. {
  1009.   if ((pThis == NULL) || (alistener == NULL))
  1010.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1011.   myAPI *temp = (myAPI *) pThis; 
  1012.   SBlog *me = (SBlog *)temp->impl_;
  1013.   SBlogContentCallbackData info = { alistener, userdata };
  1014.   SBlogContentCallbackData *p = me->UnregisterContentListener(&info);
  1015.   if (p) delete p;
  1016.   return VXIlog_RESULT_SUCCESS;
  1017. /**********************************************************************
  1018. */
  1019. SBLOG_API VXIint32 SBlogGetVersion(void)
  1020. {
  1021.   return VXI_CURRENT_VERSION;
  1022. }
  1023. SBLOG_API const VXIchar* SBlogGetImplementationName(void)
  1024. {
  1025.   static const VXIchar IMPLEMENTATION_NAME[] = COMPANY_DOMAIN L".SBlog";
  1026.   return IMPLEMENTATION_NAME;
  1027. }
  1028. SBLOG_API VXIbool SBlogDiagnosticIsEnabled(VXIlogInterface * pThis,
  1029.                                            VXIunsigned tagID)
  1030. {
  1031.   if (pThis == NULL)
  1032.     return FALSE;
  1033.   myAPI *temp = (myAPI *) pThis;
  1034.   SBlog *me = (SBlog *) temp->impl_;
  1035.   if (!me->DiagnosticIsEnabled(tagID)) return FALSE;
  1036.   return TRUE;
  1037. }
  1038. SBLOG_API VXIlogResult SBlogDiagnostic(VXIlogInterface*        pThis,
  1039.                                        VXIunsigned             tagID,
  1040.                                        const VXIchar*          subtag,
  1041.                                        const VXIchar*          format,
  1042.                                        ...)
  1043. {
  1044.   if (pThis == NULL)
  1045.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1046.   myAPI *temp = (myAPI *) pThis;
  1047.   SBlog *me = (SBlog *) temp->impl_;
  1048.   va_list args;
  1049.   va_start(args, format);
  1050.   VXIlogResult ret = me->DiagnosticLog(tagID, subtag, format, args);
  1051.   va_end(args);
  1052.   return ret;
  1053. }
  1054. SBLOG_API VXIlogResult SBlogVDiagnostic(VXIlogInterface*        pThis,
  1055.                                         VXIunsigned             tagID,
  1056.                                         const VXIchar*          subtag,
  1057.                                         const VXIchar*          format,
  1058.                                         va_list                 vargs)
  1059. {
  1060.   if (pThis == NULL)
  1061.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1062.   myAPI *temp = (myAPI *)pThis;
  1063.   SBlog *me = (SBlog *)temp->impl_;
  1064.   VXIlogResult ret = me->DiagnosticLog(tagID, subtag, format, vargs);
  1065.   return ret;
  1066. }
  1067. SBLOG_API VXIlogResult SBlogEvent(VXIlogInterface*        pThis,
  1068.                                   VXIunsigned             eventID,
  1069.                                   const VXIchar*          format,
  1070.                                   ...)
  1071. {
  1072.   if (pThis == NULL)
  1073.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1074.   myAPI *temp = (myAPI*)pThis;
  1075.   SBlog *me = (SBlog *)temp->impl_;
  1076.   va_list args;
  1077.   va_start(args, format);
  1078.   VXIlogResult ret = me->EventLog(eventID, format, args);
  1079.   va_end(args);
  1080.   return ret;
  1081. }
  1082. SBLOG_API VXIlogResult SBlogVEvent(VXIlogInterface*        pThis,
  1083.                                    VXIunsigned             eventID,
  1084.                                    const VXIchar*          format,
  1085.                                    va_list                 vargs)
  1086. {
  1087.   if (pThis == NULL)
  1088.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1089.   myAPI *temp = (myAPI*)pThis;
  1090.   SBlog *me = (SBlog *)temp->impl_;
  1091.   VXIlogResult ret = me->EventLog(eventID, format, vargs);
  1092.   return ret;
  1093. }
  1094. SBLOG_API VXIlogResult SBlogEventVector(VXIlogInterface*        pThis,
  1095. VXIunsigned             eventID,
  1096. const VXIVector*        keys,
  1097. const VXIVector*        values)
  1098. {
  1099.   if (pThis == NULL)
  1100.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1101.   myAPI *temp = (myAPI*)pThis;
  1102.   SBlog *me = (SBlog *)temp->impl_;
  1103.   VXIlogResult ret = me->EventLog(eventID, keys, values);
  1104.   return ret;
  1105. }
  1106. SBLOG_API VXIlogResult SBlogError(VXIlogInterface*        pThis,
  1107.                                   const VXIchar*          moduleName,
  1108.                                   VXIunsigned             errorID,
  1109.                                   const VXIchar*          format,
  1110.                                   ...)
  1111. {
  1112.   if (pThis == NULL)
  1113.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1114.   myAPI *temp = (myAPI*)pThis;
  1115.   SBlog *me = (SBlog *)temp->impl_;
  1116.   va_list args;
  1117.   va_start(args, format);
  1118.   VXIlogResult ret = me->ErrorLog(moduleName, errorID, format, args);
  1119.   va_end(args);
  1120.   return ret;
  1121. }
  1122. SBLOG_API VXIlogResult SBlogVError(VXIlogInterface*        pThis,
  1123.                                    const VXIchar*          moduleName,
  1124.                                    VXIunsigned             errorID,
  1125.                                    const VXIchar*          format,
  1126.                                    va_list                 vargs)
  1127. {
  1128.   if (pThis == NULL)
  1129.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1130.   myAPI *temp = (myAPI*)pThis;
  1131.   SBlog *me = (SBlog *)temp->impl_;
  1132.   VXIlogResult ret = me->ErrorLog(moduleName, errorID, format, vargs);
  1133.   return ret;
  1134. }
  1135. SBLOG_API VXIlogResult SBlogContentOpen(VXIlogInterface*  pThis,
  1136. const VXIchar*    moduleName,
  1137. const VXIchar*    contentType,
  1138. VXIString**       logKey,
  1139. VXIString**       logValue,
  1140. VXIlogStream**    stream)
  1141. {
  1142.   if (pThis == NULL)
  1143.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1144.   myAPI *temp = (myAPI*)pThis;
  1145.   SBlog *me = (SBlog *)temp->impl_;
  1146.   VXIlogResult ret = me->ContentOpen(moduleName, contentType,
  1147.      logKey, logValue, stream);
  1148.   return ret;
  1149. }
  1150. SBLOG_API VXIlogResult SBlogContentClose(VXIlogInterface* pThis,
  1151.  VXIlogStream**   stream)
  1152. {
  1153.   if (pThis == NULL)
  1154.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1155.   myAPI *temp = (myAPI*)pThis;
  1156.   SBlog *me = (SBlog *)temp->impl_;
  1157.   VXIlogResult ret = me->ContentClose(stream);
  1158.   return ret;
  1159. }
  1160. SBLOG_API VXIlogResult SBlogContentWrite(VXIlogInterface* pThis,
  1161.  const VXIbyte*   buffer,
  1162.  VXIulong         buflen,
  1163.  VXIulong*        nwritten,
  1164.  VXIlogStream*    stream)
  1165. {
  1166.   if (pThis == NULL)
  1167.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1168.   myAPI *temp = (myAPI*)pThis;
  1169.   SBlog *me = (SBlog *)temp->impl_;
  1170.   VXIlogResult ret = me->ContentWrite(buffer, buflen, nwritten, stream);
  1171.   return ret;
  1172. }
  1173. // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  1174. /**
  1175.  * Global platform initialization of SBlog
  1176.  *
  1177.  * @result VXIlogResult 0 on success
  1178.  */
  1179. SBLOG_API VXIlogResult SBlogInit(void)
  1180. {
  1181.   if (gblInitialized == true) {
  1182.     SBlog::GlobalError(SBLOG_ERR_ALREADY_INITIALIZED);
  1183.     return VXIlog_RESULT_FATAL_ERROR;
  1184.   }
  1185.   gblInitialized = true;
  1186.   return VXIlog_RESULT_SUCCESS;
  1187. }
  1188. /**
  1189.  * Global platform shutdown of Log
  1190.  *
  1191.  * @result VXIlogResult 0 on success
  1192.  */
  1193. SBLOG_API VXIlogResult SBlogShutDown(void)
  1194. {
  1195.   if (gblInitialized == false) {
  1196.     SBlog::GlobalError(SBLOG_ERR_NOT_INITIALIZED);
  1197.     return VXIlog_RESULT_FATAL_ERROR;
  1198.   }
  1199.   gblInitialized = false;
  1200.   return VXIlog_RESULT_SUCCESS;
  1201. }
  1202. /**
  1203.  * Create a new log service handle
  1204.  *
  1205.  * @result VXIlogResult 0 on success 
  1206.  */
  1207. SBLOG_API VXIlogResult SBlogCreateResource(VXIlogInterface **log)
  1208. {
  1209.   if (gblInitialized == false) {
  1210.     SBlog::GlobalError(SBLOG_ERR_NOT_INITIALIZED);
  1211.     return VXIlog_RESULT_FATAL_ERROR;
  1212.   }
  1213.   if (log == NULL) {
  1214.     SBlog::GlobalError(309, L"SBlog: SBlogCreateResource() requires a "
  1215.        L"non-NULL log interface pointer", NULL);
  1216.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1217.   }
  1218.   myAPI *temp = new myAPI;
  1219.   if (temp == NULL) {
  1220.     SBlog::GlobalError(SBLOG_ERR_OUT_OF_MEMORY);
  1221.     return VXIlog_RESULT_OUT_OF_MEMORY;
  1222.   }
  1223.   memset (temp, 0, sizeof (myAPI));
  1224.   
  1225.   SBlog *me = new SBlog(&temp->intf);
  1226.   if (me == NULL) {
  1227.     delete temp;
  1228.     SBlog::GlobalError(SBLOG_ERR_OUT_OF_MEMORY);
  1229.     return VXIlog_RESULT_OUT_OF_MEMORY;
  1230.   }
  1231.   
  1232.   // Initialize the VXIlogInterface function pointers
  1233.   temp->intf.vxilog.GetVersion            = SBlogGetVersion;
  1234.   temp->intf.vxilog.GetImplementationName = SBlogGetImplementationName;
  1235.   temp->intf.vxilog.Error                 = SBlogError;
  1236.   temp->intf.vxilog.VError                = SBlogVError;
  1237.   temp->intf.vxilog.Diagnostic            = SBlogDiagnostic;
  1238.   temp->intf.vxilog.VDiagnostic           = SBlogVDiagnostic;
  1239.   temp->intf.vxilog.DiagnosticIsEnabled   = SBlogDiagnosticIsEnabled;
  1240.   temp->intf.vxilog.Event                 = SBlogEvent;
  1241.   temp->intf.vxilog.VEvent                = SBlogVEvent;
  1242.   temp->intf.vxilog.EventVector           = SBlogEventVector;
  1243.   temp->intf.vxilog.ContentOpen           = SBlogContentOpen;
  1244.   temp->intf.vxilog.ContentClose          = SBlogContentClose;
  1245.   temp->intf.vxilog.ContentWrite          = SBlogContentWrite;
  1246.   
  1247.   // Initialize the SBlogInterface functions
  1248.   temp->intf.RegisterErrorListener = SBlogRegisterErrorListener;
  1249.   temp->intf.UnregisterErrorListener = SBlogUnregisterErrorListener;
  1250.   temp->intf.RegisterDiagnosticListener = SBlogRegisterDiagnosticListener;
  1251.   temp->intf.UnregisterDiagnosticListener = SBlogUnregisterDiagnosticListener;
  1252.   temp->intf.RegisterEventListener = SBlogRegisterEventListener;
  1253.   temp->intf.UnregisterEventListener = SBlogUnregisterEventListener;
  1254.   temp->intf.RegisterContentListener = SBlogRegisterContentListener;
  1255.   temp->intf.UnregisterContentListener = SBlogUnregisterContentListener;
  1256.   temp->intf.ControlDiagnosticTag = SBlogControlDiagnosticTag;
  1257.   temp->impl_ = (void*)me;
  1258.   // Return the object
  1259.   *log = &temp->intf.vxilog;
  1260.   return VXIlog_RESULT_SUCCESS;
  1261. }
  1262. /**
  1263.  * Destroy the interface and free internal resources
  1264.  *
  1265.  * @result VXIlogResult 0 on success 
  1266.  */
  1267. SBLOG_API VXIlogResult SBlogDestroyResource(VXIlogInterface **log)
  1268. {
  1269.   if (gblInitialized == false) {
  1270.     SBlog::GlobalError(SBLOG_ERR_NOT_INITIALIZED);
  1271.     return VXIlog_RESULT_FATAL_ERROR;
  1272.   }
  1273.   if ((log == NULL) || (*log == NULL)) {
  1274.     SBlog::GlobalError(310, L"SBlog: SBlogDestroyResource() requires a "
  1275.        L"non-NULL log interface pointer", NULL);
  1276.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1277.   }
  1278.   // Delete the object
  1279.   myAPI *temp = (myAPI *) *log;
  1280.   SBlog *me = (SBlog *)temp->impl_;
  1281.   if (me) delete me;
  1282.   if (temp) delete temp;
  1283.   *log = NULL;
  1284.   return VXIlog_RESULT_SUCCESS;
  1285. }