NCBI C Toolkit Cross Reference

C/connect/ncbi_core.c


  1 /* $Id: ncbi_core.c,v 6.22 2008/12/01 16:34:35 kazimird Exp $
  2  * ===========================================================================
  3  *
  4  *                            PUBLIC DOMAIN NOTICE
  5  *               National Center for Biotechnology Information
  6  *
  7  *  This software/database is a "United States Government Work" under the
  8  *  terms of the United States Copyright Act.  It was written as part of
  9  *  the author's official duties as a United States Government employee and
 10  *  thus cannot be copyrighted.  This software/database is freely available
 11  *  to the public for use. The National Library of Medicine and the U.S.
 12  *  Government have not placed any restriction on its use or reproduction.
 13  *
 14  *  Although all reasonable efforts have been taken to ensure the accuracy
 15  *  and reliability of the software and data, the NLM and the U.S.
 16  *  Government do not and cannot warrant the performance or results that
 17  *  may be obtained by using this software or data. The NLM and the U.S.
 18  *  Government disclaim all warranties, express or implied, including
 19  *  warranties of performance, merchantability or fitness for any particular
 20  *  purpose.
 21  *
 22  *  Please cite the author in any work or product based on this material.
 23  *
 24  * ===========================================================================
 25  *
 26  * Author:  Denis Vakatov
 27  *
 28  * File Description:
 29  *   Types and code shared by all "ncbi_*.[ch]" modules.
 30  *
 31  */
 32 
 33 #include "ncbi_ansi_ext.h"
 34 #include "ncbi_assert.h"
 35 #include <connect/ncbi_core.h>
 36 #include <stdlib.h>
 37 
 38 
 39 /******************************************************************************
 40  *  IO status
 41  */
 42 
 43 extern const char* IO_StatusStr(EIO_Status status)
 44 {
 45     static const char* s_StatusStr[eIO_Unknown + 1] = {
 46         "Success",
 47         "Timeout",
 48         "Closed",
 49         "Interrupt",
 50         "Invalid argument",
 51         "Not supported",
 52         "Unknown"
 53     };
 54 
 55     assert(status >= eIO_Success  &&  status <= eIO_Unknown);
 56     return s_StatusStr[status];
 57 }
 58 
 59 
 60 
 61 /******************************************************************************
 62  *  MT locking
 63  */
 64 
 65 /* Check the validity of the MT locker */
 66 #define MT_LOCK_VALID \
 67     assert(lk->ref_count  &&  lk->magic_number == kMT_LOCK_magic_number)
 68 
 69 
 70 /* MT locker data and callbacks */
 71 struct MT_LOCK_tag {
 72   unsigned int     ref_count;    /* reference counter */
 73   void*            user_data;    /* for "handler()" and "cleanup()" */
 74   FMT_LOCK_Handler handler;      /* locking function */
 75   FMT_LOCK_Cleanup cleanup;      /* cleanup function */
 76   unsigned int     magic_number; /* used internally to make sure it's init'd */
 77 };
 78 static const unsigned int kMT_LOCK_magic_number = 0x7A96283F;
 79 
 80 
 81 extern MT_LOCK MT_LOCK_Create
 82 (void*            user_data,
 83  FMT_LOCK_Handler handler,
 84  FMT_LOCK_Cleanup cleanup)
 85 {
 86     MT_LOCK lk = (struct MT_LOCK_tag*) malloc(sizeof(struct MT_LOCK_tag));
 87 
 88     if (lk) {
 89         lk->ref_count    = 1;
 90         lk->user_data    = user_data;
 91         lk->handler      = handler;
 92         lk->cleanup      = cleanup;
 93         lk->magic_number = kMT_LOCK_magic_number;
 94     }
 95     return lk;
 96 }
 97 
 98 
 99 extern MT_LOCK MT_LOCK_AddRef(MT_LOCK lk)
