OS400PlatformUtils.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:24k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /**
  57.  * $Id: OS400PlatformUtils.cpp,v 1.8 2001/10/25 15:42:36 tng Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #define MY_XP_CPLUSPLUS
  63. #include    "OS400PlatformUtils.hpp"
  64. #include    <pthread.h>
  65. #include    <util/PlatformUtils.hpp>
  66. #include    <util/RuntimeException.hpp>
  67. #include    <util/Janitor.hpp>
  68. #include    <util/XMLString.hpp>
  69. #include    <util/XMLUniDefs.hpp>
  70. #include    <stdio.h>
  71. #include    <stdlib.h>
  72. #include    <errno.h>
  73. #include    <unistd.h>
  74. #include    <qp0z1170.h>
  75. #include    <mimchint.h>
  76. #include    <string.h>
  77. #include    <qmhsndpm.h>
  78. #include    <except.h>
  79. #include <mih/cmpswp.h>
  80. #if defined (XML_USE_ICONV400_TRANSCODER)
  81.     #include <util/Transcoders/Iconv400/Iconv400TransService.hpp>
  82. extern "C" void cleanupDefaultConverter();
  83. #elif defined (XML_USE_ICU_TRANSCODER)
  84.     #include <util/Transcoders/ICU/ICUTransService.hpp>
  85. #else
  86.  Transcoder not Specified - For OS/400 must be either ICU or Iconv400
  87. #endif
  88. #if defined(XML_USE_MSGFILE_MESSAGELOADER)
  89.  #include <util/MsgLoaders/MsgFile/MsgLoader.hpp>
  90. #elif defined(XML_USE_INMEM_MESSAGELOADER)
  91.  #include <util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
  92. #else
  93.  #include <util/MsgLoaders/ICU/ICUMsgLoader.hpp>
  94. #endif
  95. char* PackingRepText(const char * const repText1,
  96.      const char * const repText2,
  97.      const char * const repText3,
  98.      const char * const repText4);
  99. // ---------------------------------------------------------------------------
  100. //  Local Methods
  101. // ---------------------------------------------------------------------------
  102. static void WriteCharStr( FILE* stream, const char* const toWrite)
  103. {
  104.     if (fputs(toWrite, stream) == EOF)
  105.     {
  106. ThrowXML(XMLPlatformUtilsException, XMLExcepts::Strm_StdErrWriteFailure);
  107.     }
  108. }
  109. static void WriteUStrStdErr( const XMLCh* const toWrite)
  110. {
  111.     char* tmpVal = XMLString::transcode(toWrite);
  112.     ArrayJanitor<char> janText(tmpVal);
  113.     if (fputs(tmpVal, stderr) == EOF)
  114.     {
  115. ThrowXML(XMLPlatformUtilsException, XMLExcepts::Strm_StdErrWriteFailure);
  116.     }
  117. }
  118. static void WriteUStrStdOut( const XMLCh* const toWrite)
  119. {
  120. char* tmpVal = XMLString::transcode(toWrite);
  121.     ArrayJanitor<char> janText(tmpVal);
  122.     if (fputs(tmpVal, stdout) == EOF)
  123.     {
  124. ThrowXML(XMLPlatformUtilsException, XMLExcepts::Strm_StdOutWriteFailure);
  125.     }
  126. }
  127. XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
  128. {
  129.     return 0;
  130. }
  131. // ---------------------------------------------------------------------------
  132. //  XMLPlatformUtils: Platform init method
  133. // ---------------------------------------------------------------------------
  134. //
  135. //  This method is called very early in the bootstrapping process. This guy
  136. //  must create a transcoding service and return it. It cannot use any string
  137. //  methods, any transcoding services, throw any exceptions, etc... It just
  138. //  makes a transcoding service and returns it, or returns zero on failure.
  139. //
  140. XMLTransService* XMLPlatformUtils::makeTransService()
  141. #if defined (XML_USE_ICU_TRANSCODER)
  142. {
  143.     return new ICUTransService;
  144. }
  145. #elif defined (XML_USE_ICONV400_TRANSCODER)
  146. {
  147.     return new Iconv400TransService;
  148. }
  149. #else
  150. {
  151.     return new IconvTransService;
  152. }
  153. #endif
  154. //
  155. //  This method is called by the platform independent part of this class
  156. //  when client code asks to have one of the supported message sets loaded.
  157. //  In our case, we use the ICU based message loader mechanism.
  158. //
  159. XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
  160. {
  161.     XMLMsgLoader* retVal;
  162.     try
  163.     {
  164. #if defined(XML_USE_MSGFILE_MESSAGELOADER)
  165.         #include <util/MsgLoaders/MsgFile/MsgLoader.hpp>
  166.         retVal = new MsgCatalogLoader(msgDomain);
  167. #elif defined (XML_USE_ICU_MESSAGELOADER)
  168. retVal = new ICUMsgLoader(msgDomain);
  169. #elif defined (XML_USE_ICONV_MESSAGELOADER)
  170. retVal = new MsgCatalogLoader(msgDomain);
  171. #else
  172. retVal = new InMemMsgLoader(msgDomain);
  173. #endif
  174.     }
  175.     catch(...)
  176.     {
  177.         panic( XMLPlatformUtils::Panic_NoDefTranscoder );
  178.     }
  179.     return retVal;
  180. }
  181. // ---------------------------------------------------------------------------
  182. //  XMLPlatformUtils: The panic method
  183. // ---------------------------------------------------------------------------
  184. void XMLPlatformUtils::panic(const PanicReasons reason)
  185. {
  186.     //
  187.     //  We just print a message and exit, Note we are currently dependent on
  188.     // the number of reasons being under 10 for this teo work
  189.     //
  190.     {
  191. struct reason_code
  192.  {
  193.     char reason_char;
  194.     char endofstring;
  195.  }
  196.  reason_code;
  197.  reason_code.reason_char = '0';
  198.  reason_code.endofstring = '';
  199.  reason_code.reason_char = reason_code.reason_char + reason;
  200.  send_message((char*)&reason_code,GENERAL_PANIC_MESSAGE,'e');
  201. }
  202. }
  203. // ---------------------------------------------------------------------------
  204. //  XMLPlatformUtils: File Methods
  205. // ---------------------------------------------------------------------------
  206. unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile)
  207. {
  208.     // Get the current position
  209.     int curPos = ftell( (FILE*)theFile);
  210.     if (curPos == -1)
  211. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize);
  212.     return (unsigned int)curPos;
  213. }
  214. void XMLPlatformUtils::closeFile(FileHandle theFile)
  215. {
  216.     if (fclose((FILE*)theFile))
  217. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
  218. }
  219. unsigned int XMLPlatformUtils::fileSize(FileHandle theFile)
  220. {
  221.     // Get the current position
  222.     long  int curPos = ftell((FILE*)theFile);
  223.     if (curPos == -1)
  224. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);
  225.     // Seek to the end and save that value for return
  226.      if (fseek( (FILE*)theFile, 0, SEEK_END) )
  227. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd);
  228.     long int retVal = ftell( (FILE*)theFile);
  229.     if (retVal == -1)
  230. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd);
  231.     // And put the pointer back
  232.     if (fseek( (FILE*)theFile, curPos, SEEK_SET) )
  233. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToPos);
  234.     return (unsigned int)retVal;
  235. }
  236. #include <qmhrtvm.h>
  237. #include <qusec.h>
  238. FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName)
  239. {   char errno_id[7];
  240.     const char* tmpFileName = XMLString::transcode(fileName);
  241.     ArrayJanitor<char> janText((char*)tmpFileName);
  242.     errno = 0;
  243.     FileHandle retVal = (FILE*)fopen( tmpFileName , "rb" );
  244.     if (retVal == NULL)
  245.     {
  246.      send_message((char*)tmpFileName,FILE_OPEN_PROBLEMS,'d');
  247.      convert_errno(errno_id,errno);
  248.      send_message(NULL,errno_id,'d');
  249.         return 0;
  250.     }
  251.     return retVal;
  252. }
  253. FileHandle XMLPlatformUtils::openFile(const char* const fileName)
  254. {   char errno_id[7];
  255.     errno = 0;
  256.     FileHandle retVal = (FILE*)fopen( fileName , "rb" );
  257.     if (retVal == NULL)
  258.     {
  259.      send_message((char*)fileName,FILE_OPEN_PROBLEMS,'d');
  260.      convert_errno(errno_id,errno);
  261.      send_message(NULL,errno_id,'d');
  262.         return 0;
  263.     }
  264.     return retVal;
  265. }
  266. unsigned int
  267. XMLPlatformUtils::readFileBuffer(  FileHandle      theFile
  268.                                 , const unsigned int    toRead
  269.                                 , XMLByte* const  toFill)
  270. {
  271.     size_t noOfItemsRead = fread( (void*) toFill, 1, toRead, (FILE*)theFile);
  272.     if(ferror((FILE*)theFile))
  273.     {
  274. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
  275.     }
  276.     return (unsigned int)noOfItemsRead;
  277. }
  278. void XMLPlatformUtils::resetFile(FileHandle theFile)
  279. {
  280.     // Seek to the start of the file
  281.     if (fseek((FILE*)theFile, 0, SEEK_SET) )
  282. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile);
  283. }
  284. // ---------------------------------------------------------------------------
  285. //  XMLPlatformUtils: Timing Methods
  286. // ---------------------------------------------------------------------------
  287. unsigned long XMLPlatformUtils::getCurrentMillis()
  288. {
  289.  _MI_Time mt;
  290.          struct timeval tv;
  291.          int rc;
  292.          mattod(mt);
  293.    rc = Qp0zCvtToTimeval(&tv, mt, QP0Z_CVTTIME_TO_TIMESTAMP);
  294.    return((tv.tv_sec*1000 )+ (tv.tv_usec/1000));
  295. }
  296. /* since we do not have the realpath function on AS/400 and it appears
  297. to no be important that we convert the name to the real path we will
  298. only verify that the path exists  - note that this may make AS/400 output a different error for the pathname but customer should
  299. be able to determine what the name is suppose to be*/
  300. #include <unistd.h>
  301. #include <errno.h>
  302. #include <string.h>
  303. char *realpath(const char *file_name, char *resolved_name)
  304. {
  305.  if (file_name== NULL)
  306.  {
  307.    errno = EINVAL;
  308.    return(NULL);
  309.  }
  310.  if (access(file_name,F_OK)) /* verify that the file exists*/
  311.  {
  312.   errno = EACCES;
  313.   return(NULL);
  314.  }
  315.  else
  316.  /* code says that we make a copy of the file name so do it */
  317.   strcpy(resolved_name,file_name);
  318.   return(resolved_name);
  319. }
  320. XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath)
  321. {
  322.     //
  323.     //  NOTE: THe path provided has always already been opened successfully,
  324.     //  so we know that its not some pathological freaky path. It comes in
  325.     //  in native format, and goes out as Unicode always
  326.     //
  327.     char* newSrc = XMLString::transcode(srcPath);
  328.      ArrayJanitor<char> janText(newSrc);
  329.     // Use a local buffer that is big enough for the largest legal path
  330.     char *absPath = new char[256];
  331. //get the absolute path
  332.     char* retPath = realpath(newSrc, absPath);
  333.     ArrayJanitor<char> janText2(retPath);
  334.     if (!retPath)
  335.     {
  336. ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName);
  337.     }
  338.     return XMLString::transcode(absPath);
  339. }
  340. bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck)
  341. {
  342.     // Check for pathological case of empty path
  343.     if (!toCheck[0])
  344.         return false;
  345.     //
  346.     //  If it starts with a slash, then it cannot be relative. This covers
  347.     //  both something like "TestFile.xml" and an NT Lan type remote path
  348.     //  that starts with a node like "\MyNodeTestFile.xml".
  349.     //
  350.     if (*toCheck == chForwardSlash)
  351.         return false;
  352.     // Else assume its a relative path
  353.     return true;
  354. }
  355. XMLCh* XMLPlatformUtils::weavePaths
  356.     (
  357.         const   XMLCh* const    basePath
  358.         , const XMLCh* const    relativePath
  359.     )
  360. {
  361. // Create a buffer as large as both parts and empty it
  362.     XMLCh* tmpBuf = new XMLCh[XMLString::stringLen(basePath)
  363.                               + XMLString::stringLen(relativePath)
  364.                               + 2];
  365.     *tmpBuf = 0;
  366.     //
  367.     //  If we have no base path, then just take the relative path as
  368.     //  is.
  369.     //
  370.     if (!basePath)
  371.     {
  372.         XMLString::copyString(tmpBuf, relativePath);
  373.         return tmpBuf;
  374.     }
  375.     if (!*basePath)
  376.     {
  377.         XMLString::copyString(tmpBuf, relativePath);
  378.         return tmpBuf;
  379.     }
  380.     if (*relativePath == chForwardSlash)
  381.     {
  382.         XMLString::copyString(tmpBuf, relativePath);
  383.         return tmpBuf;
  384.     }
  385.     const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1);
  386.     if ((*basePtr != chForwardSlash)
  387.     &&  (*basePtr != chBackSlash))
  388.     {
  389.         while ((basePtr >= basePath)
  390.         &&     ((*basePtr != chForwardSlash) && (*basePtr != chBackSlash)))
  391.         {
  392.             basePtr--;
  393.         }
  394.     }
  395.     // There is no relevant base path, so just take the relative part
  396.     if (basePtr < basePath)
  397.     {
  398.         XMLString::copyString(tmpBuf, relativePath);
  399.         return tmpBuf;
  400.     }
  401.     // After this, make sure the buffer gets handled if we exit early
  402.     ArrayJanitor<XMLCh> janBuf(tmpBuf);
  403.     //
  404.     //  We have some path part, so we need to check to see if we ahve to
  405.     //  weave any of the parts together.
  406.     //
  407.     const XMLCh* pathPtr = relativePath;
  408.     while (true)
  409.     {
  410. // If it does not start with some period, then we are done
  411.         if (*pathPtr != chPeriod)
  412.             break;
  413.         unsigned int periodCount = 1;
  414.         pathPtr++;
  415.         if (*pathPtr == chPeriod)
  416.         {
  417.             pathPtr++;
  418.             periodCount++;
  419.         }
  420.         // Has to be followed by a  or / or the null to mean anything
  421.         if ((*pathPtr != chForwardSlash) && (*pathPtr != chBackSlash)
  422.         &&  *pathPtr)
  423.         {
  424.             break;
  425.         }
  426.         if (*pathPtr)
  427.             pathPtr++;
  428.         // If its one period, just eat it, else move backwards in the base
  429.         if (periodCount == 2)
  430.         {
  431.             basePtr--;
  432.             while ((basePtr >= basePath)
  433.             &&     ((*basePtr != chForwardSlash) && (*basePtr != chBackSlash)))
  434.             {
  435.                 basePtr--;
  436.             }
  437.             // The base cannot provide enough levels, so its in error/
  438.             if (basePtr < basePath)
  439.                 ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_BasePathUnderflow);
  440.         }
  441.     }
  442.     // Copy the base part up to the base pointer
  443.     XMLCh* bufPtr = tmpBuf;
  444.     const XMLCh* tmpPtr = basePath;
  445.     while (tmpPtr <= basePtr)
  446.         *bufPtr++ = *tmpPtr++;
  447.     // And then copy on the rest of our path
  448.     XMLString::copyString(bufPtr, pathPtr);
  449.     // Orphan the buffer and return it
  450.     janBuf.orphan();
  451. return tmpBuf;
  452. }
  453. void send_message (char * text, char * messageid, char type)
  454. {
  455.            short textsize;
  456.            char* buffer;
  457.            char* anchor;
  458.            char* id;
  459.            char message_id[8] = "CPF9897";/* id for raw txt
  460.                                              message                */
  461.            char message_file_name[21];
  462.            char message_type[11] ="*DIAG     ";/* send diagnostic
  463.                                                            message   */
  464.            char call_stack[11] ="*         " ;/* current callstack*/
  465.            int call_stack_counter= 0;/* sent to current call stack */
  466.            char message_key[4]; /* return value - not used          */
  467.             struct {
  468.              int bytes_available;
  469.              int bytes_used;
  470.              char exception_id[7];
  471.              char reserved;
  472.              char exception_data[1];
  473.                     } error_code;
  474.            int msg_size;
  475.           char* msg_type;
  476.          error_code.bytes_available = sizeof(error_code);
  477. /* check input parameters and set up the message information */
  478.          if (messageid != 0)  /* was a message id passed   */
  479.  {
  480.            if (strncmp(messageid,"CPF",3) &&
  481.                strncmp(messageid,"CPE",3))
  482.              strcpy(message_file_name,"QXMLMSG   *LIBL     ");
  483.            else
  484.              strcpy(message_file_name,"QCPFMSG   QSYS      ");
  485.            id = messageid; /* yes - use the id, will be
  486.                            in QCPFMSG                              */
  487.  }
  488.          else  /* just use what we have for immediate text          */
  489.  {
  490.            id = &message_id[0];
  491.            strcpy(message_file_name,"QCPFMSG   QSYS      ");
  492.  }
  493.          if (type == 'e')  /* is this the terminating exception     */
  494.               msg_type = "*COMP      ";/* set it as completion      */
  495.          else            /* currently all other messages are
  496.                              diagnostics                             */
  497.               msg_type = "*DIAG      ";
  498.          if (text != 0)                  /* was a text field passed           */
  499.          {
  500.           textsize = strlen(text);
  501.           msg_size = textsize + sizeof(short);
  502.           buffer = (char*)malloc(msg_size);
  503.           anchor = buffer;
  504.           memcpy(buffer, (void*)&textsize, sizeof(short));
  505.           buffer +=sizeof(short);
  506.           memcpy(buffer, text, textsize);
  507.          }
  508.          else
  509.            msg_size = 0;
  510.          #pragma exception_handler(jsendprob, 0, _C1_ALL, _C2_ALL,_CTLA_HANDLE)
  511.               QMHSNDPM((char *)id,&message_file_name,anchor,
  512.                      msg_size,(char*)msg_type,(char*)&call_stack,
  513.                      call_stack_counter,&message_key,&error_code);
  514.    jsendprob:
  515. #pragma disable_handler
  516.     return ;
  517. }
  518. void abnormal_termination(int termcode)
  519. {
  520.    send_message(NULL,"CPF9899",'e'); /* send final exception that we have terminated*/
  521. }
  522. // -----------------------------------------------------------------------
  523. //  Mutex methods
  524. // -----------------------------------------------------------------------
  525. #if !defined (APP_NO_THREADS)
  526. static pthread_mutex_t* gAtomicOpMutex =0 ;
  527. void XMLPlatformUtils::platformInit()
  528. {
  529.     //
  530.     // The gAtomicOpMutex mutex needs to be created
  531. // because compareAndSwap and incrementlocation and decrementlocation
  532. // does not have the atomic system calls for usage
  533.     // Normally, mutexes are created on first use, but there is a
  534.     // circular dependency between compareAndExchange() and
  535.     // mutex creation that must be broken.
  536.     gAtomicOpMutex = new pthread_mutex_t;
  537.     if (pthread_mutex_init(gAtomicOpMutex, NULL)) {
  538. delete gAtomicOpMutex;
  539. gAtomicOpMutex = 0;
  540.         panic( XMLPlatformUtils::Panic_SystemInit );
  541. }
  542. }
  543. class  RecursiveMutex
  544. {
  545. public:
  546.     pthread_mutex_t   mutex;
  547.     int               recursionCount;
  548.     pthread_t         tid;
  549.     RecursiveMutex() {
  550.        if (pthread_mutex_init(&mutex, NULL))
  551.     ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotCreate);
  552.                        recursionCount = 0;
  553.                        tid.reservedHiId = 0;
  554.        tid.reservedLoId = 0;
  555.                        tid.reservedHandle = 0;
  556.                      };
  557.     ~RecursiveMutex() {
  558. if (pthread_mutex_destroy(&mutex))
  559.     ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotDestroy);
  560.                       };
  561.      void lock()      {
  562.   if (pthread_equal(tid, pthread_self()))
  563.   {
  564.       recursionCount++;
  565.       return;
  566.   }
  567.   if (pthread_mutex_lock(&mutex) != 0)
  568.       ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotLock);
  569.   tid = pthread_self();
  570.   recursionCount = 1;
  571.       };
  572.      void unlock()    {
  573.                           if (--recursionCount > 0)
  574.                               return;
  575.   if (pthread_mutex_unlock(&mutex) != 0)
  576.       ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotUnlock);
  577.                           tid.reservedHandle= 0;
  578.   tid.reservedHiId = 0;
  579.   tid.reservedLoId = 0;
  580.                        };
  581.    };
  582. void* XMLPlatformUtils::makeMutex()
  583. {
  584.     return new RecursiveMutex;
  585. };
  586. void XMLPlatformUtils::closeMutex(void* const mtxHandle)
  587. {
  588.     if (mtxHandle == NULL)
  589.         return;
  590.     RecursiveMutex *rm = (RecursiveMutex *)mtxHandle;
  591.     delete rm;
  592. };
  593. void XMLPlatformUtils::lockMutex(void* const mtxHandle)
  594. {
  595.     if (mtxHandle == NULL)
  596.         return;
  597.     RecursiveMutex *rm = (RecursiveMutex *)mtxHandle;
  598.     rm->lock();
  599. }
  600. void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
  601. {
  602.     if (mtxHandle == NULL)
  603.         return;
  604.     RecursiveMutex *rm = (RecursiveMutex *)mtxHandle;
  605.     rm->unlock();
  606. }
  607. // -----------------------------------------------------------------------
  608. //  Miscellaneous synchronization methods
  609. // -----------------------------------------------------------------------
  610. //atomic system calls in Solaris is only restricted to kernel libraries
  611. //So, to make operations thread safe we implement static mutex and lock
  612. //the atomic operations. It makes the process slow but what's the alternative!
  613. void* XMLPlatformUtils::compareAndSwap ( void**      toFill ,
  614.                     const void* const newValue ,
  615.                     const void* const toCompare)
  616. {
  617.     //return ((void*)cas32( (uint32_t*)toFill,  (uint32_t)toCompare, (uint32_t)newValue) );
  618.     // the below calls are temporarily made till the above functions are part of user library
  619.     // Currently its supported only in the kernel mode
  620.     if (pthread_mutex_lock( gAtomicOpMutex))
  621.         panic(XMLPlatformUtils::Panic_SynchronizationErr);
  622.     void *retVal = *toFill;
  623.     if (*toFill == toCompare)
  624.               *toFill = (void *)newValue;
  625.     if (pthread_mutex_unlock( gAtomicOpMutex))
  626.         panic(XMLPlatformUtils::Panic_SynchronizationErr);
  627.     return retVal;
  628. }
  629. int XMLPlatformUtils::atomicIncrement(int &location)
  630. {
  631.     int current = location;
  632.     int new_loc = current+1;
  633.     while (_CMPSWP(&current,
  634.                    &location,
  635.                    new_loc) == 0)
  636.         new_loc = current+1;
  637.     int tmp = new_loc;
  638.     return tmp;
  639. }
  640. int XMLPlatformUtils::atomicDecrement(int &location)
  641. {
  642.     int current = location;
  643.     int new_loc = current-1;
  644.     while (_CMPSWP(&current,
  645.                    &location,
  646.                    new_loc) == 0)
  647.         new_loc = current-1;
  648.     int tmp = new_loc;
  649.     return tmp;
  650. }
  651. #else // #if !defined (APP_NO_THREADS)
  652. void XMLPlatformUtils::platformInit()
  653. {
  654.    // do nothing
  655. }
  656. void XMLPlatformUtils::closeMutex(void* const mtxHandle)
  657. {
  658. }
  659. void XMLPlatformUtils::lockMutex(void* const mtxHandle)
  660. {
  661. }
  662. void* XMLPlatformUtils::makeMutex()
  663. {
  664.         return 0;
  665. }
  666. void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
  667. {
  668. }
  669. void* XMLPlatformUtils::compareAndSwap ( void**      toFill,
  670.                                    const void* const newValue,
  671.                                    const void* const toCompare)
  672. {
  673.     void *retVal = *toFill;
  674.     if (*toFill == toCompare)
  675.        *toFill = (void *)newValue;
  676.     return retVal;
  677. }
  678. int XMLPlatformUtils::atomicIncrement(int &location)
  679. {
  680.     return ++location;
  681. }
  682. int XMLPlatformUtils::atomicDecrement(int &location)
  683. {
  684.     return --location;
  685. }
  686. #endif // APP_NO_THREADS
  687. /*
  688.  * convert the errno value to a cpf message identifier by converting the
  689.  * error to its decimal equivalent and appending "CPE" to the front
  690.  * note that the caller passes the storage for the message id as a parm
  691.  */
  692. void convert_errno(char* errno_id,int errnum)
  693.       {
  694. sprintf(errno_id,"CPE%d04" ,errnum );
  695. return;
  696.       }
  697. FileHandle XMLPlatformUtils::openStdInHandle()
  698. {
  699.     return (FileHandle)fdopen(dup(0), "rb");
  700. }
  701. void XMLPlatformUtils::platformTerm()
  702. {
  703. #if !defined (APP_NO_THREADS)
  704. pthread_mutex_destroy(gAtomicOpMutex);
  705.     delete gAtomicOpMutex;
  706. gAtomicOpMutex = 0;
  707. #endif
  708. #if defined (XML_USE_ICONV400_TRANSCODER)
  709. cleanupDefaultConverter();
  710. #endif
  711. }