1 #ifndef CONNECT___NCBI_PRIV__H 2 #define CONNECT___NCBI_PRIV__H 3 4 /* $Id: ncbi_priv.h,v 6.104 2016/11/18 17:34:14 fukanchi Exp $ 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 * Authors: Denis Vakatov, Anton Lavrentiev, Pavel Ivanov 30 * 31 * File Description: 32 * Private aux. code for the "ncbi_*.[ch]" 33 * 34 ********************************* 35 * Tracing and logging 36 * C error codes: NCBI_C_DEFINE_ERRCODE_X, NCBI_C_ERRCODE_X 37 * private global: g_CORE_Log 38 * macros: CORE_TRACE[F], CORE_LOG[F][_[EX]X], 39 * CORE_LOG[F]_ERRNO[_[EX]X](), CORE_DATA[F][_[EX]X] 40 * Critical section (basic multi-thread synchronization) 41 * private global: g_CORE_MT_Lock 42 * macros: CORE_LOCK_WRITE, CORE_LOCK_READ, CORE_UNLOCK 43 * Registry: 44 * private global: g_CORE_Registry 45 * macros: CORE_REG_GET, CORE_REG_SET 46 * Setup accounting: ECORE_Set 47 * private global: g_CORE_Set 48 * Random generator seeding support 49 * private global: g_NCBI_ConnectRandomSeed 50 * macro: NCBI_CONNECT_SRAND_ADDEND 51 * App name / NCBI ID / DTab support 52 * private globals: g_CORE_GetAppName 53 * g_CORE_GetRequestID 54 * g_CORE_GetRequestDtab 55 * 56 */ 57 58 59 //#define NCBI_MONKEY 60 61 #include "ncbi_assert.h" 62 #include <connect/ncbi_util.h> 63 #ifdef NCBI_MONKEY 64 # if defined(NCBI_OS_MSWIN) 65 # include <WinSock2.h> 66 # else 67 # include <sys/socket.h> 68 # define SOCKET int 69 # endif /*NCBI_OS_MSWIN*/ 70 #endif /* NCBI_MONKEY */ 71 72 73 #ifdef __cplusplus 74 extern "C" { 75 #endif 76 77 78 /****************************************************************************** 79 * Error handling and logging 80 * 81 * Several macros brought here from ncbidiag.hpp. The names slightly 82 * changed (added _C) because some sources can include this header and 83 * ncbidiag.hpp simultaneously. 84 */ 85 86 /** Define global error code name with given value (err_code) */ 87 #define NCBI_C_DEFINE_ERRCODE_X(name, err_code, max_err_subcode) \ 88 enum enum##name { \ 89 eErrCodeX_##name = err_code \ 90 /* automatic subcode checking is not implemented in C code */ \ 91 } 92 93 /* Here are only error codes used in C sources. For error codes used in 94 * C++ sources (in C++ Toolkit) see include/connect/error_codes.hpp. 95 */ 96 NCBI_C_DEFINE_ERRCODE_X(Connect_Conn, 301, 36); 97 NCBI_C_DEFINE_ERRCODE_X(Connect_Socket, 302, 163); 98 NCBI_C_DEFINE_ERRCODE_X(Connect_Util, 303, 9); 99 NCBI_C_DEFINE_ERRCODE_X(Connect_LBSM, 304, 33); 100 NCBI_C_DEFINE_ERRCODE_X(Connect_FTP, 305, 13); 101 NCBI_C_DEFINE_ERRCODE_X(Connect_SMTP, 306, 33); 102 NCBI_C_DEFINE_ERRCODE_X(Connect_HTTP, 307, 23); 103 NCBI_C_DEFINE_ERRCODE_X(Connect_Service, 308, 9); 104 NCBI_C_DEFINE_ERRCODE_X(Connect_HeapMgr, 309, 33); 105 /* 310 unused */ 106 NCBI_C_DEFINE_ERRCODE_X(Connect_Mghbn, 311, 16); 107 NCBI_C_DEFINE_ERRCODE_X(Connect_Crypt, 312, 5); 108 NCBI_C_DEFINE_ERRCODE_X(Connect_LocalNet, 313, 4); 109 110 /** Make one identifier from 2 parts */ 111 #define NCBI_C_CONCAT_IDENTIFIER(prefix, postfix) prefix##postfix 112 113 /** Return value of error code by its name defined by NCBI_DEFINE_ERRCODE_X 114 * 115 * @sa NCBI_C_DEFINE_ERRCODE_X 116 */ 117 #define NCBI_C_ERRCODE_X_NAME(name) \ 118 NCBI_C_CONCAT_IDENTIFIER(eErrCodeX_, name) 119 120 /** Return currently set default error code. Default error code is set by 121 * definition of NCBI_USE_ERRCODE_X with name of error code as its value. 122 * 123 * @sa NCBI_DEFINE_ERRCODE_X 124 */ 125 #define NCBI_C_ERRCODE_X \ 126 NCBI_C_ERRCODE_X_NAME(NCBI_USE_ERRCODE_X) 127 128 129 extern NCBI_XCONNECT_EXPORT LOG g_CORE_Log; 130 131 /* Always use the following macros and functions to access "g_CORE_Log", 132 * do not access/change it directly! 133 */ 134 135 #ifdef _DEBUG 136 # define CORE_TRACE(message) CORE_LOG(eLOG_Trace, message) 137 # define CORE_TRACEF(fmt_args) CORE_LOGF(eLOG_Trace, fmt_args) 138 # define CORE_DEBUG_ARG(arg) arg 139 #else 140 # define CORE_TRACE(message) ((void) 0) 141 # define CORE_TRACEF(fmt_args) ((void) 0) 142 # define CORE_DEBUG_ARG(arg) /*arg*/ 143 #endif /*_DEBUG*/ 144 145 #define CORE_LOG_X(subcode, level, message) \ 146 DO_CORE_LOG(NCBI_C_ERRCODE_X, subcode, level, \ 147 message, 0) 148 149 #define CORE_LOGF_X(subcode, level, fmt_args) \ 150 DO_CORE_LOG(NCBI_C_ERRCODE_X, subcode, level, \ 151 g_CORE_Sprintf fmt_args, 1) 152 153 #define CORE_LOG(level, message) \ 154 DO_CORE_LOG(0, 0, level, \ 155 message, 0) 156 157 #define CORE_LOGF(level, fmt_args) \ 158 DO_CORE_LOG(0, 0, level, \ 159 g_CORE_Sprintf fmt_args, 1) 160 161 #define CORE_LOG_ERRNO_X(subcode, level, error, message) \ 162 DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, 0, \ 163 message, 0) 164 165 #define CORE_LOGF_ERRNO_X(subcode, level, error, fmt_args) \ 166 DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, 0, \ 167 g_CORE_Sprintf fmt_args, 1) 168 169 #define CORE_LOG_ERRNO(level, error, message) \ 170 DO_CORE_LOG_ERRNO(0, 0, level, error, 0, \ 171 message, 0) 172 173 #define CORE_LOGF_ERRNO(level, error, fmt_args) \ 174 DO_CORE_LOG_ERRNO(0, 0, level, error, 0, \ 175 g_CORE_Sprintf fmt_args, 1) 176 177 #define CORE_LOG_ERRNO_EXX(subcode, level, error, descr, message) \ 178 DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, descr, \ 179 message, 0) 180 181 #define CORE_LOGF_ERRNO_EXX(subcode, level, error, descr, fmt_args) \ 182 DO_CORE_LOG_ERRNO(NCBI_C_ERRCODE_X, subcode, level, error, descr, \ 183 g_CORE_Sprintf fmt_args, 1) 184 185 #define CORE_LOG_ERRNO_EX(level, error, descr, message) \ 186 DO_CORE_LOG_ERRNO(0, 0, level, error, descr, \ 187 message, 0) 188 189 #define CORE_LOGF_ERRNO_EX(level, error, descr, fmt_args) \ 190 DO_CORE_LOG_ERRNO(0, 0, level, error, descr, \ 191 g_CORE_Sprintf fmt_args, 1) 192 193 #define CORE_DATA_X(subcode, level, data, size, message) \ 194 DO_CORE_LOG_DATA(NCBI_C_ERRCODE_X, subcode, level, data, size, \ 195 message, 0) 196 197 #define CORE_DATAF_X(subcode, level, data, size, fmt_args) \ 198 DO_CORE_LOG_DATA(NCBI_C_ERRCODE_X, subcode, level, data, size, \ 199 g_CORE_Sprintf fmt_args, 1) 200 201 #define CORE_DATA(level, data, size, message) \ 202 DO_CORE_LOG_DATA(0, 0, level, data, size, \ 203 message, 0) 204 205 #define CORE_DATAF(level, data, size, fmt_args) \ 206 DO_CORE_LOG_DATA(0, 0, level, data, size, \ 207 g_CORE_Sprintf fmt_args, 1) 208 209 /* helpers follow */ 210 #define DO_CORE_LOG_X(_code, _subcode, _level, _message, _dynamic, \ 211 _error, _descr, _raw_data, _raw_size) \ 212 do { \ 213 ELOG_Level _xx_level = (_level); \ 214 if (g_CORE_Log || _xx_level == eLOG_Fatal) { \ 215 SLOG_Handler _mess; \ 216 _mess.dynamic = _dynamic; \ 217 _mess.message = NcbiMessagePlusError(&_mess.dynamic, \ 218 (_message), \ 219 (_error), \ 220 (_descr)); \ 221 _mess.level = _xx_level; \ 222 _mess.module = THIS_MODULE; \ 223 _mess.func = CORE_CURRENT_FUNCTION; \ 224 _mess.file = __FILE__; \ 225 _mess.line = __LINE__; \ 226 _mess.raw_data = (_raw_data); \ 227 _mess.raw_size = (_raw_size); \ 228 _mess.err_code = (_code); \ 229 _mess.err_subcode = (_subcode); \ 230 CORE_LOCK_READ; \ 231 LOG_WriteInternal(g_CORE_Log, &_mess); \ 232 CORE_UNLOCK; \ 233 } \ 234 } while (0) 235 236 #define DO_CORE_LOG(code, subcode, level, \ 237 message, dynamic) \ 238 DO_CORE_LOG_X(code, subcode, level, message, dynamic, 0, 0, 0, 0) 239 240 #define DO_CORE_LOG_ERRNO(code, subcode, level, error, descr, \ 241 message, dynamic) \ 242 DO_CORE_LOG_X(code, subcode, level, message, dynamic, error, descr, 0, 0) 243 244 #define DO_CORE_LOG_DATA(code, subcode, level, data, size, \ 245 message, dynamic) \ 246 DO_CORE_LOG_X(code, subcode, level, message, dynamic, 0, 0, data, size) 247 248 extern NCBI_XCONNECT_EXPORT const char* g_CORE_Sprintf(const char* fmt, ...) 249 #ifdef __GNUC__ 250 __attribute__((format(printf,1,2))) 251 #endif 252 ; 253 254 255 /****************************************************************************** 256 * Multi-Thread SAFETY 257 */ 258 259 extern struct MT_LOCK_tag g_CORE_MT_Lock_default; 260 261 extern NCBI_XCONNECT_EXPORT MT_LOCK g_CORE_MT_Lock; 262 263 264 /* Always use the following macros and functions to access "g_CORE_MT_Lock", 265 * do not access/change it directly! 266 */ 267 268 #define CORE_LOCK_WRITE verify(CORE_CHECK_LOCK && \ 269 MT_LOCK_Do(g_CORE_MT_Lock, eMT_Lock )) 270 #define CORE_LOCK_READ verify(CORE_CHECK_LOCK && \ 271 MT_LOCK_Do(g_CORE_MT_Lock, eMT_LockRead)) 272 #define CORE_UNLOCK verify(CORE_CHECK_UNLOCK && \ 273 MT_LOCK_Do(g_CORE_MT_Lock, eMT_Unlock )) 274 275 #ifdef _DEBUG 276 extern NCBI_XCONNECT_EXPORT int g_NCBI_CoreCheckLock (void); 277 extern NCBI_XCONNECT_EXPORT int g_NCBI_CoreCheckUnlock(void); 278 # define CORE_CHECK_LOCK g_NCBI_CoreCheckLock() 279 # define CORE_CHECK_UNLOCK g_NCBI_CoreCheckUnlock() 280 #else 281 # define CORE_CHECK_LOCK (1/*TRUE*/) 282 # define CORE_CHECK_UNLOCK (1/*TRUE*/) 283 #endif /*_DEBUG*/ 284 285 286 /****************************************************************************** 287 * Registry 288 */ 289 290 extern NCBI_XCONNECT_EXPORT REG g_CORE_Registry; 291 292 /* Always use the following macros and functions to access "g_CORE_Registry", 293 * do not access/change it directly! 294 */ 295 296 #define CORE_REG_GET(section, name, value, value_size, def_value) \ 297 g_CORE_RegistryGET(section, name, value, value_size, def_value) 298 299 #define CORE_REG_SET(section, name, value, storage) \ 300 g_CORE_RegistrySET(section, name, value, storage) 301 302 303 /* (private, to be used exclusively by the above macro CORE_REG_GET) */ 304 extern NCBI_XCONNECT_EXPORT const char* g_CORE_RegistryGET 305 (const char* section, 306 const char* name, 307 char* value, 308 size_t value_size, 309 const char* def_value 310 ); 311 312 /* (private, to be used exclusively by the above macro CORE_REG_SET) */ 313 extern NCBI_XCONNECT_EXPORT int/*bool*/ g_CORE_RegistrySET 314 (const char* section, 315 const char* name, 316 const char* value, 317 EREG_Storage storage 318 ); 319 320 321 /****************************************************************************** 322 * Setup accounting 323 */ 324 325 typedef enum { 326 eCORE_SetSSL = 1, 327 eCORE_SetREG = 4, 328 eCORE_SetLOG = 2, 329 eCORE_SetLOCK = 8 330 } ECORE_Set; 331 typedef unsigned int TCORE_Set; 332 333 334 extern TCORE_Set g_CORE_Set; 335 336 337 /****************************************************************************** 338 * Random generator seeding support 339 */ 340 341 extern NCBI_XCONNECT_EXPORT int g_NCBI_ConnectRandomSeed; 342 extern NCBI_XCONNECT_EXPORT int g_NCBI_ConnectSrandAddend(void); 343 #define NCBI_CONNECT_SRAND_ADDEND g_NCBI_ConnectSrandAddend() 344 345 346 /****************************************************************************** 347 * App name support (may return NULL; gets converted to "" at the user level) 348 */ 349 350 typedef const char* (*FNcbiGetAppName)(void); 351 extern NCBI_XCONNECT_EXPORT FNcbiGetAppName g_CORE_GetAppName; 352 353 354 /****************************************************************************** 355 * NCBI request ID support (return "as is" to the user) 356 * Return NULL on error; otherwise, the returned ID is a non-empty string 357 * allocated on the heap, and must be free()'d when no longer needed. 358 */ 359 360 typedef char* (*FNcbiGetRequestID)(ENcbiRequestID); 361 extern NCBI_XCONNECT_EXPORT FNcbiGetRequestID g_CORE_GetRequestID; 362 363 364 /****************************************************************************** 365 * DTab-Local support (returned NULL gets converted to "" at the user level) 366 */ 367 typedef const char* (*FNcbiGetRequestDtab)(void); 368 extern NCBI_XCONNECT_EXPORT FNcbiGetRequestDtab g_CORE_GetRequestDtab; 369 370 371 /****************************************************************************** 372 * Miscellanea 373 */ 374 375 #ifdef __GNUC__ 376 # define likely(x) __builtin_expect(!!(x),1) 377 # define unlikely(x) __builtin_expect(!!(x),0) 378 #else 379 # define likely(x) (x) 380 # define unlikely(x) (x) 381 #endif /*__GNUC__*/ 382 383 384 /****************************************************************************** 385 * NCBI Crazy Monkey support 386 */ 387 388 #ifdef NCBI_MONKEY 389 /* UNIX and Windows have different prototypes for send(), recv(), etc., so 390 * some types have to be pre-selected based on current OS 391 */ 392 # ifdef NCBI_OS_MSWIN 393 # define MONKEY_RETTYPE int 394 # define MONKEY_SOCKTYPE SOCKET 395 # define MONKEY_DATATYPE char* 396 # define MONKEY_LENTYPE int 397 # define MONKEY_SOCKLENTYPE int 398 # define MONKEY_STDCALL __stdcall /* in Windows, socket functions have 399 prototypes with __stdcall */ 400 # else 401 # define MONKEY_RETTYPE ssize_t 402 # define MONKEY_SOCKTYPE int 403 # define MONKEY_DATATYPE void* 404 # define MONKEY_LENTYPE size_t 405 # define MONKEY_SOCKLENTYPE socklen_t 406 # define MONKEY_STDCALL /* empty*/ 407 # endif /* NCBI_OS_MSWIN */ 408 409 /****************************************************************************** 410 * Socket functions via Crazy Monkey 411 */ 412 typedef MONKEY_RETTYPE 413 (MONKEY_STDCALL *FMonkeyRecv) (MONKEY_SOCKTYPE sock, 414 MONKEY_DATATYPE buf, 415 MONKEY_LENTYPE size, 416 int flags, 417 void* /* SOCK* */ sock_ptr); 418 typedef MONKEY_RETTYPE 419 (MONKEY_STDCALL *FMonkeySend) (MONKEY_SOCKTYPE sock, 420 const MONKEY_DATATYPE data, 421 MONKEY_LENTYPE size, 422 int flags, 423 void* /* SOCK* */ sock_ptr); 424 typedef int(MONKEY_STDCALL *FMonkeyConnect)(MONKEY_SOCKTYPE sock, 425 const struct sockaddr* name, 426 MONKEY_SOCKLENTYPE namelen); 427 428 typedef int /* bool */ (*FMonkeyPoll) (size_t* n, 429 void* /*SSOCK_Poll[]* */polls, 430 EIO_Status* ret_status); 431 typedef void (*FMonkeyClose) (SOCKET sock); 432 typedef void (*FSockHasSocket)(void* /* SOCK* */ sock, 433 MONKEY_SOCKTYPE socket); 434 435 436 extern NCBI_XCONNECT_EXPORT FMonkeySend g_MONKEY_Send; 437 extern NCBI_XCONNECT_EXPORT FMonkeyRecv g_MONKEY_Recv; 438 extern NCBI_XCONNECT_EXPORT FMonkeyPoll g_MONKEY_Poll; 439 extern NCBI_XCONNECT_EXPORT FMonkeyConnect g_MONKEY_Connect; 440 extern NCBI_XCONNECT_EXPORT FMonkeyClose g_MONKEY_Close; 441 extern NCBI_XCONNECT_EXPORT FSockHasSocket g_MONKEY_SockHasSocket; 442 #endif /*NCBI_MONKEY*/ 443 444 445 #ifdef __cplusplus 446 } /* extern "C" */ 447 #endif 448 449 #endif /* CONNECT___NCBI_PRIV__H */ 450