100 {
101     MT_LOCK_VALID;
102     lk->ref_count++;
103     return lk;
104 }
105 
106 
107 extern MT_LOCK MT_LOCK_Delete(MT_LOCK lk)
108 {
109     if (lk) {
110         MT_LOCK_VALID;
111 
112         if (!--lk->ref_count) {
113             if (lk->handler) {  /* weak extra protection */
114                 verify(lk->handler(lk->user_data, eMT_Lock));
115                 verify(lk->handler(lk->user_data, eMT_Unlock));
116             }
117 
118             if (lk->cleanup)
119                 lk->cleanup(lk->user_data);
120 
121             lk->magic_number++;
122             free(lk);
123             lk = 0;
124         }
125     }
126     return lk;
127 }
128 
129 
130 extern int/*bool*/ MT_LOCK_DoInternal(MT_LOCK lk, EMT_Lock how)
131 {
132     MT_LOCK_VALID;
133     if (lk->handler)
134         return lk->handler(lk->user_data, how);
135     return -1/* rightful non-doing */;
136 }
137 
138 
139 
140 /******************************************************************************
141  *  ERROR HANDLING and LOGGING
142  */
143 
144 /* Lock/unlock the logger */
145 #define LOG_LOCK_WRITE  verify(MT_LOCK_Do(lg->mt_lock, eMT_Lock))
146 #define LOG_LOCK_READ   verify(MT_LOCK_Do(lg->mt_lock, eMT_LockRead))
147 #define LOG_UNLOCK      verify(MT_LOCK_Do(lg->mt_lock, eMT_Unlock))
148 
149 
150 /* Check the validity of the logger */
151 #define LOG_VALID \
152     assert(lg->ref_count  &&  lg->magic_number == kLOG_magic_number)
153 
154 
155 /* Logger data and callbacks */
156 struct LOG_tag {
157     unsigned int ref_count;
158     void*        user_data;
159     FLOG_Handler handler;
160     FLOG_Cleanup cleanup;
161     MT_LOCK      mt_lock;
162     unsigned int magic_number;  /* used internally, to make sure it's init'd */
163 };
164 static const unsigned int kLOG_magic_number = 0x3FB97156;
165 
166 
167 extern const char* LOG_LevelStr(ELOG_Level level)
168 {
169     static const char* s_PostSeverityStr[eLOG_Fatal+1] = {
170         "TRACE",
171         "NOTE",
172         "WARNING",
173         "ERROR",
174         "CRITICAL",
175         "FATAL"
176     };
177     return s_PostSeverityStr[level];
178 }
179 
180 
181 extern LOG LOG_Create
182 (void*        user_data,
183  FLOG_Handler handler,
184  FLOG_Cleanup cleanup,
185  MT_LOCK      mt_lock)
186 {
187     LOG lg = (struct LOG_tag*) malloc(sizeof(struct LOG_tag));
188 
189     if (lg) {
190         lg->ref_count    = 1;
191         lg->user_data    = user_data;
192         lg->handler      = handler;
193         lg->cleanup      = cleanup;
194         lg->mt_lock      = mt_lock;
195         lg->magic_number = kLOG_magic_number;
196     }
197     return lg;
198 }
199 
200 
201 extern LOG LOG_Reset
202 (LOG          lg,
203  void*        user_data,
204  FLOG_Handler handler,
205  FLOG_Cleanup cleanup)
206 {
207     LOG_LOCK_WRITE;
208     LOG_VALID;
209 
210     if (lg->cleanup)
211         lg->cleanup(lg->user_data);
212 
213     lg->user_data = user_data;
214     lg->handler   = handler;
215     lg->cleanup   = cleanup;
216 
217     LOG_UNLOCK;
218     return lg;
219 }
220 
221 
222 extern LOG LOG_AddRef(LOG lg)
223 {
224     LOG_LOCK_WRITE;
225     LOG_VALID;
226 
227     lg->ref_count++;
228 
229     LOG_UNLOCK;
230     return lg;
231 }
232 
233 
234 extern LOG LOG_Delete(LOG lg)
235 {
236     if (lg) {
237         LOG_LOCK_WRITE;
238         LOG_VALID;
239 
240         if (lg->ref_count > 1) {
241             lg->ref_count--;
242             LOG_UNLOCK;
243             return lg;
244         }
245 
246         LOG_UNLOCK;
247 
248         LOG_Reset(lg, 0, 0, 0);
249         lg->ref_count--;
250         lg->magic_number++;
251 
252         if (lg->mt_lock)
253             MT_LOCK_Delete(lg->mt_lock);
254         free(lg);
255     }
256     return 0;
257 }
258 
259 
260 extern void LOG_WriteInternal
261 (LOG           lg,
262  SLOG_Handler* call_data
263  )
264 {
265     assert(!call_data->raw_size  ||  call_data->raw_data);
266 
267     if (lg) {
268         LOG_LOCK_READ;
269         LOG_VALID;
270 
271         if (lg->handler)
272             lg->handler(lg->user_data, call_data);
273 
274         LOG_UNLOCK;
275 
276         if (call_data->dynamic  &&  call_data->message)
277             free((void*) call_data->message);
278     }
279 
280     /* unconditional exit/abort on fatal error */
281     if (call_data->level == eLOG_Fatal) {
282 #if defined(NDEBUG)
283         exit(1);
284 #else
285         abort();
286 #endif
287     }
288 }
289 
290 
291 extern void LOG_Write
292 (LOG         lg,
293  int         code,
294  int         subcode,
295  ELOG_Level  level,
296  const char* module,
297  const char* file,
298  int         line,
299  const char* message,
300  const void* raw_data,
301  size_t      raw_size
302  )
303 {
304     SLOG_Handler call_data;
305 
306     call_data.dynamic     = 0;
307     call_data.message     = message;
308     call_data.level       = level;
309     call_data.module      = module;
310     call_data.file        = file;
311     call_data.line        = line;
312     call_data.raw_data    = raw_data;
313     call_data.raw_size    = raw_size;
314     call_data.err_code    = code;
315     call_data.err_subcode = subcode;
316 
317     LOG_WriteInternal(lg, &call_data);
318 }
319 
320 
321 
322 /******************************************************************************
323  *  REGISTRY
324  */
325 
326 /* Lock/unlock the registry  */
327 #define REG_LOCK_WRITE  verify(MT_LOCK_Do(rg->mt_lock, eMT_Lock))
328 #define REG_LOCK_READ   verify(MT_LOCK_Do(rg->mt_lock, eMT_LockRead))
329 #define REG_UNLOCK      verify(MT_LOCK_Do(rg->mt_lock, eMT_Unlock))
330 
331 
332 /* Check the validity of the registry */
333 #define REG_VALID \
334     assert(rg->ref_count  &&  rg->magic_number == kREG_magic_number)
335 
336 
337 /* Logger data and callbacks */
338 struct REG_tag {
339     unsigned int ref_count;
340     void*        user_data;
341     FREG_Get     get;
342     FREG_Set     set;
343     FREG_Cleanup cleanup;
344     MT_LOCK      mt_lock;
345     unsigned int magic_number;  /* used internally, to make sure it's init'd */
346 };
347 static const unsigned int kREG_magic_number = 0xA921BC08;
348 
349 
350 extern REG REG_Create
351 (void*        user_data,
352  FREG_Get     get,
353  FREG_Set     set,
354  FREG_Cleanup cleanup,
355  MT_LOCK      mt_lock)
356 {
357     REG rg = (struct REG_tag*) malloc(sizeof(struct REG_tag));
358 
359     if (rg) {
360         rg->ref_count    = 1;
361         rg->user_data    = user_data;
362         rg->get          = get;
363         rg->set          = set;
364         rg->cleanup      = cleanup;
365         rg->mt_lock      = mt_lock;
366         rg->magic_number = kREG_magic_number;
367     }
368     return rg;
369 }
370 
371 
372 extern void REG_Reset
373 (REG          rg,
374  void*        user_data,
375  FREG_Get     get,
376  FREG_Set     set,
377  FREG_Cleanup cleanup,
378  int/*bool*/  do_cleanup)
379 {
380     REG_LOCK_WRITE;
381     REG_VALID;
382 
383     if (do_cleanup  &&  rg->cleanup)
384         rg->cleanup(rg->user_data);
385 
386     rg->user_data = user_data;
387     rg->get       = get;
388     rg->set       = set;
389     rg->cleanup   = cleanup;
390 
391     REG_UNLOCK;
392 }
393 
394 
395 extern REG REG_AddRef(REG rg)
396 {
397     REG_LOCK_WRITE;
398     REG_VALID;
399 
400     rg->ref_count++;
401 
402     REG_UNLOCK;
403     return rg;
404 }
405 
406 
407 extern REG REG_Delete(REG rg)
408 {
409     if (rg) {
410         REG_LOCK_WRITE;
411         REG_VALID;
412 
413         if (rg->ref_count > 1) {
414             rg->ref_count--;
415             REG_UNLOCK;
416             return rg;
417         }
418 
419         REG_UNLOCK;
420 
421         REG_Reset(rg, 0, 0, 0, 0, 1/*true*/);
422         rg->ref_count--;
423         rg->magic_number++;
424 
425         if (rg->mt_lock)
426             MT_LOCK_Delete(rg->mt_lock);
427         free(rg);
428     }
429     return 0;
430 }
431 
432 
433 extern const char* REG_Get
434 (REG         rg,
435  const char* section,
436  const char* name,
437  char*       value,
438  size_t      value_size,
439  const char* def_value)
440 {
441     if (!value  ||  value_size <= 0)
442         return 0;
443 
444     if (def_value)
445         strncpy0(value, def_value, value_size - 1);
446     else
447         *value = '\0';
448 
449     if (rg) {
450         REG_LOCK_READ;
451         REG_VALID;
452 
453         if (rg->get)
454             rg->get(rg->user_data, section, name, value, value_size);
455 
456         REG_UNLOCK;
457     }
458 
459     return value;
460 }
461 
462 
463 extern int/*bool*/ REG_Set
464 (REG          rg,
465  const char*  section,
466  const char*  name,
467  const char*  value,
468  EREG_Storage storage)
469 {
470     int result;
471     if (rg) {
472         REG_LOCK_READ;
473         REG_VALID;
474 
475         result = (rg->set
476                   ? rg->set(rg->user_data, section, name, value, storage)
477                   : 0);
478 
479         REG_UNLOCK;
480     } else
481         result = 0;
482 
483     return result;
484 }
485 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.