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

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. #define SBLOGLISTENERS_EXPORTS
  24. #include "SBlogListeners.h"
  25. #include <wchar.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string>                // for STL string and wstring
  29. #include <sstream>               // for STL basic_ostringstream( )
  30. #include <limits.h>
  31. #include <cerrno>                // For errno to report fopen( ) errors
  32. #include <SBlog.h>
  33. #include <VXItrd.h>
  34. #include <VXItypes.h>
  35. #include <SBlogMapper.h>
  36. #include "SBlogOSUtils.h"
  37. #ifdef WIN32
  38. namespace std { };
  39. using namespace std;
  40. #define localtime_r(clock, result) 
  41.         ((result)->tm_sec = 0, localtime(clock))
  42. #endif
  43. static const VXIunsigned MAX_LOG_BUFFER  = 4096;
  44. #ifndef MAX_PATH
  45. #define MAX_PATH        1024
  46. #endif
  47. #define SBLOG_ERR_OUT_OF_MEMORY 100, L"SBlogListeners: Out of memory", NULL
  48. #define SBLOG_ERR_MUTEX_CREATE 101, L"SBlogListeners: Mutex create failed", NULL
  49. #define SBLOG_ERR_MUTEX_LOCK 102, L"SBlogListeners: Mutex lock failed", NULL
  50. #define SBLOG_ERR_MUTEX_UNLOCK 103, L"SBlogListeners: Mutex unlock failed", NULL
  51. #define SBLOG_ERR_ALREADY_INITIALIZED 104, L"SBlogListeners: Not initialized", NULL
  52. #define SBLOG_ERR_NOT_INITIALIZED 105, L"SBlogListeners: Not initialized", NULL
  53. #ifndef MODULE_PREFIX
  54. #define MODULE_PREFIX  COMPANY_DOMAIN L"."
  55. #endif
  56. #define MODULE_NAME MODULE_PREFIX     L"SBlog"
  57. static VXIbool gblLogPerformanceCounter = TRUE;
  58. /**********************************************************************/
  59. // Internal class definitions
  60. /**********************************************************************/
  61. static const VXIchar KEY_SEP     = L'=';
  62. static const char    N_KEY_SEP   =  '=';
  63. static const VXIchar ENTRY_SEP   = L'|';
  64. static const char    N_ENTRY_SEP =  '|';
  65. static const VXIchar ESCAPE      = L'\';
  66. static const char    N_ESCAPE    =  '\';
  67. class SBlogLogEntry{
  68. public:
  69.   enum LogEscapes {
  70.     ESCAPES_NONE,
  71.     ESCAPES_STANDARD,
  72.     ESCAPES_OSR_EVNT_LOG,
  73.   };
  74. public:
  75.   SBlogLogEntry(LogEscapes escapes = ESCAPES_STANDARD);
  76.   SBlogLogEntry(time_t, VXIunsigned);
  77.   ~SBlogLogEntry() {}
  78.   void SetEscapes(LogEscapes escapes) { escapes_ = escapes; }
  79.   VXIlogResult Append(const VXIchar*, VXIunsigned n);
  80.   VXIlogResult Append(const VXIVector *keys,
  81.           const VXIVector *values);
  82.   void operator+= (const VXIchar *val) { Append(val, 0); }
  83.   void operator+= (const VXIchar val) {
  84.     if (cur_size_ < MAX_LOG_BUFFER) {
  85.       entry_[cur_size_++] =  val;
  86.     }
  87.     entry_[cur_size_]=L'';
  88.     return ;
  89.   }
  90.   void operator+= (const char*);
  91.   void operator+= (long int);
  92.   void operator+= (VXIint32);
  93.   void operator+= (VXIunsigned);
  94.   void operator+= (VXIflt32);
  95.   void operator+= (VXIptr);
  96.   void operator+= (const VXIValue *);
  97.   void operator+= (VXIulong);
  98.   void operator+= (VXIflt64);
  99.   void AddKeySep() {
  100.     (*this) += KEY_SEP;
  101.   }
  102.   void AddEntrySep() {
  103.     (*this) += ENTRY_SEP;
  104.   }
  105.   void Terminate(bool addCpuTimes = true, bool addNewline = true);
  106.   const wchar_t *Entry()const {return entry_;}
  107.   
  108.   VXIunsigned size() const {
  109.     return cur_size_;
  110.   }
  111. protected:
  112.   LogEscapes escapes_;
  113.   unsigned int cur_size_;
  114.   wchar_t entry_[MAX_LOG_BUFFER+1];
  115. };
  116. class SBlogLogStream {
  117. private:
  118.   enum LogFormat {
  119.     FORMAT_TEXT_LATIN1 = 0,
  120.     FORMAT_TEXT_UTF8
  121.   };
  122. public:
  123.   SBlogLogStream();
  124.   virtual ~SBlogLogStream() {}
  125.   VXIlogResult Init(const VXIchar   *filename,
  126.         const VXIchar   *fileMimeType,
  127.         VXIint32         maxLogSizeBytes,
  128.         const VXIchar   *logContentDir,
  129.         VXIint32         maxContentDirSize,
  130.         VXIbool          logToStdout,
  131.         VXIbool          keepLogFileOpen,
  132.         VXIbool          reportErrorText,
  133.         const VXIVector *errorMapFiles);
  134.   VXIlogResult ShutDown();
  135.   VXIlogResult WriteEntry(const SBlogLogEntry& entry, 
  136.         VXIbool logToStdout = TRUE);
  137.   VXIlogResult CheckOpen();
  138.   VXIlogResult Open(VXIunsigned nextblock_size);
  139.   VXIlogResult Close();
  140.   VXIbool Enabled() {
  141.     if ((logfilename_ == NULL) && (! logToStdout_))
  142.       return FALSE;
  143.     return TRUE;
  144.   }
  145.   VXIbool ReportErrorText( ) { return reportErrorText_; }
  146.   const VXIchar *GetErrorText(VXIunsigned errorID, const VXIchar *moduleName,
  147.             const VXIchar **severity);
  148.   const VXIchar *GetContentDir(void) const { return logContentDir_; }
  149.   const char *GetNContentDir(void) const { return narrowLogContentDir_; }
  150.   const VXIint32 GetContentDirMaxSize(void) const { return maxContentDirSize_;}
  151.   // ----- Internal error logging functions
  152.   static VXIlogResult GlobalError(VXIunsigned errorID, 
  153.           const VXIchar *errorIDText,
  154.           const VXIchar *format, ...);
  155. protected:
  156.   VXItrdResult Lock() { 
  157.     VXItrdResult rc = VXItrdMutexLock(loglock_);
  158.     if (rc != VXItrd_RESULT_SUCCESS) GlobalError(SBLOG_ERR_MUTEX_LOCK);
  159.     return rc;
  160.   }
  161.   VXItrdResult Unlock() { 
  162.     VXItrdResult rc = VXItrdMutexUnlock(loglock_); 
  163.     if (rc != VXItrd_RESULT_SUCCESS) GlobalError(SBLOG_ERR_MUTEX_UNLOCK);
  164.     return rc;
  165.   }
  166. private:
  167.   SBlogErrorMapper *errorMapper_;
  168.   VXIchar *logfilename_;
  169.   VXIchar *logContentDir_;
  170.   char narrowlogfilename_[MAX_PATH];
  171.   char narrowLogContentDir_[MAX_PATH];
  172.   FILE *logFp_;
  173.   VXIint32 currentSize_;
  174.   VXIint32 maxLogSizeBytes_;
  175.   VXIint32 maxContentDirSize_;
  176.   LogFormat logFormat_;
  177.   VXIbool logToStdout_;
  178.   VXIbool keepLogFileOpen_;
  179.   VXIbool reportErrorText_;
  180.   VXItrdMutex *loglock_;
  181.   VXItrdMutex *internalErrorLoggingLock_;
  182.   VXIthreadID internalErrorLoggingThread_;
  183. };
  184. // ContentStream class
  185. class SBlogContentStream : public SBlogStream {
  186. public:
  187.   static const char PATH_SEPARATOR;
  188. public:
  189.   SBlogContentStream();
  190.   virtual ~SBlogContentStream();
  191.   VXIlogResult Open(const VXIchar *moduleName, 
  192.         const VXIchar *contentType,
  193.         const char *baseDir,
  194.         VXIint channel);
  195.   const VXIchar *GetPath(void) const { return wpath_.c_str(); }
  196.     
  197. private:
  198.   static VXIlogResult CallClose(struct SBlogStream  **stream);
  199.   static VXIlogResult CallWrite(struct SBlogStream *stream, 
  200.         const VXIbyte *buffer,
  201.         VXIulong buflen,
  202.         VXIulong *nwritten);
  203.   
  204.   VXIlogResult Close(void);
  205.   VXIlogResult Write(const VXIbyte *buffer, VXIulong buflen,
  206.          VXIulong *nwritten);
  207.   VXIlogResult CreatePath(const VXIchar *moduleName, 
  208.         const VXIchar *contentType,
  209.         const char *baseDir,
  210.         VXIint channel);
  211.   VXIlogResult CreateDirectories(void);
  212. private:
  213.   FILE *fp_;
  214.   std::string::size_type baseDirLen_;
  215.   std::string npath_;
  216.   std::basic_string<wchar_t> wpath_;
  217. };
  218. // define class static member
  219. #ifdef WIN32
  220. const char SBlogContentStream::PATH_SEPARATOR = '\';
  221. #else
  222. const char SBlogContentStream::PATH_SEPARATOR = '/';
  223. #endif
  224. // return file extension based on the given mine type
  225. // if the mine type is not recognized, no extension is generated.
  226. static const char* GetExtension(const VXIchar *mimetype)
  227. {
  228.   static const char EXT_ALAW[] = ".alaw";
  229.   static const char EXT_TXT[]  = ".txt";
  230.   static const char EXT_ULAW[] = ".ulaw";
  231.   static const char EXT_VOX[]  = ".vox";
  232.   static const char EXT_WAV[]  = ".wav";
  233.   static const char EXT_XML[]  = ".xml";
  234.   static const char EXT_VXML[] = ".vxml";
  235.   static const char EXT_L8[]   = ".L8";
  236.   static const char EXT_L16[]  = ".L16";
  237.   static const char EXT_UNKNOWN[] = "";
  238.   if (wcscmp(VXI_MIME_TEXT, mimetype) == 0 ||
  239.       wcscmp(VXI_MIME_UNICODE_TEXT, mimetype) == 0 ||
  240.       wcscmp(VXI_MIME_UTF16_TEXT, mimetype) == 0)
  241.   {
  242.     return EXT_TXT;
  243.   }
  244.   else if (wcscmp(VXI_MIME_XML, mimetype) == 0 ||
  245.      wcscmp(VXI_MIME_SSML, mimetype) == 0 ||
  246.      wcscmp(VXI_MIME_SRGS, mimetype) == 0)
  247.   {
  248.     return EXT_XML;
  249.   }
  250.   else if (wcscmp(VXI_MIME_VXML, mimetype) == 0)
  251.   {
  252.     return EXT_VXML;
  253.   }
  254.   else if (wcscmp(VXI_MIME_ALAW, mimetype) == 0)
  255.   {
  256.     return EXT_ALAW;
  257.   }
  258.   else if (wcscmp(VXI_MIME_WAV, mimetype) == 0) 
  259.   {
  260.     return EXT_WAV;
  261.   }
  262.   else if (wcscmp(VXI_MIME_LINEAR, mimetype) == 0)
  263.   {
  264.     return EXT_L8;
  265.   }
  266.   else if (wcscmp(VXI_MIME_LINEAR_16, mimetype) == 0 ||
  267.      wcscmp(VXI_MIME_LINEAR_16_16KHZ, mimetype) == 0)
  268.   {
  269.     return EXT_L16;
  270.   }
  271.   else if (wcscmp(VXI_MIME_ULAW, mimetype) == 0)
  272.   {
  273.     return EXT_ULAW;
  274.   }
  275.   else if (wcscmp(VXI_MIME_VOX, mimetype) == 0)
  276.   {
  277.     return EXT_VOX;
  278.   }
  279.   else
  280.   {
  281.     return EXT_UNKNOWN;  
  282.   }
  283. }
  284. /**********************************************************************/
  285. // SBlogContentStream class implementation
  286. /**********************************************************************/
  287. // c'tor
  288. SBlogContentStream::SBlogContentStream() : 
  289.   SBlogStream(), fp_(NULL), baseDirLen_(0), npath_(), wpath_()
  290. {
  291.   SBlogStream::Close = CallClose;
  292.   SBlogStream::Write = CallWrite;
  293. }
  294. // d'tor
  295. SBlogContentStream::~SBlogContentStream()
  296. {
  297.   if (fp_)
  298.     fclose(fp_);
  299. }
  300. // create path
  301. VXIlogResult SBlogContentStream::CreatePath(const VXIchar *moduleName, 
  302.               const VXIchar *contentType,
  303.               const char *baseDir,
  304.               VXIint channel)
  305. {
  306.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  307.   // Create the content path, with the file name based on a timestamp
  308.   // to millisecond granularity
  309.   std::basic_ostringstream<char> pathStream;
  310.   if (( baseDir ) && ( *baseDir )) {
  311.     baseDirLen_ = strlen (baseDir);
  312.     pathStream << baseDir << PATH_SEPARATOR;
  313.   }
  314.   if (( moduleName ) && ( *moduleName )) {
  315.     for (const VXIchar *ptr = moduleName; *ptr; ptr++) {
  316.       if ((( *ptr >= L'0' ) && ( *ptr <= L'9' )) ||
  317.           (( *ptr >= L'A' ) && ( *ptr <= L'Z' )) ||
  318.           (( *ptr >= L'a' ) && ( *ptr <= L'z' )) ||
  319.           ( *ptr == L'.'  ) || ( *ptr == PATH_SEPARATOR)
  320.           )
  321.         pathStream << static_cast<char>(*ptr);
  322.       else
  323.         pathStream << '_';
  324.     }
  325.   } else {
  326.     pathStream << "unknown_module";
  327.   }
  328.   pathStream << PATH_SEPARATOR;
  329.   
  330.   // Construct the file name
  331.   char logNFileName[32];
  332.   time_t tnow;
  333.   VXIunsigned mSec;
  334.   SBlogGetTime(&tnow, &mSec);
  335.   struct tm *ts, ts_r = { 0 };
  336.   ts = localtime_r(&tnow, &ts_r);
  337.   ts->tm_year = (ts->tm_year < 1900 ? ts->tm_year + 1900 : ts->tm_year); // y2k
  338.   ts->tm_mon++;  // tm_mon is 0 base
  339.   sprintf(logNFileName, "%03d-%d%02d%02d%02d%02d%02d%03d", 
  340.           channel, ts->tm_year, ts->tm_mon, ts->tm_mday,
  341.           ts->tm_hour, ts->tm_min, ts->tm_sec, mSec);
  342.   // Construct the final path
  343.   pathStream << logNFileName << GetExtension(contentType);
  344.   npath_ = pathStream.str();
  345.   // Convert back to wide characters
  346.   for (std::string::size_type i = 0; i < npath_.size( ); i++)
  347.     wpath_ += static_cast<wchar_t>(npath_[i]);
  348.   return rc;
  349. }
  350. // Create the directory tree for the path
  351. VXIlogResult SBlogContentStream::CreateDirectories( ) 
  352. {
  353.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  354.   // Go through the directories for the relative portion and create them
  355.   std::string::size_type componentLen = baseDirLen_;
  356.   while (componentLen != std::string::npos) {
  357.     std::string tempPath (npath_, 0, componentLen);
  358.     SBlogMkDir (tempPath.c_str());
  359.     componentLen = npath_.find_first_of ("/\", componentLen + 1);
  360.   }
  361.   return rc;
  362. }
  363. // open content stream
  364. VXIlogResult SBlogContentStream::Open(const VXIchar *moduleName, 
  365.               const VXIchar *contentType,
  366.               const char *baseDir,
  367.               VXIint channel)
  368. {
  369.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  370.   rc = CreatePath(moduleName, contentType, baseDir, channel);
  371.   if ( rc == VXIlog_RESULT_SUCCESS )
  372.     rc = CreateDirectories();
  373.   if ( rc == VXIlog_RESULT_SUCCESS ) {
  374.     fp_ = fopen(npath_.c_str(), "wb");
  375.     if ( fp_ == NULL ) {
  376.       SBlogLogStream::GlobalError(252, 
  377.                   L"SBlogListeners: Content log file open failed", 
  378.       L"%s%S%s%S%s%d", L"file", npath_.c_str(),
  379.       L"errnoStr", strerror(errno), L"errno", errno);
  380.       return VXIlog_RESULT_IO_ERROR;
  381.     }
  382.   }
  383.   return rc;
  384. }
  385. // close content stream
  386. VXIlogResult SBlogContentStream::Close()
  387. {
  388.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  389.   if ( fp_ ) {
  390.     fclose(fp_);
  391.     fp_ = NULL;
  392.   }
  393.   return rc;
  394. }
  395. VXIlogResult SBlogContentStream::CallClose(struct SBlogStream **stream)
  396. {
  397.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  398.   if ( stream == NULL || *stream == NULL ) 
  399.     return VXIlog_RESULT_INVALID_ARGUMENT;
  400.   SBlogContentStream *myStream = static_cast<SBlogContentStream *>(*stream);
  401.   rc = myStream->Close();
  402.   delete myStream;
  403.   *stream = NULL;
  404.   return rc;
  405. }
  406. // write content stream
  407. VXIlogResult SBlogContentStream::Write( const VXIbyte *buffer, 
  408.           VXIulong buflen, VXIulong *nwritten)
  409. {
  410.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  411.   if ( fp_ == NULL ) return VXIlog_RESULT_FAILURE;
  412.   *nwritten =  fwrite (buffer, 1, buflen, fp_);
  413.   if ( *nwritten == 0 ) {
  414.     if ( ferror (fp_) ) {
  415.       SBlogLogStream::GlobalError(253, 
  416.                   L"SBlogListeners: Content logging file write failed", 
  417.       L"%s%S%s%S%s%d", L"file", npath_.c_str(),
  418.       L"errnoStr", strerror(errno), L"errno", errno);
  419.       rc = VXIlog_RESULT_IO_ERROR;
  420.     } else {
  421.       rc = VXIlog_RESULT_NON_FATAL_ERROR;
  422.     } 
  423.   }
  424.   return rc;
  425. }
  426. VXIlogResult SBlogContentStream::CallWrite(struct SBlogStream *stream, 
  427.              const VXIbyte *buffer,
  428.              VXIulong buflen,
  429.              VXIulong *nwritten)
  430. {
  431.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  432.   if ( stream == NULL ) return VXIlog_RESULT_INVALID_ARGUMENT;
  433.   SBlogContentStream *myStream = static_cast<SBlogContentStream *>(stream);
  434.   rc = myStream->Write(buffer, buflen, nwritten);
  435.   return rc;
  436. }
  437. /**********************************************************************/
  438. // globals to the file
  439. /**********************************************************************/
  440. static SBlogLogStream *g_LogStream=NULL;
  441. /**********************************************************************/
  442. // Logging class implementation
  443. /**********************************************************************/
  444. SBlogLogEntry::SBlogLogEntry(LogEscapes escapes)
  445. {
  446.   escapes_ = escapes;
  447.   cur_size_ = 0;
  448. }
  449. SBlogLogEntry::SBlogLogEntry(time_t timestamp, VXIunsigned timestampMsec)
  450. {
  451.   escapes_ = ESCAPES_STANDARD;
  452.   cur_size_ = 0;
  453.   char timestampStr[128];
  454.   SBlogGetTimeStampStr(timestamp,timestampMsec,timestampStr);
  455.   (*this) += timestampStr;
  456. }
  457. VXIlogResult
  458. SBlogLogEntry::Append (const VXIchar* val, VXIunsigned n)
  459. {
  460.   unsigned int i = 0;
  461.   if (n <= 0)
  462.     n = wcslen(val);
  463.   // strip leading and trailing whitespace
  464.   while ((n > 0) && (SBlogIsSpace(val[n-1]))) n--;
  465.   while ((i < n) && (SBlogIsSpace(val[i]))) i++;
  466.   while((cur_size_ < MAX_LOG_BUFFER) && (i < n)) {
  467.     if (SBlogIsSpace(val[i])) {
  468.       entry_[cur_size_++] = L' ';
  469.     } else {
  470.       bool suppress = false;
  471.       switch(escapes_) {
  472.         case ESCAPES_STANDARD:
  473.           // CC: Remove \ 
  474.           //if ((val[i] == KEY_SEP) || (val[i] == ENTRY_SEP) || (val[i] == ESCAPE))
  475.           //  entry_[cur_size_++] = ESCAPE;
  476.           break;
  477.         case ESCAPES_OSR_EVNT_LOG:
  478.           if (val[i] == ENTRY_SEP) {
  479.             // In OSR event log, escape for | is putting 2 in a row
  480.             entry_[cur_size_++] = ENTRY_SEP;
  481.           } else if (val[i] == KEY_SEP) {
  482.             // In OSR event log, no escape defined for =
  483.             suppress = true;
  484.             entry_[cur_size_++] = L'-';
  485.             entry_[cur_size_++] = L'>';
  486.           }
  487.           break;
  488.         default:
  489.           break;
  490.       }
  491.       if (! suppress)
  492.         entry_[cur_size_++] = val[i];
  493.     }
  494.     i++;
  495.   }
  496.   entry_[cur_size_]=L'';
  497.   return VXIlog_RESULT_SUCCESS;
  498. }
  499. VXIlogResult 
  500. SBlogLogEntry::Append(const VXIVector *keys,
  501.           const VXIVector *values)
  502. {
  503.   if ((! keys) || (! values))
  504.     return VXIlog_RESULT_INVALID_ARGUMENT;
  505.   VXIunsigned index = VXIVectorLength(keys);
  506.   for(VXIunsigned i = 0; i < index; i++) {
  507.     const VXIValue *key = VXIVectorGetElement(keys, i);
  508.     const VXIValue *value = VXIVectorGetElement(values, i);
  509.     if (!key || !value)
  510.       break;
  511.     *this += key;
  512.     AddKeySep();
  513.     *this += value;
  514.     if (i < index - 1) AddEntrySep();
  515.   }
  516.   return VXIlog_RESULT_SUCCESS;
  517. }
  518. void 
  519. SBlogLogEntry::operator+= (const char* val)
  520. {
  521.   unsigned int i = 0;
  522.   unsigned int n = strlen(val);
  523.   // strip leading and trailing whitespace
  524.   while ((n > 0) && (SBlogIsSpace(val[n-1]))) n--;
  525.   while ((i < n) && (SBlogIsSpace(val[i]))) i++;
  526.   while((cur_size_ < MAX_LOG_BUFFER) && (i < n)) {
  527.     if (SBlogIsSpace(val[i])) {
  528.       entry_[cur_size_++] = L' ';
  529.     } else {
  530.       bool suppress = false;
  531.       switch(escapes_) {
  532.         case ESCAPES_STANDARD:
  533.           // CC: Remove \
  534.           //if ((val[i] == KEY_SEP) || (val[i] == ENTRY_SEP) || (val[i] == ESCAPE))
  535.           //entry_[cur_size_++] = ESCAPE;
  536.           break;
  537.         case ESCAPES_OSR_EVNT_LOG:
  538.           if (val[i] == ENTRY_SEP) {
  539.             // In OSR event log, escape for | is putting 2 in a row
  540.             entry_[cur_size_++] = ENTRY_SEP;
  541.           } else if (val[i] == KEY_SEP) {
  542.             // In OSR event log, no escape defined for =
  543.             suppress = true;
  544.             entry_[cur_size_++] = L'-';
  545.             entry_[cur_size_++] = L'>';
  546.           }
  547.           break;
  548.         default:
  549.           break;
  550.       }
  551.       if (! suppress)
  552.         entry_[cur_size_++] = (VXIchar) val[i];
  553.     }
  554.     i++;
  555.   }
  556.   entry_[cur_size_]=L'';
  557. }
  558. void
  559. SBlogLogEntry::operator+= (VXIint32 val)
  560. {
  561.   char temp[128];
  562.   sprintf(temp,"%d",val);
  563.   (*this) += temp;
  564.   return ;
  565. }
  566. void
  567. SBlogLogEntry::operator+= (long int val)
  568. {
  569.   char temp[128];
  570.   sprintf(temp,"%ld",val);
  571.   (*this) += temp;
  572.   return ;
  573. }
  574. void
  575. SBlogLogEntry::operator+= (VXIunsigned val)
  576. {
  577.   char temp[128];
  578.   sprintf(temp,"%d",val);
  579.   (*this) += temp;
  580.   return ;
  581. }
  582. void
  583. SBlogLogEntry::operator+= (VXIflt32 val)
  584. {
  585.   char temp[128];
  586.   sprintf(temp,"%f",val);
  587.   (*this) += temp;
  588.   return ;
  589. }
  590. void
  591. SBlogLogEntry::operator+= (VXIulong val)
  592. {
  593.   char temp[128];
  594.   sprintf(temp,"%u",val);
  595.   (*this) += temp;
  596.   return ;
  597. }
  598. void
  599. SBlogLogEntry::operator+= (VXIflt64 val)
  600. {
  601.   char temp[128];
  602.   sprintf(temp,"%f",val);
  603.   (*this) += temp;
  604.   return ;
  605. }
  606. void
  607. SBlogLogEntry::operator+= (VXIptr val)
  608. {
  609.   char temp[128];
  610.   sprintf(temp,"0x%p",val);
  611.   (*this) += temp;
  612.   return ;
  613. }
  614. void
  615. SBlogLogEntry::operator+=(const VXIValue *value)
  616. {
  617.   switch (VXIValueGetType(value)) {
  618.   case VALUE_STRING:
  619.     (*this) += VXIStringCStr((const VXIString *) value);
  620.     break;
  621.   case VALUE_INTEGER:
  622.     (*this) += VXIIntegerValue((const VXIInteger *) value);
  623.     break;
  624.   case VALUE_FLOAT:
  625.     (*this) += VXIFloatValue((const VXIFloat *) value);
  626.     break;
  627.   case VALUE_DOUBLE:
  628.     (*this) += VXIDoubleValue((const VXIDouble *) value);
  629.     break;
  630.   case VALUE_ULONG:
  631.     (*this) += VXIULongValue((const VXIULong *) value);
  632.     break;
  633.   case VALUE_PTR:
  634.     (*this) += VXIPtrValue((const VXIPtr *) value);
  635.     break;
  636.   default:
  637.     (*this) += L"unsupported type ";
  638.     (*this) += VXIValueGetType(value);
  639.   }
  640. }
  641. void SBlogLogEntry::Terminate(bool addCpuTimes, bool addNewline)
  642. {
  643.   // overwrite addCpuTime param
  644.   addCpuTimes = (gblLogPerformanceCounter == TRUE ? true : false);
  645.   if (addCpuTimes) {
  646.     long userTime;
  647.     long kernelTime;
  648.     SBlogGetCPUTimes(&userTime,&kernelTime);
  649.     this->AddEntrySep();
  650.     (*this) += "UCPU";
  651.     this->AddKeySep();
  652.     (*this) += userTime;
  653.     
  654.     this->AddEntrySep();
  655.     (*this) += "SCPU";
  656.     this->AddKeySep();
  657.     (*this) += kernelTime;
  658.   }
  659.   
  660.   if (addNewline) {
  661.     if (cur_size_ == MAX_LOG_BUFFER)
  662.       cur_size_--;
  663.     entry_[cur_size_++] ='n';
  664.   }
  665.   entry_[cur_size_] = '';
  666. }
  667. SBlogLogStream::SBlogLogStream() :
  668.   errorMapper_(NULL),
  669.   logfilename_(NULL),
  670.   logContentDir_(NULL),
  671.   logFp_(NULL),
  672.   currentSize_(0),
  673.   maxLogSizeBytes_(0),
  674.   maxContentDirSize_(0),
  675.   logFormat_(FORMAT_TEXT_LATIN1),
  676.   logToStdout_(TRUE),
  677.   keepLogFileOpen_(TRUE),
  678.   reportErrorText_(FALSE),
  679.   loglock_(NULL),
  680.   internalErrorLoggingLock_(NULL),
  681.   internalErrorLoggingThread_((VXIthreadID) -1)
  682. {
  683.   narrowlogfilename_[0] = '';
  684.   narrowLogContentDir_[0] = '';
  685. }
  686. VXIlogResult
  687. SBlogLogStream::Init(const VXIchar   *filename,
  688.          const VXIchar   *fileMimeType,
  689.          VXIint32         maxLogSizeBytes,
  690.          const VXIchar   *logContentDir,
  691.          VXIint32         maxContentDirSize,
  692.          VXIbool          logToStdout,
  693.          VXIbool          keepLogFileOpen,
  694.          VXIbool          reportErrorText,
  695.          const VXIVector *errorMapFiles)
  696. {
  697.   int n;
  698.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  699.   // check the inputs
  700.   if (maxLogSizeBytes < 0) {
  701.     GlobalError(152, L"SBlogListeners: Invalid system log file size "
  702.                 L"limit configured", L"%s%ld", L"configured",
  703.                 (long) maxLogSizeBytes);
  704.     return VXIlog_RESULT_INVALID_ARGUMENT;
  705.   } else if (maxContentDirSize < 0) {
  706.     GlobalError(153, L"SBlogListeners: Invalid content logging file "
  707.                 L"size limit configured", L"%s%ld", L"configured",
  708.                 (long) maxContentDirSize);
  709.     return VXIlog_RESULT_INVALID_ARGUMENT;
  710.   }
  711.   if ((! fileMimeType) || (! fileMimeType[0]) ||
  712.       (wcscmp(fileMimeType, SBLOG_MIME_TEXT_LATIN1) == 0))
  713.     logFormat_ = FORMAT_TEXT_LATIN1;
  714.   else if (wcscmp(fileMimeType, SBLOG_MIME_TEXT_UTF8) == 0)
  715.     logFormat_ = FORMAT_TEXT_UTF8;
  716.   else {
  717.     GlobalError(150, L"SBlogListeners: Invalid system log file format "
  718.                 L"configured", L"%s%s", L"format", fileMimeType);
  719.     return VXIlog_RESULT_INVALID_ARGUMENT;
  720.   }
  721.   maxLogSizeBytes_ = maxLogSizeBytes;
  722.   maxContentDirSize_ = maxContentDirSize;
  723.   logToStdout_ = logToStdout;
  724.   keepLogFileOpen_ = keepLogFileOpen;
  725.   reportErrorText_ = reportErrorText;
  726.   if (logfilename_) {
  727.     delete [] logfilename_;
  728.     logfilename_ = NULL;
  729.   }
  730.   if (logContentDir_) {
  731.     delete [] logContentDir_;
  732.     logContentDir_ = NULL;
  733.   }
  734.   if (filename != NULL) { // write to a file otherwise only stdout
  735.     // copy the filename
  736.     n = wcslen(filename);
  737.     logfilename_ = new VXIchar[n+1];
  738.     if (!logfilename_) {
  739.       GlobalError(SBLOG_ERR_OUT_OF_MEMORY);
  740.       return VXIlog_RESULT_OUT_OF_MEMORY;
  741.     }
  742.     wcscpy(logfilename_, filename);
  743.     
  744.     // convert the file name path
  745.     SBlogWchar2Latin1(logfilename_, narrowlogfilename_, MAX_PATH);
  746.     rc = CheckOpen();
  747.   }
  748.   if (logContentDir != NULL) {
  749.     // copy the filename
  750.     n = wcslen(logContentDir);
  751.     logContentDir_ = new VXIchar[n+1];
  752.     if (!logContentDir_) {
  753.       GlobalError(SBLOG_ERR_OUT_OF_MEMORY);
  754.       return VXIlog_RESULT_OUT_OF_MEMORY;
  755.     }
  756.     wcscpy(logContentDir_, logContentDir);
  757.     
  758.     // convert the file name path
  759.     SBlogWchar2Latin1(logContentDir_, narrowLogContentDir_, MAX_PATH);
  760.     // reate the content directory
  761.     SBlogMkDir (narrowLogContentDir_);
  762.   }
  763.   // Create the mutexes
  764.   if ((VXItrdMutexCreate(&loglock_) != VXItrd_RESULT_SUCCESS) ||
  765.       (VXItrdMutexCreate(&internalErrorLoggingLock_) !=
  766.        VXItrd_RESULT_SUCCESS)) {
  767.     GlobalError(SBLOG_ERR_MUTEX_CREATE);
  768.     rc = VXIlog_RESULT_SYSTEM_ERROR;
  769.   }
  770.   // load the XML error files into a VXIMap member here
  771.   if (errorMapFiles)
  772.   {
  773.     VXIlogResult rc2 = SBlogErrorMapperCreate(errorMapFiles, &errorMapper_);
  774.     // write to log file if unable to display error text
  775.     if (rc2 != VXIlog_RESULT_SUCCESS && Enabled())
  776.     {
  777.       if( rc2 == VXIlog_RESULT_UNSUPPORTED )
  778.         GlobalError(350, L"XML error text lookup feature disabled because the "
  779.                     L"listener is compiled without defining HAVE_XERCES", NULL);
  780.       else
  781.         GlobalError(351, L"XML error text lookup feature disabled due to an "
  782.                     L"error in parsing the configured XML error files", NULL);
  783.     }
  784.   }
  785.   return rc;
  786. }
  787. VXIlogResult
  788. SBlogLogStream::ShutDown()
  789. {
  790.   if (errorMapper_) {
  791.     SBlogErrorMapperDestroy(&errorMapper_);
  792.     errorMapper_ = NULL;
  793.   }
  794.   if (logfilename_) {
  795.     delete [] logfilename_;
  796.     logfilename_ = NULL;
  797.   }
  798.   if (logContentDir_) {
  799.     delete [] logContentDir_;
  800.     logContentDir_ = NULL;
  801.   }
  802.   if (logFp_) {
  803.     fclose(logFp_);
  804.     logFp_ = NULL;
  805.   }
  806.   if ((loglock_) && (VXItrdMutexDestroy(&loglock_) != VXItrd_RESULT_SUCCESS))
  807.     return VXIlog_RESULT_SYSTEM_ERROR;
  808.   if ((internalErrorLoggingLock_) && 
  809.       (VXItrdMutexDestroy(&internalErrorLoggingLock_) != 
  810.        VXItrd_RESULT_SUCCESS))
  811.     return VXIlog_RESULT_SYSTEM_ERROR;
  812.   return VXIlog_RESULT_SUCCESS;
  813. }
  814. /*
  815.   Make sure the current file can be opened - safety during the intialize
  816.   */
  817. VXIlogResult
  818. SBlogLogStream::CheckOpen()
  819. {
  820.   if (narrowlogfilename_[0] == '') {
  821.     GlobalError(154, L"SBlogListeners: Invalid system log file name "
  822.                 L"configured", NULL);
  823.     return VXIlog_RESULT_PLATFORM_ERROR;
  824.   }
  825.   // See if the file exists and open it, getting the size
  826.   SBlogFileStats info;
  827.   if (SBlogGetFileStats(narrowlogfilename_, &info) == 0) {
  828.     currentSize_ = info.st_size;
  829.     logFp_ = fopen(narrowlogfilename_, "a");
  830.   } else {
  831.     currentSize_ = 0;
  832.     logFp_ = fopen(narrowlogfilename_, "w");
  833.   }
  834.   if (! logFp_) {
  835.     GlobalError(151, L"SBlogListeners: System log file open failed", 
  836.                 L"%s%S%s%S%s%d", L"file", narrowlogfilename_,
  837.                 L"errnoStr", strerror(errno), L"errno", errno);
  838.     return VXIlog_RESULT_IO_ERROR;
  839.   }
  840.   if (! keepLogFileOpen_) {
  841.     fclose(logFp_);
  842.     logFp_ = NULL;
  843.   }
  844.   return VXIlog_RESULT_SUCCESS;
  845. }
  846. VXIlogResult
  847. SBlogLogStream::Open(VXIunsigned nextblock_size)
  848. {
  849.   if (narrowlogfilename_[0] == '') {
  850.     GlobalError(154, L"SBlogListeners: Invalid system log file name "
  851.                 L"configured", NULL);
  852.     return VXIlog_RESULT_PLATFORM_ERROR;
  853.   }
  854.   if (! logFp_) {
  855.     // See if the file exists and open it, getting the size
  856.     SBlogFileStats info;
  857.     if (SBlogGetFileStats(narrowlogfilename_, &info) == 0) {
  858.       currentSize_ = info.st_size;
  859.     } else {
  860.       currentSize_ = 0;
  861.     }
  862.   }
  863.   if ((currentSize_ + nextblock_size) > (VXIunsigned) maxLogSizeBytes_) {
  864.     if (logFp_) {
  865.       fclose(logFp_);
  866.       logFp_ = NULL;
  867.     }
  868.     currentSize_ = 0;
  869.     char overflowName[MAX_PATH+64];
  870.     strcpy(overflowName,narrowlogfilename_);
  871.     strcat(overflowName,".old");
  872.     remove(overflowName);
  873.     if (rename(narrowlogfilename_,overflowName)) {
  874.       GlobalError(251, L"SBlogListeners: System log file rollover failed",
  875.                   L"%s%S%s%S%s%S%s%d", L"logFile", narrowlogfilename_, 
  876.                   L"rolloverFile", overflowName, L"errnoStr", strerror(errno),
  877.                   L"errno", errno);
  878.       return VXIlog_RESULT_IO_ERROR;
  879.     }
  880.     logFp_ = fopen(narrowlogfilename_, "w");
  881.   } else if (! logFp_) {
  882.     logFp_ = fopen(narrowlogfilename_, "a");
  883.   }
  884.   if (! logFp_) {
  885.     GlobalError(151, L"SBlogListeners: System log file open failed", 
  886.                 L"%s%S%s%S%s%d", L"file", narrowlogfilename_,
  887.                 L"errnoStr", strerror(errno), L"errno", errno);
  888.     return VXIlog_RESULT_IO_ERROR;
  889.   }
  890.   return VXIlog_RESULT_SUCCESS;
  891. }
  892. VXIlogResult
  893. SBlogLogStream::Close()
  894. {
  895.   if (!logFp_)
  896.     return VXIlog_RESULT_IO_ERROR;
  897.   if (! keepLogFileOpen_) {
  898.     fclose(logFp_);
  899.     logFp_ = NULL;
  900.   } else {
  901.     fflush(logFp_);
  902.   }
  903.   return VXIlog_RESULT_SUCCESS;
  904. }
  905. VXIlogResult
  906. SBlogLogStream::WriteEntry(const SBlogLogEntry &entry, VXIbool logToStdout)
  907. {
  908.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  909.   unsigned int nFileBytes = 0;
  910.   char latin1OutBuf[MAX_LOG_BUFFER + 1]; // make sure enough room
  911.   char utf8OutBuf[MAX_LOG_BUFFER * 4 + 1];
  912.   const char *fileBuf = NULL;
  913.   latin1OutBuf[0] = 0;
  914.   utf8OutBuf[0] = 0;
  915.   // Exit if there is nothing to write, should never happen
  916.   if (entry.size() == 0)
  917.     return VXIlog_RESULT_FATAL_ERROR;
  918.   if ((logfilename_ != NULL) || (logToStdout && logToStdout_)) {
  919.     // Generate Latin-1 and/or UTF-8 output as required. Note that
  920.     // Latin-1 is used for console output even when the log file
  921.     // format is not Latin-1 because under many operating
  922.     // system/compiler/console combinations wide character output
  923.     // doesn't work right.
  924.     switch (logFormat_) {
  925.     case FORMAT_TEXT_UTF8:
  926.       SBlogWchar2UTF8(entry.Entry(), utf8OutBuf, MAX_LOG_BUFFER * 4,
  927.           &nFileBytes);
  928.       fileBuf = utf8OutBuf;
  929.       break;
  930.     case FORMAT_TEXT_LATIN1:
  931.       SBlogWchar2Latin1(entry.Entry(), latin1OutBuf, MAX_LOG_BUFFER);
  932.       fileBuf = latin1OutBuf;
  933.       nFileBytes = entry.size();
  934.       break;
  935.     default:
  936.       GlobalError(150, L"SBlogListeners: Invalid system log file format "
  937.                   L"configured", NULL);
  938.       return VXIlog_RESULT_FATAL_ERROR;
  939.     }
  940. #ifndef WCHART_CONSOLE_OUTPUT
  941.     if ((logToStdout) && (logToStdout_) && (! latin1OutBuf[0]))
  942.       SBlogWchar2Latin1(entry.Entry(), latin1OutBuf, MAX_LOG_BUFFER);
  943. #endif
  944.   }
  945.   
  946.   if (nFileBytes == 0)
  947.     return VXIlog_RESULT_SUCCESS;
  948.   if (Lock() != VXItrd_RESULT_SUCCESS)
  949.     return VXIlog_RESULT_SYSTEM_ERROR;
  950.   if (logfilename_ != NULL) {
  951.     // proceed to log to stdout if enabled, but return the error code
  952.     rc = Open(entry.size());
  953.     if (rc == VXIlog_RESULT_SUCCESS) {
  954.       int nwrite = fwrite(fileBuf, 1, nFileBytes, logFp_);
  955.       if (nwrite == 0) {
  956.         // should disable logging.
  957.         GlobalError(250, L"SBlogListeners: System log file write failed", 
  958.                     L"%s%S%s%S%s%d", L"file", narrowlogfilename_,
  959.                     L"errnoStr", strerror(errno), L"errno", errno);
  960.         rc = VXIlog_RESULT_IO_ERROR;
  961.       } else {
  962.         currentSize_ += nwrite;
  963.         // to ensure we don't lose log lines on a crash/abort
  964.         fflush(logFp_);
  965.       }
  966.     }
  967.     VXIlogResult rc2 = Close();
  968.     if (rc2 != VXIlog_RESULT_SUCCESS)
  969.       rc = rc2;
  970.   }
  971.   if ((logToStdout) && (logToStdout_)) {
  972.     VXIlogResult rc2 = VXIlog_RESULT_SUCCESS;
  973. #ifdef WCHART_CONSOLE_OUTPUT
  974.     if (fputws(entry.Entry(), stdout) <= 0)
  975.       rc2 = VXIlog_RESULT_IO_ERROR;
  976. #else
  977.     if (fwrite(latin1OutBuf, 1, entry.size(), stdout) <= 0)
  978.       rc2 = VXIlog_RESULT_IO_ERROR;
  979. #endif
  980.     if (fflush(stdout) != 0)
  981.       rc = VXIlog_RESULT_IO_ERROR;
  982.     if (rc2 != VXIlog_RESULT_SUCCESS)
  983.       rc = rc2;
  984.   }
  985.   if (Unlock() != VXItrd_RESULT_SUCCESS)
  986.     rc = VXIlog_RESULT_SYSTEM_ERROR;
  987.   return rc;
  988. }
  989. const VXIchar *
  990. SBlogLogStream::GetErrorText(VXIunsigned errorID, const VXIchar *moduleName,
  991.            const VXIchar **severity)
  992. {
  993.   static const VXIchar *severityStr[4] = {
  994.     L"", L"CRITICAL", L"SEVERE", L"WARNING" };
  995.   VXIint severityNum = -1;
  996.   const VXIchar *errText;
  997.   
  998.   // mapping here
  999.   if (errorMapper_)
  1000.     SBlogErrorMapperGetErrorInfo(errorMapper_, errorID, moduleName,
  1001.          &errText, &severityNum);
  1002.   else
  1003.     errText = severityStr[0];
  1004.   if ((severityNum >= 1) && (severityNum <= 3))
  1005.     *severity = severityStr[severityNum];
  1006.   else
  1007.     *severity = severityStr[0];
  1008.   
  1009.   // If the mapping failed, this returned an empty string
  1010.   return errText;
  1011. }
  1012. VXIlogResult SBlogLogStream::GlobalError(VXIunsigned errorID, 
  1013.            const VXIchar *errorIDText,
  1014.            const VXIchar *format, ...)
  1015. {
  1016.   va_list args;
  1017.   va_start(args, format);
  1018.   VXIlogResult rc = SBlogVLogErrorToConsole(MODULE_NAME, errorID, errorIDText,
  1019.                                             format, args);
  1020.   va_end(args);
  1021.   return rc;
  1022. }
  1023. SBLOGLISTENERS_API void DiagnosticListener
  1024. (
  1025.   SBlogInterface *pThis,
  1026.   VXIunsigned tagID,
  1027.   const VXIchar* subtag,
  1028.   time_t timestamp,
  1029.   VXIunsigned timestampMsec,
  1030.   const VXIchar* printmsg,
  1031.   void *userdata
  1032. )
  1033. {
  1034.   // casting userdata
  1035.   SBlogListenerChannelData *data = (SBlogListenerChannelData *)userdata;
  1036.   if ( data == NULL ) return;
  1037.   // Exit immediately if no logging enabled
  1038.   if (!g_LogStream || !g_LogStream->Enabled())
  1039.     return;
  1040.   SBlogLogEntry entry(timestamp, timestampMsec);
  1041.   entry.AddEntrySep();
  1042.   entry += (long) VXItrdThreadGetID();
  1043.   // entry.AddEntrySep();
  1044.   entry.AddEntrySep();
  1045.   entry += data->channel;
  1046.   entry.AddEntrySep();
  1047.   entry += tagID;
  1048.   entry.AddEntrySep();
  1049.   entry += subtag;
  1050.   entry.AddEntrySep();
  1051.   entry += printmsg;
  1052.   entry.Terminate();
  1053.   g_LogStream->WriteEntry(entry);
  1054.   return;
  1055. }
  1056. SBLOGLISTENERS_API void ErrorListener
  1057. (
  1058.   SBlogInterface *pThis,
  1059.   const VXIchar *moduleName,
  1060.   VXIunsigned errorID,
  1061.   time_t timestamp,
  1062.   VXIunsigned timestampMsec,
  1063.   const VXIVector *keys,
  1064.   const VXIVector *values,
  1065.   void *userdata
  1066. )
  1067. {
  1068.   // casting userdata, even if we get NULL for pThis and userdata
  1069.   // proceed since we rely on that in SBlogStream::Error() above
  1070.   SBlogListenerChannelData *data = (SBlogListenerChannelData *)userdata;
  1071.   // Exit immediately if no logging enabled
  1072.   if (!g_LogStream || !g_LogStream->Enabled())
  1073.     return;
  1074.   // Lookup error text
  1075.   const VXIchar *errorText = L"", *severity = L"";
  1076.   if ( g_LogStream->ReportErrorText( ) )
  1077.     errorText = g_LogStream->GetErrorText (errorID, moduleName, &severity);
  1078.   SBlogLogEntry entry(timestamp, timestampMsec);
  1079.   entry.AddEntrySep();
  1080.   entry += (long) VXItrdThreadGetID();
  1081.   // entry.AddEntrySep();
  1082.   entry.AddEntrySep();
  1083.   if (data)
  1084.     entry += data->channel;
  1085.   else
  1086.     entry += -1;
  1087.   entry.AddEntrySep();
  1088.   entry += severity;
  1089.   entry.AddEntrySep();
  1090.   entry += moduleName;
  1091.   entry.AddEntrySep();
  1092.   entry += errorID;
  1093.   entry.AddEntrySep();
  1094.   entry += errorText;
  1095.   entry.AddEntrySep();
  1096.   entry.Append(keys, values);
  1097.   entry.Terminate();
  1098.   g_LogStream->WriteEntry(entry);
  1099. }
  1100. SBLOGLISTENERS_API void EventListener
  1101. (
  1102.   SBlogInterface *pThis,
  1103.   VXIunsigned eventID,
  1104.   time_t timestamp,
  1105.   VXIunsigned timestampMsec,
  1106.   const VXIVector *keys,
  1107.   const VXIVector *values,
  1108.   void *userdata
  1109. )
  1110. {
  1111.   // casting userdata
  1112.   SBlogListenerChannelData *data = (SBlogListenerChannelData *)userdata;
  1113.   if ( data == NULL ) return;
  1114.   // Exit immediately if no logging enabled
  1115.   if (!g_LogStream || !g_LogStream->Enabled())
  1116.     return;
  1117.   SBlogLogEntry entry(timestamp, timestampMsec);
  1118.   entry.AddEntrySep();
  1119.   entry += (long) VXItrdThreadGetID();
  1120.   entry.AddEntrySep();
  1121.   // entry.AddEntrySep();
  1122.   entry += data->channel;
  1123.   entry.AddEntrySep();
  1124.   entry += L"EVENT";
  1125.   entry.AddEntrySep();
  1126.   entry += eventID;
  1127.   entry.AddEntrySep();
  1128.   entry.Append(keys, values);
  1129.   entry.Terminate();
  1130.   g_LogStream->WriteEntry(entry, FALSE);
  1131. }
  1132. SBLOGLISTENERS_API VXIlogResult ContentListener
  1133. (
  1134.   SBlogInterface *pThis,
  1135.   const VXIchar  *moduleName,
  1136.   const VXIchar  *contentType,
  1137.   void           *userdata,
  1138.   VXIString     **logKey,
  1139.   VXIString     **logValue,
  1140.   SBlogStream   **stream
  1141. )
  1142. {
  1143.   // casting userdata
  1144.   SBlogListenerChannelData *data = (SBlogListenerChannelData *)userdata;
  1145.   if ( data == NULL ) return VXIlog_RESULT_INVALID_ARGUMENT;
  1146.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  1147.   *logKey = NULL;
  1148.   *logValue = NULL;
  1149.   *stream = NULL;
  1150.   // Exit immediately if no logging enabled
  1151.   if (!g_LogStream || !g_LogStream->Enabled())
  1152.     return VXIlog_RESULT_FAILURE;
  1153.   const char *baseDir = g_LogStream->GetNContentDir();
  1154.   VXIulong maxSize = g_LogStream->GetContentDirMaxSize();
  1155.   // only do open if content dir. and size is valid
  1156.   if (baseDir && *baseDir != 0 && maxSize > 0 )
  1157.   {
  1158.     SBlogContentStream *openedStream = new SBlogContentStream;
  1159.     rc = openedStream->Open(moduleName, contentType, baseDir, data->channel);
  1160.     if ( rc != VXIlog_RESULT_SUCCESS ) {
  1161.       delete openedStream;
  1162.     } else {  
  1163.       // create key & value for cross-reference
  1164.       VXIString *logKey_ = VXIStringCreate(L"contentURL");
  1165.       VXIString *logValue_ = VXIStringCreate(openedStream->GetPath());
  1166.       *logKey = logKey_;
  1167.       *logValue = logValue_;
  1168.       *stream = static_cast<SBlogStream *>(openedStream);
  1169.     }
  1170.   } else {
  1171.     rc = VXIlog_RESULT_FAILURE;
  1172.   }
  1173.   return rc;
  1174. }
  1175. /**********************************************************************/
  1176. // Public Interface
  1177. /**********************************************************************/
  1178. SBLOGLISTENERS_API VXIlogResult SBlogListenerInit
  1179. (
  1180.  const VXIchar   *filename,
  1181.  VXIint32         maxLogSizeBytes,
  1182.  VXIbool          logToStdout,
  1183.  VXIbool          keepLogFileOpen
  1184. )
  1185. {
  1186.   return SBlogListenerInitEx2(filename, NULL, maxLogSizeBytes, NULL, 0, 
  1187.                               logToStdout, keepLogFileOpen, FALSE, NULL);
  1188. }
  1189. SBLOGLISTENERS_API VXIlogResult SBlogListenerInitEx
  1190. (
  1191.  const VXIchar   *filename,
  1192.  VXIint32         maxLogSizeBytes,
  1193.  const VXIchar   *logContentDir,
  1194.  VXIint32         maxContentDirSize,
  1195.  VXIbool          logToStdout,
  1196.  VXIbool          keepLogFileOpen,
  1197.  VXIbool          reportErrorText,
  1198.  const VXIVector *errorMapFiles
  1199. )
  1200. {
  1201.   return SBlogListenerInitEx2(filename, NULL, maxLogSizeBytes, logContentDir,
  1202.                               maxContentDirSize, logToStdout, keepLogFileOpen,
  1203.                               reportErrorText, errorMapFiles);
  1204. }
  1205. SBLOGLISTENERS_API VXIlogResult SBlogListenerInitEx2
  1206. (
  1207.  const VXIchar   *filename,
  1208.  const VXIchar   *fileMimeType,
  1209.  VXIint32         maxLogSizeBytes,
  1210.  const VXIchar   *logContentDir,
  1211.  VXIint32         maxContentDirSize,
  1212.  VXIbool          logToStdout,
  1213.  VXIbool          keepLogFileOpen,
  1214.  VXIbool          reportErrorText,
  1215.  const VXIVector *errorMapFiles
  1216. )
  1217. {
  1218.   return SBlogListenerInitEx3(filename, fileMimeType, maxLogSizeBytes, 
  1219.                               logContentDir, maxContentDirSize, logToStdout, keepLogFileOpen,
  1220.                               TRUE, reportErrorText, errorMapFiles);
  1221. }
  1222. SBLOGLISTENERS_API VXIlogResult SBlogListenerInitEx3
  1223. (
  1224.  const VXIchar   *filename,
  1225.  const VXIchar   *fileMimeType,
  1226.  VXIint32         maxLogSizeBytes,
  1227.  const VXIchar   *logContentDir,
  1228.  VXIint32         maxContentDirSize,
  1229.  VXIbool          logToStdout,
  1230.  VXIbool          keepLogFileOpen,
  1231.  VXIbool          logPerformanceCounter,
  1232.  VXIbool          reportErrorText,
  1233.  const VXIVector *errorMapFiles
  1234. )
  1235. {
  1236.   if (g_LogStream != NULL) {
  1237.     SBlogLogStream::GlobalError(SBLOG_ERR_NOT_INITIALIZED);
  1238.     return VXIlog_RESULT_NON_FATAL_ERROR;
  1239.   }
  1240.   g_LogStream = new SBlogLogStream();
  1241.   if (!g_LogStream) {
  1242.     SBlogLogStream::GlobalError(SBLOG_ERR_OUT_OF_MEMORY);
  1243.     return VXIlog_RESULT_OUT_OF_MEMORY;
  1244.   }
  1245.   gblLogPerformanceCounter = logPerformanceCounter;
  1246.   return g_LogStream->Init(filename, fileMimeType, maxLogSizeBytes, 
  1247.                            logContentDir, maxContentDirSize, logToStdout,
  1248.                            keepLogFileOpen, reportErrorText, errorMapFiles);
  1249. }
  1250. SBLOGLISTENERS_API VXIlogResult SBlogListenerShutDown()
  1251. {
  1252.   if (g_LogStream == NULL) {
  1253.     SBlogLogStream::GlobalError(SBLOG_ERR_NOT_INITIALIZED);
  1254.     return VXIlog_RESULT_NON_FATAL_ERROR;
  1255.   }
  1256.   VXIlogResult ret = g_LogStream->ShutDown();
  1257.   if (ret) {
  1258.     return ret;
  1259.   }
  1260.   delete g_LogStream;
  1261.   g_LogStream = NULL;
  1262.   return ret;
  1263. }
  1264. SBLOGLISTENERS_API VXIlogResult ControlDiagnosticTag
  1265. (
  1266.  VXIlogInterface *pThis,
  1267.  VXIunsigned tagID,
  1268.  VXIbool     state
  1269. )
  1270. {
  1271.   if ( pThis == NULL ) {
  1272.     SBlogLogStream::GlobalError(254, 
  1273.                            L"SBlogListeners: Invalid argument to API function",
  1274.                            L"%s%s", L"function", L"ControlDiagnosticTag");
  1275.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1276.   }
  1277.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1278.   return( logIntf->ControlDiagnosticTag(logIntf, tagID, state) );
  1279. }
  1280. SBLOGLISTENERS_API VXIlogResult RegisterErrorListener
  1281. (
  1282.   VXIlogInterface           *pThis,
  1283.   SBlogErrorListener        *alistener,
  1284.   SBlogListenerChannelData  *channelData
  1285. )
  1286. {
  1287.   if ((pThis == NULL) || (channelData == NULL)) {
  1288.     SBlogLogStream::GlobalError(254, 
  1289.                            L"SBlogListeners: Invalid argument to API function",
  1290.                            L"%s%s", L"function", L"RegisterErrorListener");
  1291.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1292.   }
  1293.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1294.   return ( logIntf->RegisterErrorListener(logIntf,alistener,channelData) );
  1295. }
  1296. SBLOGLISTENERS_API VXIlogResult UnregisterErrorListener
  1297. (
  1298.   VXIlogInterface           *pThis,
  1299.   SBlogErrorListener        *alistener,
  1300.   SBlogListenerChannelData  *channelData
  1301. )
  1302. {
  1303.   if ((pThis == NULL) || (channelData == NULL)) {
  1304.     SBlogLogStream::GlobalError(254, 
  1305.           L"SBlogListeners: Invalid argument to API function",
  1306.           L"%s%s", L"function", L"UnregisterErrorListener");
  1307.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1308.   }
  1309.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1310.   return ( logIntf->UnregisterErrorListener(logIntf,alistener,channelData) );
  1311. }
  1312. SBLOGLISTENERS_API VXIlogResult RegisterDiagnosticListener
  1313. (
  1314.   VXIlogInterface           *pThis,
  1315.   SBlogDiagnosticListener   *alistener,
  1316.   SBlogListenerChannelData  *channelData
  1317. )
  1318. {
  1319.   if ((pThis == NULL) || (channelData == NULL)) {
  1320.     SBlogLogStream::GlobalError(254, 
  1321.                 L"SBlogListeners: Invalid argument to API function",
  1322.                 L"%s%s", L"function", L"RegisterDiagnosticListener");
  1323.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1324.   }
  1325.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1326.   return (logIntf->RegisterDiagnosticListener(logIntf,alistener,channelData));
  1327. }
  1328. SBLOGLISTENERS_API VXIlogResult UnregisterDiagnosticListener
  1329. (
  1330.   VXIlogInterface           *pThis,
  1331.   SBlogDiagnosticListener   *alistener,
  1332.   SBlogListenerChannelData  *channelData
  1333. )
  1334. {
  1335.   if ((pThis == NULL) || (channelData == NULL)) {
  1336.     SBlogLogStream::GlobalError(254,
  1337.           L"SBlogListeners: Invalid argument to API function",
  1338.           L"%s%s", L"function", L"UnregisterDiagnosticListener");
  1339.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1340.   }
  1341.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1342.   return (logIntf->UnregisterDiagnosticListener(logIntf,alistener,channelData));
  1343. }
  1344. SBLOGLISTENERS_API VXIlogResult RegisterEventListener
  1345. (
  1346.   VXIlogInterface           *pThis,
  1347.   SBlogEventListener        *alistener,
  1348.   SBlogListenerChannelData  *channelData
  1349. )
  1350. {
  1351.   if ((pThis == NULL) || (channelData == NULL)) {
  1352.     SBlogLogStream::GlobalError(254,
  1353.           L"SBlogListeners: Invalid argument to API function",
  1354.           L"%s%s", L"function", L"RegisterEventListener");
  1355.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1356.   }
  1357.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1358.   return(logIntf->RegisterEventListener(logIntf,alistener,channelData));
  1359.  
  1360. SBLOGLISTENERS_API VXIlogResult UnregisterEventListener
  1361. (
  1362.   VXIlogInterface           *pThis,
  1363.   SBlogEventListener        *alistener,
  1364.   SBlogListenerChannelData  *channelData
  1365. )
  1366. {
  1367.   if ((pThis == NULL) || (channelData == NULL)) {
  1368.     SBlogLogStream::GlobalError(254,
  1369.           L"SBlogListeners: Invalid argument to API function",
  1370.           L"%s%s", L"function", L"UnregisterEventListener");
  1371.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1372.   }
  1373.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1374.   return(logIntf->UnregisterEventListener(logIntf,alistener,channelData));  
  1375. }
  1376. SBLOGLISTENERS_API VXIlogResult RegisterContentListener
  1377. (
  1378.   VXIlogInterface           *pThis,
  1379.   SBlogContentListener      *alistener,
  1380.   SBlogListenerChannelData  *channelData
  1381. )
  1382. {
  1383.   if ((pThis == NULL) || (channelData == NULL)) {
  1384.     SBlogLogStream::GlobalError(254,
  1385.           L"SBlogListeners: Invalid argument to API function",
  1386.           L"%s%s", L"function", L"RegisterContentListener");
  1387.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1388.   }
  1389.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1390.   return(logIntf->RegisterContentListener(logIntf,alistener,channelData));
  1391.  
  1392. SBLOGLISTENERS_API VXIlogResult UnregisterContentListener
  1393. (
  1394.   VXIlogInterface           *pThis,
  1395.   SBlogContentListener      *alistener,
  1396.   SBlogListenerChannelData  *channelData
  1397. )
  1398. {
  1399.   if ((pThis == NULL) || (channelData == NULL)) {
  1400.     SBlogLogStream::GlobalError(254,
  1401.           L"SBlogListeners: Invalid argument to API function",
  1402.           L"%s%s", L"function", L"UnregisterContentListener");
  1403.     return VXIlog_RESULT_INVALID_ARGUMENT;
  1404.   }
  1405.   SBlogInterface *logIntf = (SBlogInterface *)pThis;
  1406.   return(logIntf->UnregisterContentListener(logIntf,alistener,channelData));  
  1407. }