ncbi_core.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:12k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbi_core.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 16:36:12  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.14
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbi_core.c,v 1000.0 2003/10/29 16:36:12 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Denis Vakatov
  35.  *
  36.  * File Description:
  37.  *   Types and code shared by all "ncbi_*.[ch]" modules.
  38.  *
  39.  */
  40. #include "ncbi_ansi_ext.h"
  41. #include <connect/ncbi_core.h>
  42. #include <stdlib.h>
  43. /******************************************************************************
  44.  *  IO status
  45.  */
  46. extern const char* IO_StatusStr(EIO_Status status)
  47. {
  48.     static const char* s_StatusStr[eIO_Unknown+1] = {
  49.         "Success",
  50.         "Timeout",
  51.         "Closed",
  52.         "Interrupt",
  53.         "Invalid argument",
  54.         "Not supported",
  55.         "Unknown"
  56.     };
  57.     assert(status >= eIO_Success  &&  status <= eIO_Unknown);
  58.     return s_StatusStr[status];
  59. }
  60. /******************************************************************************
  61.  *  MT locking
  62.  */
  63. /* Check the validity of the MT locker */
  64. #define MT_LOCK_VALID 
  65.     assert(lk->ref_count  &&  lk->magic_number == s_MT_LOCK_magic_number)
  66. /* MT locker data and callbacks */
  67. struct MT_LOCK_tag {
  68.   unsigned int     ref_count;    /* reference counter */
  69.   void*            user_data;    /* for "handler()" and "cleanup()" */
  70.   FMT_LOCK_Handler handler;      /* locking function */
  71.   FMT_LOCK_Cleanup cleanup;      /* cleanup function */
  72.   unsigned int     magic_number; /* used internally to make sure it's init'd */
  73. };
  74. static const unsigned int s_MT_LOCK_magic_number = 0x7A96283F;
  75. extern MT_LOCK MT_LOCK_Create
  76. (void*            user_data,
  77.  FMT_LOCK_Handler handler,
  78.  FMT_LOCK_Cleanup cleanup)
  79. {
  80.     MT_LOCK lk = (struct MT_LOCK_tag*) malloc(sizeof(struct MT_LOCK_tag));
  81.     lk->ref_count = 1;
  82.     lk->user_data = user_data;
  83.     lk->handler   = handler;
  84.     lk->cleanup   = cleanup;
  85.     lk->magic_number = s_MT_LOCK_magic_number;
  86.     return lk;
  87. }
  88. extern MT_LOCK MT_LOCK_AddRef(MT_LOCK lk)
  89. {
  90.     MT_LOCK_VALID;
  91.     lk->ref_count++;
  92.     return lk;
  93. }
  94. extern MT_LOCK MT_LOCK_Delete(MT_LOCK lk)
  95. {
  96.     if ( !lk )
  97.         return 0;
  98.     MT_LOCK_VALID;
  99.     if ( --lk->ref_count )
  100.         return lk;
  101.     if ( lk->handler ) {  /* weak extra protection */
  102.         verify(lk->handler(lk->user_data, eMT_Lock));
  103.         verify(lk->handler(lk->user_data, eMT_Unlock));
  104.     }
  105.     if ( lk->cleanup )
  106.         lk->cleanup(lk->user_data);
  107.     lk->magic_number++;
  108.     free(lk);
  109.     return 0;
  110. }
  111. extern int/*bool*/ MT_LOCK_DoInternal(MT_LOCK lk, EMT_Lock how)
  112. {
  113.     MT_LOCK_VALID;
  114.     if ( lk->handler )
  115.         return lk->handler(lk->user_data, how);
  116.     return -1 /* rightful non-doing */;
  117. }
  118. /******************************************************************************
  119.  *  ERROR HANDLING and LOGGING
  120.  */
  121. /* Lock/unlock the logger */
  122. #define LOG_LOCK_WRITE  verify(MT_LOCK_Do(lg->mt_lock, eMT_Lock))
  123. #define LOG_LOCK_READ   verify(MT_LOCK_Do(lg->mt_lock, eMT_LockRead))
  124. #define LOG_UNLOCK      verify(MT_LOCK_Do(lg->mt_lock, eMT_Unlock))
  125. /* Check the validity of the logger */
  126. #define LOG_VALID 
  127.     assert(lg->ref_count  &&  lg->magic_number == s_LOG_magic_number)
  128. /* Logger data and callbacks */
  129. struct LOG_tag {
  130.     unsigned int ref_count;
  131.     void*        user_data;
  132.     FLOG_Handler handler;
  133.     FLOG_Cleanup cleanup;
  134.     MT_LOCK      mt_lock;
  135.     unsigned int magic_number;  /* used internally, to make sure it's init'd */
  136. };
  137. static const unsigned int s_LOG_magic_number = 0x3FB97156;
  138. extern const char* LOG_LevelStr(ELOG_Level level)
  139. {
  140.     static const char* s_PostSeverityStr[eLOG_Fatal+1] = {
  141.         "TRACE",
  142.         "NOTE",
  143.         "WARNING",
  144.         "ERROR",
  145.         "CRITICAL_ERROR",
  146.         "FATAL_ERROR"
  147.     };
  148.     return s_PostSeverityStr[level];
  149. }
  150. extern LOG LOG_Create
  151. (void*        user_data,
  152.  FLOG_Handler handler,
  153.  FLOG_Cleanup cleanup,
  154.  MT_LOCK      mt_lock)
  155. {
  156.     LOG lg = (struct LOG_tag*) malloc(sizeof(struct LOG_tag));
  157.     lg->ref_count = 1;
  158.     lg->user_data = user_data;
  159.     lg->handler   = handler;
  160.     lg->cleanup   = cleanup;
  161.     lg->mt_lock   = mt_lock;
  162.     lg->magic_number = s_LOG_magic_number;
  163.     return lg;
  164. }
  165. extern void LOG_Reset
  166. (LOG          lg,
  167.  void*        user_data,
  168.  FLOG_Handler handler,
  169.  FLOG_Cleanup cleanup)
  170. {
  171.     LOG_LOCK_WRITE;
  172.     LOG_VALID;
  173.     if (lg->cleanup)
  174.         lg->cleanup(lg->user_data);
  175.     lg->user_data = user_data;
  176.     lg->handler   = handler;
  177.     lg->cleanup   = cleanup;
  178.     LOG_UNLOCK;
  179. }
  180. extern LOG LOG_AddRef(LOG lg)
  181. {
  182.     LOG_LOCK_WRITE;
  183.     LOG_VALID;
  184.     lg->ref_count++;
  185.     LOG_UNLOCK;
  186.     return lg;
  187. }
  188. extern LOG LOG_Delete(LOG lg)
  189. {
  190.     if ( !lg )
  191.         return 0;
  192.     LOG_LOCK_WRITE;
  193.     LOG_VALID;
  194.     if (lg->ref_count > 1) {
  195.         lg->ref_count--;
  196.         LOG_UNLOCK;
  197.         return lg;
  198.     }
  199.     LOG_UNLOCK;
  200.     LOG_Reset(lg, 0, 0, 0);
  201.     lg->ref_count--;
  202.     lg->magic_number++;
  203.     if ( lg->mt_lock )
  204.         MT_LOCK_Delete(lg->mt_lock);
  205.     free(lg);
  206.     return 0;
  207. }
  208. extern void LOG_WriteInternal
  209. (LOG         lg,
  210.  ELOG_Level  level,
  211.  const char* module,
  212.  const char* file,
  213.  int         line,
  214.  const char* message,
  215.  const void* raw_data,
  216.  size_t      raw_size)
  217. {
  218.     if ( lg ) {
  219.         LOG_LOCK_READ;
  220.         LOG_VALID;
  221.         assert(!raw_size || raw_data);
  222.         if ( lg->handler ) {
  223.             SLOG_Handler call_data;
  224.             call_data.level    = level;
  225.             call_data.module   = module;
  226.             call_data.file     = file;
  227.             call_data.line     = line;
  228.             call_data.message  = message;
  229.             call_data.raw_data = raw_data;
  230.             call_data.raw_size = raw_size;
  231.             lg->handler(lg->user_data, &call_data);
  232.         }
  233.         LOG_UNLOCK;
  234.     }
  235.     /* unconditional exit/abort on fatal error */
  236.     if (level == eLOG_Fatal) {
  237. #if defined(NDEBUG)
  238.         exit(1);
  239. #else
  240.         abort();
  241. #endif
  242.     }
  243. }
  244. /******************************************************************************
  245.  *  REGISTRY
  246.  */
  247. /* Lock/unlock the registry  */
  248. #define REG_LOCK_WRITE  verify(MT_LOCK_Do(rg->mt_lock, eMT_Lock))
  249. #define REG_LOCK_READ   verify(MT_LOCK_Do(rg->mt_lock, eMT_LockRead))
  250. #define REG_UNLOCK      verify(MT_LOCK_Do(rg->mt_lock, eMT_Unlock))
  251. /* Check the validity of the registry */
  252. #define REG_VALID 
  253.     assert(rg->ref_count  &&  rg->magic_number == s_REG_magic_number)
  254. /* Logger data and callbacks */
  255. struct REG_tag {
  256.     unsigned int ref_count;
  257.     void*        user_data;
  258.     FREG_Get     get;
  259.     FREG_Set     set;
  260.     FREG_Cleanup cleanup;
  261.     MT_LOCK      mt_lock;
  262.     unsigned int magic_number;  /* used internally, to make sure it's init'd */
  263. };
  264. static const unsigned int s_REG_magic_number = 0xA921BC08;
  265. extern REG REG_Create
  266. (void*        user_data,
  267.  FREG_Get     get,
  268.  FREG_Set     set,
  269.  FREG_Cleanup cleanup,
  270.  MT_LOCK      mt_lock)
  271. {
  272.     REG rg = (struct REG_tag*) malloc(sizeof(struct REG_tag));
  273.     rg->ref_count = 1;
  274.     rg->user_data = user_data;
  275.     rg->get       = get;
  276.     rg->set       = set;
  277.     rg->cleanup   = cleanup;
  278.     rg->mt_lock   = mt_lock;
  279.     rg->magic_number = s_REG_magic_number;
  280.     return rg;
  281. }
  282. extern void REG_Reset
  283. (REG          rg,
  284.  void*        user_data,
  285.  FREG_Get     get,
  286.  FREG_Set     set,
  287.  FREG_Cleanup cleanup,
  288.  int/*bool*/  do_cleanup)
  289. {
  290.     REG_LOCK_WRITE;
  291.     REG_VALID;
  292.     if (do_cleanup  &&  rg->cleanup)
  293.         rg->cleanup(rg->user_data);
  294.     rg->user_data = user_data;
  295.     rg->get       = get;
  296.     rg->set       = set;
  297.     rg->cleanup   = cleanup;
  298.     REG_UNLOCK;
  299. }
  300. extern REG REG_AddRef(REG rg)
  301. {
  302.     REG_LOCK_WRITE;
  303.     REG_VALID;
  304.     rg->ref_count++;
  305.     REG_UNLOCK;
  306.     return rg;
  307. }
  308. extern REG REG_Delete(REG rg)
  309. {
  310.     if ( !rg )
  311.         return 0;
  312.     REG_LOCK_WRITE;
  313.     REG_VALID;
  314.     if (rg->ref_count > 1) {
  315.         rg->ref_count--;
  316.         REG_UNLOCK;
  317.         return rg;
  318.     }
  319.     REG_UNLOCK;
  320.     REG_Reset(rg, 0, 0, 0, 0, 1/*true*/);
  321.     rg->ref_count--;
  322.     rg->magic_number++;
  323.     if ( rg->mt_lock )
  324.         MT_LOCK_Delete(rg->mt_lock);
  325.     free(rg);
  326.     return 0;
  327. }
  328. extern char* REG_Get
  329. (REG         rg,
  330.  const char* section,
  331.  const char* name,
  332.  char*       value,
  333.  size_t      value_size,
  334.  const char* def_value)
  335. {
  336.     if (value_size <= 0  ||  !value)
  337.         return 0;
  338.     if ( def_value )
  339.         strncpy0(value, def_value, value_size - 1);
  340.     else
  341.         *value = '';
  342.     if ( !rg )
  343.         return value;
  344.     REG_LOCK_READ;
  345.     REG_VALID;
  346.     if ( rg->get )
  347.         rg->get(rg->user_data, section, name, value, value_size);
  348.     REG_UNLOCK;
  349.     return value;
  350. }
  351. extern void REG_Set
  352. (REG          rg,
  353.  const char*  section,
  354.  const char*  name,
  355.  const char*  value,
  356.  EREG_Storage storage)
  357. {
  358.     if ( !rg )
  359.         return;
  360.     REG_LOCK_READ;
  361.     REG_VALID;
  362.     if ( rg->set )
  363.         rg->set(rg->user_data, section, name, value, storage);
  364.     REG_UNLOCK;
  365. }
  366. /*
  367.  * ---------------------------------------------------------------------------
  368.  * $Log: ncbi_core.c,v $
  369.  * Revision 1000.0  2003/10/29 16:36:12  gouriano
  370.  * PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R6.14
  371.  *
  372.  * Revision 6.14  2003/08/28 18:47:51  ucko
  373.  * Revert previous hack (now handled another way)
  374.  *
  375.  * Revision 6.13  2003/08/27 12:32:30  ucko
  376.  * Yet another attempt to work around the WorkShop lossage with k*Timeout.
  377.  *
  378.  * Revision 6.12  2003/05/05 20:17:17  lavr
  379.  * LOG_WriteInternal() to require data ptr only if data size is not zero
  380.  *
  381.  * Revision 6.11  2003/02/20 17:52:12  lavr
  382.  * Status verbal names changed not to have caps in the middle
  383.  *
  384.  * Revision 6.10  2002/10/28 15:42:48  lavr
  385.  * Use "ncbi_ansi_ext.h" privately and use strncpy0()
  386.  *
  387.  * Revision 6.9  2002/08/13 19:30:13  lavr
  388.  * Verbal representation of eIO_Interrupt; log moved to end
  389.  *
  390.  * Revision 6.8  2001/08/09 16:24:29  lavr
  391.  * Remove last (unneeded) parameter from LOG_Reset()
  392.  *
  393.  * Revision 6.7  2001/04/25 20:52:29  vakatov
  394.  * LOG_WriteInternal() -- abort on "eLOG_Fatal" even if no logging is set
  395.  *
  396.  * Revision 6.6  2001/01/11 16:42:32  lavr
  397.  * Registry Get/Set methods got the 'user_data' argument, forgotten earlier
  398.  *
  399.  * Revision 6.5  2000/10/18 20:29:43  vakatov
  400.  * REG_Get::  pass in the default value (rather than '')
  401.  *
  402.  * Revision 6.4  2000/06/23 19:34:43  vakatov
  403.  * Added means to log binary data
  404.  *
  405.  * Revision 6.3  2000/05/30 23:21:36  vakatov
  406.  * LOG_WriteInternal():  exit/abort on "eLOG_Fatal"
  407.  *
  408.  * Revision 6.2  2000/03/24 23:12:07  vakatov
  409.  * Starting the development quasi-branch to implement CONN API.
  410.  * All development is performed in the NCBI C++ tree only, while
  411.  * the NCBI C tree still contains "frozen" (see the last revision) code.
  412.  *
  413.  * Revision 6.1  2000/02/23 22:36:16  vakatov
  414.  * Initial revision
  415.  *
  416.  * ===========================================================================
  417.  */