|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/connect/ncbi_core.c |
source navigation diff markup identifier search freetext search file search |
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 |
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more information. |