1 #ifndef CONNECT___NCBI_CORE__H
2 #define CONNECT___NCBI_CORE__H
3 
4 /* $Id: ncbi_core.h 604951 2020-04-05 03:12:01Z lavr $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author:  Denis Vakatov
30  *
31  * File Description:
32  * @file ncbi_core.h
33  *   Types and code shared by all "ncbi_*.[ch]" modules.
34  *
35  * I/O status and direction:
36  *    enum:       EIO_ReadMethod
37  *    enum:       EIO_WriteMethod
38  *    enum:       EIO_Status,  verbal: IO_StatusStr()
39  *    enum:       EIO_Event
40  *
41  * Critical section (basic multi-thread synchronization):
42  *    handle:     MT_LOCK
43  *    enum:       EMT_Lock
44  *    callbacks:  (*FMT_LOCK_Handler)(),  (*FMT_LOCK_Cleanup)()
45  *    methods:    MT_LOCK_Create(),  MT_LOCK_AddRef(),  MT_LOCK_Delete(),
46  *                MT_LOCK_Do()
47  *
48  * Tracing and logging:
49  *    handle:     LOG
50  *    enum:       ELOG_Level,  verbal: LOG_LevelStr()
51  *    flags:      TLOG_FormatFlags, ELOG_FormatFlags
52  *    callbacks:  (*FLOG_Handler)(),  (*FLOG_Cleanup)()
53  *    methods:    LOG_Create(),  LOG_Reset(),  LOG_AddRef(),  LOG_Delete(),
54  *                LOG_Write(), LOG_WriteInternal()
55  *
56  * Registry:
57  *    handle:     REG
58  *    enum:       EREG_Storage
59  *    callbacks:  (*FREG_Get)(),  (*FREG_Set)(),  (*FREG_Cleanup)()
60  *    methods:    REG_Create(),  REG_Reset(),  REG_AddRef(),  REG_Delete(),
61  *                REG_Get(),  REG_Set()
62  *
63  */
64 
65 #include <connect/ncbi_types.h>
66 
67 
68 /** @addtogroup UtilityFunc
69  *
70  * @{
71  */
72 
73 
74 #ifdef __cplusplus
75 extern "C" {
76 #endif
77 
78 
79 /******************************************************************************
80  *  I/O
81  */
82 
83 
84 /** I/O read method.
85  * @sa
86  *  EIO_WriteMethod
87  */
88 typedef enum {
89     eIO_ReadPeek,       /**< do eIO_ReadPlain but leave data in input queue  */
90     eIO_ReadPlain,      /**< read readily available data only, wait if none  */
91     eIO_ReadPersist     /**< read exactly as much as requested, w/waits      */
92 } EIO_ReadMethod;
93 
94 
95 /** I/O write method.
96  * @sa
97  *  EIO_ReadMethod
98  */
99 typedef enum {
100     eIO_WriteNone,      /**< invalid reserved opcode, not for use!           */
101     eIO_WritePlain,     /**< write as much as possible, report back how much */
102     eIO_WritePersist,   /**< write exactly as much as specified, w/waits     */
103     eIO_WriteOutOfBand  /**< write out-of-band chunk of urgent data (if supp)*/
104 } EIO_WriteMethod;
105 
106 
107 /** I/O event (or direction).
108  * @note
109  *  Internally, these constants are used as bit-values, and therefore must not
110  *  be changed in this header.  On the other hand, user code should not rely
111  *  on the values of these constants, either.
112  * @warning
113  *  Careful with an unfortunate naming similarity of eIO_Close from this set
114  *  and eIO_Closed from EIO_Status -- do not mix the two!
115  * @sa
116  *  SOCK_Wait, SOCK_Poll, CONN_Wait, SOCK_SetTimeout, CONN_SetTimeout
117  */
118 typedef enum {
119     eIO_Open      = 0,  /**< also serves as no-event indicator in SOCK_Poll  */
120     eIO_Read      = 1,  /**< read                                            */
121     eIO_Write     = 2,  /**< write                                           */
122     eIO_ReadWrite = 3,  /**< eIO_Read | eIO_Write (also, eCONN_OnFlush)      */
123     eIO_Close     = 4   /**< also serves as an error indicator in SOCK_Poll  */
124 } EIO_Event;
125 
126 
127 /** I/O status.
128  * @warning
129  *  Careful with an unfortunate naming similarity of eIO_Closed from this set
130  *  and eIO_Close from EIO_Event -- do not mix the two!
131  */
132 typedef enum {
133     eIO_Success = 0,    /**< everything is fine, no error occurred           */
134     eIO_Timeout,        /**< timeout expired before any I/O succeeded        */
135     eIO_Reserved,       /**< reserved status code -- do not use!             */
136     eIO_Interrupt,      /**< signal arrival prevented any I/O to succeed     */
137     eIO_InvalidArg,     /**< bad argument / parameter value(s) supplied      */
138     eIO_NotSupported,   /**< operation is not supported or is not available  */
139     eIO_Unknown,        /**< unknown I/O error (likely fatal but can retry)  */
140     eIO_Closed          /**< connection is / has been closed, EOF condition  */
141 #define EIO_N_STATUS  8
142 } EIO_Status;
143 
144 
145 /** Get the text form of an enum status value.
146  * @param status
147  *  An enum value to get the text form for
148  * @return
149  *  Verbal description of the I/O status
150  * @warning
151  *  Returns NULL on out-of-bound values
152  * @note
153  *  Reserved status code(s) returned as an empty string ("")
154  * @sa
155  *  EIO_Status
156  */
157 extern NCBI_XCONNECT_EXPORT const char* IO_StatusStr(EIO_Status status);
158 
159 
160 
161 /******************************************************************************
162  *  MT locking
163  */
164 
165 
166 /** Lock handle -- keeps all data needed for the locking and for the cleanup.
167  * @sa
168  *   CORE_SetLOCK
169  */
170 struct MT_LOCK_tag;
171 typedef struct MT_LOCK_tag* MT_LOCK;
172 
173 
174 /** Set the lock/unlock callback function and its data for MT critical section.
175  * @note
176  *  If the RW-lock functionality is not provided by the callback, then:
177  *  eMT_LockRead <==> eMT_Lock
178  *
179  */
180 typedef enum {
181     eMT_Lock,        /**< lock   critical section                     */
182     eMT_LockRead,    /**< lock   critical section for reading         */
183     eMT_Unlock,      /**< unlock critical section                     */
184     eMT_TryLock,     /**< try to lock,             return immediately */
185     eMT_TryLockRead  /**< try to lock for reading, return immediately */
186 } EMT_Lock;
187 
188 
189 /** MT locking callback (operates like a [recursive] mutex or RW-lock).
190  * @param data
191  *  See "data" in MT_LOCK_Create()
192  * @param how
193  *  As passed to MT_LOCK_Do()
194  * @return
195  *  Non-zero value if the requested operation was successful.
196  * @note
197  *  The "-1" value is reserved for unset handler;  you also may want to return
198  *  "-1" if your locking function does no locking, and you don't consider it as
199  *  an error, but still want the caller to be aware of this "rightful
200  *  non-doing" as opposed to the "rightful doing".
201  * @sa
202  *   MT_LOCK_Create, MT_LOCK_Delete
203  */
204 typedef int/*bool*/ (*FMT_LOCK_Handler)
205 (void*    data,
206  EMT_Lock how
207  );
208 
209 /** MT lock cleanup callback.
210  * @param data
211  *  See "data" in MT_LOCK_Create()
212  * @sa
213  *  MT_LOCK_Create, MT_LOCK_Delete
214  */
215 typedef void (*FMT_LOCK_Cleanup)
216 (void* data
217  );
218 
219 
220 /** Create a new MT lock (with an internal reference count set to 1).
221  * @param data
222  *  Unspecified data to call "handler" and "cleanup" with
223  * @param handler
224  *  Locking callback
225  * @param cleanup
226  *  Cleanup callback
227  * @sa
228  *  FMT_LOCK_Handler, FMT_LOCK_Cleanup, MT_LOCK_Delete
229  */
230 extern NCBI_XCONNECT_EXPORT MT_LOCK MT_LOCK_Create
231 (void*            data,
232  FMT_LOCK_Handler handler,
233  FMT_LOCK_Cleanup cleanup
234  );
235 
236 
237 /** Increment internal reference count by 1, then return "lk".
238  * @param lk
239  *  A handle previously obtained from MT_LOCK_Create
240  * @sa
241  *  MT_LOCK_Create, MT_LOCK_Delete
242  */
243 extern NCBI_XCONNECT_EXPORT MT_LOCK MT_LOCK_AddRef(MT_LOCK lk);
244 
245 
246 /** Decrement internal reference count by 1, and if it reaches 0, then
247  * destroy the handle, call "lk->cleanup(lk->data)", and return NULL;
248  * otherwise (if the reference count is still > 0), return "lk".
249  * @param lk
250  *  A handle previously obtained from MT_LOCK_Create
251  * @sa
252  *  MT_LOCK_Create, FMT_LOCK_Cleanup
253  */
254 extern NCBI_XCONNECT_EXPORT MT_LOCK MT_LOCK_Delete(MT_LOCK lk);
255 
256 
257 /** Call "lk->handler(lk->data, how)".
258  * @param lk
259  *  A handle previously obtained from MT_LOCK_Create
260  * @param how
261  *  Whether to lock (and how: read, write) or to unlock
262  * @return
263  *  Value returned by the lock handler ("handler" in MT_LOCK_Create()).
264  * If lock handler is not specified then always return "-1".
265  * @note
266  *  Use MT_LOCK_Do to avoid overhead!
267  * @sa
268  *  MT_LOCK_Create, FMT_LOCK_Handler, EMT_Lock
269  */
270 #define MT_LOCK_Do(lk, how)  ((lk) ? MT_LOCK_DoInternal((lk), (how)) : -1)
271 extern NCBI_XCONNECT_EXPORT int/*bool*/ MT_LOCK_DoInternal
272 (MT_LOCK  lk,
273  EMT_Lock how
274  );
275 
276 
277 /******************************************************************************
278  *  Error handling and logging
279  */
280 
281 
282 /** Log handle -- keeps all data needed for the logging and for the cleanup.
283  * @sa
284  *   CORE_SetLOG
285  */
286 struct LOG_tag;
287 typedef struct LOG_tag* LOG;
288 
289 
290 /** Log severity level.
291  */
292 typedef enum {
293     eLOG_Trace = 0,
294     eLOG_Note,
295     eLOG_Info = eLOG_Note,  /**< In C++ Toolkit "Info" is used, not "Note" */
296     eLOG_Warning,
297     eLOG_Error,
298     eLOG_Critical,
299     eLOG_Fatal
300 } ELOG_Level;
301 
302 
303 /** Obtain verbal representation of an enum level value.
304  * @param level
305  *  An enum value to get the text form for
306  * @return
307  *  Verbal description of the log level
308  * @sa
309  *  ELOG_Level
310  */
311 extern NCBI_XCONNECT_EXPORT const char* LOG_LevelStr(ELOG_Level level);
312 
313 
314 /** Message and miscellaneous data to pass to log post callback FLOG_Handler.
315  * @param dynamic
316  *  if non-zero then LOG_WriteInternal() will call free(message) before return
317  * @param message
318  *  A message to post, can be NULL
319  * @param level
320  *  A message level
321  * @param module
322  *  A module string to post, can be NULL
323  * @param file
324  *  A file name to post, can be NULL
325  * @param line
326  *  A line number within the file (above) to post, can be 0
327  * @param raw_data
328  *  Raw data to log (usually NULL)
329  * @param raw_size
330  *  Size of the raw data (usually zero)
331  * @param err_code
332  *  Error code of the message
333  * @param err_subcode
334  *  Error subcode of the message
335  * @sa
336  *  FLOG_Handler, LOG_Create, LOG_WriteInternal, LOG_Write
337  */
338 typedef struct {
339     int/*bool*/ dynamic;
340     const char* message;
341     ELOG_Level  level;
342     const char* module;
343     const char* func;
344     const char* file;
345     int         line;
346     const void* raw_data;
347     size_t      raw_size;
348     int         err_code;
349     int         err_subcode;
350 } SLOG_Message;
351 
352 
353 /** Log post callback.
354  * @param data
355  *  Unspeficied data as passed to LOG_Create() or LOG_Reset()
356  * @param mess
357  *  Composed from arguments passed to LOG_WriteInternal()
358  * @sa
359  *  SLOG_Message, LOG_Create, LOG_Reset, LOG_WriteInternal
360  */
361 typedef void (*FLOG_Handler)
362 (void*               data,
363  const SLOG_Message* mess
364  );
365 
366 
367 /** Log cleanup callback.
368  * @param data
369  *   Unspeficied data as passed to LOG_Create() or LOG_Reset()
370  * @sa
371  *  LOG_Create, LOG_Reset
372  *
373  */
374 typedef void (*FLOG_Cleanup)
375 (void* data
376  );
377 
378 
379 /** Create a new LOG (with an internal reference count set to 1).
380  * @warning
381  *  If non-NULL "lock" is specified then MT_LOCK_AddRef() is called on it here,
382  *  and MT_LOCK_Delete() will be called on it when this LOG gets deleted.
383  * @param data
384  *  Unspecified data to call "handler" and "cleanup" with
385  * @param handler
386  *  Log post callback
387  * @param cleanup
388  *  Cleanup callback
389  * @param lock
390  *  Protective MT lock (may be NULL)
391  * @sa
392  *  MT_LOCK, MT_LOCK_AddRef, FLOG_Handler, FLOG_Cleanup, LOG_Reset, LOG_Delete
393  */
394 extern NCBI_XCONNECT_EXPORT LOG LOG_Create
395 (void*        data,
396  FLOG_Handler handler,
397  FLOG_Cleanup cleanup,
398  MT_LOCK      lock
399  );
400 
401 
402 /** Reset the "lg" to use the new "data", "handler" and "cleanup".
403  * @note
404  *  It does not change the reference count of the log.
405  * @param lg
406  *  A log handle previously obtained from LOG_Create
407  * @param data
408  *  New user data
409  * @param handler
410  *  New log post callback
411  * @param cleanup
412  *  New cleanup callback
413  * @return
414  *  lg (as passed in the first parameter)
415  * @sa
416  *  LOG_Create
417  */
418 extern NCBI_XCONNECT_EXPORT LOG LOG_Reset
419 (LOG          lg,
420  void*        data,
421  FLOG_Handler handler,
422  FLOG_Cleanup cleanup
423  );
424 
425 
426 /** Increment internal reference count by 1, then return "lg".
427  * @param lg
428  *  A log handle previously obtained from LOG_Create
429  * @sa
430  *  LOG_Create
431  */
432 extern NCBI_XCONNECT_EXPORT LOG LOG_AddRef(LOG lg);
433 
434 
435 /** Decrement internal reference count by 1, and if it reaches 0, then
436  * call "lg->cleanup(lg->data)", destroy the handle, and return NULL;
437  * otherwise (if reference count is still > 0), return "lg".
438  * @param lg
439  *  A log handle previously obtained from LOG_Create
440  * @sa
441  *  LOG_Create
442  */
443 extern NCBI_XCONNECT_EXPORT LOG LOG_Delete(LOG lg);
444 
445 
446 /** Upon having filled SLOG_Message data from parameters, write a message
447  * (perhaps with raw data attached) to the log by calling LOG_WriteInternal().
448  * @note
449  *  Do not call this function directly, if possible.  Instead, use the
450  *  LOG_WRITE() and LOG_DATA() macros from <connect/ncbi_util.h>!
451  * @param code
452  *  Error code of the message
453  * @param subcode
454  *  Error subcode of the message
455  * @param level
456  *  The message severity
457  * @param module
458  *  Module name (can be NULL)
459  * @param func
460  *  Function name (can be NULL)
461  * @param file
462  *  Source file name (can be NULL)
463  * @param line
464  *  Source line within the file (can be 0 to omit the line number)
465  * @param message
466  *  Message content
467  * @param raw_data
468  *  Raw data to log (can be NULL)
469  * @param raw_size
470  *  Size of the raw data (can be zero)
471  * @sa
472  *  LOG_Create, ELOG_Level, FLOG_Handler, LOG_WriteInternal
473  */
474 extern NCBI_XCONNECT_EXPORT void LOG_Write
475 (LOG         lg,
476  int         code,
477  int         subcode,
478  ELOG_Level  level,
479  const char* module,
480  const char* func,
481  const char* file,
482  int         line,
483  const char* message,
484  const void* raw_data,
485  size_t      raw_size
486 );
487 
488 
489 /** Write message (perhaps with raw data attached) to the log by calling
490  * "lg->handler(lg->data, mess)".
491  * @note
492  *  Do not call this function directly, if possible.  Instead, use the
493  *  LOG_WRITE() and LOG_DATA() macros from <ncbi_util.h>!
494  * @warning
495  *  This call free()s "mess->message" when "mess->dynamic" is set non-zero!
496  * @param lg
497  *  A log handle previously obtained from LOG_Create
498  * @sa
499  *  LOG_Create, ELOG_Level, FLOG_Handler, LOG_Write
500  */
501 extern NCBI_XCONNECT_EXPORT void LOG_WriteInternal
502 (LOG                 lg,
503  const SLOG_Message* mess
504  );
505 
506 
507 /******************************************************************************
508  *  Registry
509  */
510 
511 
512 /** Registry handle (keeps all data needed for the registry get/set/cleanup).
513  * @sa
514  *   CORE_SetReg
515  */
516 struct REG_tag;
517 typedef struct REG_tag* REG;
518 
519 
520 /** Transient/Persistent storage.
521  * @sa
522  *  REG_Get, REG_Set
523  */
524 typedef enum {
525     eREG_Transient = 0,  /**< only in-memory storage while program runs */
526     eREG_Persistent      /**< hard-copy storage across program runs     */
527 } EREG_Storage;
528 
529 
530 /** Registry getter callback.
531  * Copy registry value stored in "section" under name "name" to buffer "value".
532  * Look for the matching entry first in the transient storage, and then in
533  * the persistent storage.  Do not modify the "value" (leave it "as is",
534  * i.e. default) if the requested entry is not found in the registry.
535  * @note
536  *  Always terminate value with '\0'.
537  * @note
538  *  Do not put more than "value_size" bytes to "value".
539  * @param data
540  *  Unspecified data as passed to REG_Create or REG_Reset
541  * @param section
542  *  Section name to search
543  * @param name
544  *  Key name to search within the section
545  * @param value
546  *  Default value passed in (cut to "value_size") symbols, found value out
547  * @param value_size
548  *  Size of "value" storage, must be greater than 0
549  * @return
550  *  1 if successfully found and stored;  -1 if not found (the default is to be
551  *  used);  0 if an error (including truncation) occurred
552  * @sa
553  *  REG_Create, REG_Reset
554  */
555 typedef int (*FREG_Get)
556 (void*       data,
557  const char* section,
558  const char* name,
559  char*       value,
560  size_t      value_size
561  );
562 
563 
564 /** Registry setter callback.
565  * Store the "value" to  the registry section "section" under name "name",
566  * and according to "storage".
567  * @param data
568  *  Unspecified data as passed to REG_Create or REG_Reset
569  * @param section
570  *  Section name to add the key to
571  * @param name
572  *  Key name to add to the section
573  * @param value
574  *  Key value to associate with the key (NULL to deassociate, i.e. unset)
575  * @param storage
576  *  How to store the new setting, temporarily or permanently
577  * @return
578  *  Non-zero if successful (including replacing a value with itself)
579  * @sa
580  *  REG_Create, REG_Reset, EREG_Storage
581  */
582 typedef int/*bool*/ (*FREG_Set)
583 (void*        data,
584  const char*  section,
585  const char*  name,
586  const char*  value,
587  EREG_Storage storage
588  );
589 
590 
591 /** Registry cleanup callback.
592  * @param data
593  *  Unspecified data as passed to REG_Create or REG_Reset
594  * @sa
595  *  REG_Reset, REG_Delete
596  */
597 typedef void (*FREG_Cleanup)
598 (void* data
599  );
600 
601 
602 /** Create a new registry (with an internal reference count set to 1).
603  * @warning
604  *  if non-NULL "lock" is specified then MT_LOCK_AddRef() is called on it here,
605  *  and MT_LOCK_Delete() will be called on it when this REG gets destroyed.
606  *  Passing NULL callbacks below causes limiting the functionality
607  *  only to those operations that have the callbacks set for.
608  * @param data
609  *  Unspecified data to call "set", "get" and "cleanup" with
610  * @param get
611  *  Getter callback
612  * @param set
613  *  Setter callback
614  * @param cleanup
615  *  Cleanup callback
616  * @param lock
617  *  Protective MT lock (may be NULL)
618  * @sa
619  *  MT_LOCK, MT_LOCK_AddRef, REG_Get, REG_Set, REG_Reset, REG_Delete
620  */
621 extern NCBI_XCONNECT_EXPORT REG REG_Create
622 (void*        data,
623  FREG_Get     get,
624  FREG_Set     set,
625  FREG_Cleanup cleanup,
626  MT_LOCK      lock
627  );
628 
629 
630 /** Reset the registry handle to use the new "data", "set", "get",
631  * and "cleanup".
632  * @note
633  *  No change to the internal reference count.
634  * @param rg
635  *  Registry handle as previously obtained from REG_Create
636  * @param data
637  *  New user data
638  * @param get
639  *  New getter callback
640  * @param set
641  *  New setter callback
642  * @param cleanup
643  *  New cleanup callback
644  * @param do_cleanup
645  *  Whether to call old cleanup (if any specified) for old data
646  * @sa
647  *  REG_Create, REG_Delete
648  */
649 extern NCBI_XCONNECT_EXPORT void REG_Reset
650 (REG          rg,
651  void*        data,
652  FREG_Get     get,
653  FREG_Set     set,
654  FREG_Cleanup cleanup,
655  int/*bool*/  do_cleanup
656  );
657 
658 
659 /** Increment internal reference count by 1, then return "rg".
660  * @param rg
661  *  Registry handle as previously obtained from REG_Create
662  * @sa
663  *  REG_Create
664  */
665 extern NCBI_XCONNECT_EXPORT REG REG_AddRef(REG rg);
666 
667 
668 /** Decrement internal reference count by 1, and if it reaches 0, then
669  * call "rg->cleanup(rg->data)", destroy the handle, and return NULL;
670  * otherwise (if the reference count is still > 0), return "rg".
671  * @param rg
672  *  Registry handle as previously obtained from REG_Create
673  * @sa
674  *  REG_Create
675  */
676 extern NCBI_XCONNECT_EXPORT REG REG_Delete(REG rg);
677 
678 
679 /** Copy the registry value stored in "section" under name "name" to buffer
680  * "value";  if the entry is found in both transient and persistent storages,
681  * then copy the one from the transient storage.
682  * If the specified entry is not found in the registry (or if there is no
683  * registry defined), and "def_value" is not NULL, then copy "def_value" to
684  * "value" (although, only up to "value_size" characters).
685  * @param rg
686  *  Registry handle as previously obtained from REG_Create
687  * @param section
688  *  Registry section name
689  * @param name
690  *  Registry entry name
691  * @param value
692  *  Buffer to receive the value of the requested entry, must be non-NULL
693  * @param value_size
694  *  Maximal size of buffer "value", must be greater than 0
695  * @param def_value
696  *  Default value (none if passed NULL or "")
697  * @return
698  *  Return "value" if the found value, including the default, and with its '\0'
699  *  terminator, fits entirely within "value_size";  return NULL if there was an
700  *  error retrieving the value, or if it had to be truncated (but regardless,
701  *  "value" must always be kept '\0'-terminated unless "value_size" was zero).
702  * @sa
703  *  REG_Create, REG_Set
704  */
705 extern NCBI_XCONNECT_EXPORT const char* REG_Get
706 (REG         rg,
707  const char* section,
708  const char* name,
709  char*       value,
710  size_t      value_size,
711  const char* def_value
712  );
713 
714 
715 /** Store the "value" into the registry section "section" under the key "name",
716  * and according to "storage".
717  * @param rg
718  *  Registry handle as previously obtained from REG_Create
719  * @param section
720  *  Section name to store the value into
721  * @param name
722  *  Name to store the value under
723  * @param value
724  *  The value to store (NULL to unset the parameter)
725  * @param storage
726  *  Whether to store temporarily or permanently
727  * @return
728  *  Non-zero if successful (including replacing a value with itself)
729  * @sa
730  *  REG_Create, EREG_Storage, REG_Get
731  */
732 extern NCBI_XCONNECT_EXPORT int REG_Set
733 (REG          rg,
734  const char*  section,
735  const char*  name,
736  const char*  value,
737  EREG_Storage storage
738  );
739 
740 
741 #ifdef __cplusplus
742 }  /* extern "C" */
743 #endif
744 
745 
746 /* @} */
747 
748 #endif /* CONNECT___NCBI_CORE__H */
749