1 /* $Id: ncbi_core_cxx.cpp 624723 2021-02-03 18:51:43Z ivanov $
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: Anton Lavrentiev
27 *
28 * File Description:
29 * C++->C conversion tools for basic CORE connect stuff:
30 * Registry
31 * Logging
32 * Locking
33 *
34 */
35
36 #include <ncbi_pch.hpp>
37 #include "ncbi_ansi_ext.h"
38 #include "ncbi_priv.h"
39 #include "ncbi_socketp.h"
40 #include <corelib/ncbiapp.hpp>
41 #include <corelib/ncbidbg.hpp>
42 #include <corelib/ncbi_param.hpp>
43 #include <corelib/request_ctx.hpp>
44 #include <connect/error_codes.hpp>
45 #include <connect/ncbi_core_cxx.hpp>
46 #include <connect/ncbi_monkey.hpp>
47 #include <common/ncbi_sanitizers.h>
48
49 #define NCBI_USE_ERRCODE_X Connect_Core
50
51
52 BEGIN_NCBI_SCOPE
53
54
55 NCBI_PARAM_DECL (bool, CONN, TRACE_REG);
56 NCBI_PARAM_DEF_EX(bool, CONN, TRACE_REG,
57 false, eParam_Default, CONN_TRACE_REG);
58 static NCBI_PARAM_TYPE (CONN, TRACE_REG) s_TraceReg;
59
60 NCBI_PARAM_DECL (bool, CONN, TRACE_LOG);
61 NCBI_PARAM_DEF_EX(bool, CONN, TRACE_LOG,
62 false, eParam_Default, CONN_TRACE_LOG);
63 static NCBI_PARAM_TYPE (CONN, TRACE_LOG) s_TraceLog;
64
65 NCBI_PARAM_DECL (bool, CONN, TRACE_LOCK);
66 NCBI_PARAM_DEF_EX(bool, CONN, TRACE_LOCK,
67 false, eParam_Default, CONN_TRACE_LOCK);
68 static NCBI_PARAM_TYPE (CONN, TRACE_LOCK) s_TraceLock;
69
70
71 static TCORE_Set s_CORE_Set = 0;
72
73
74 /***********************************************************************
75 * Registry *
76 ***********************************************************************/
77
78
x_Reg(const char * section,const char * name,const char * value=0,EREG_Storage storage=eREG_Transient)79 static string x_Reg(const char* section, const char* name,
80 const char* value = 0,
81 EREG_Storage storage = eREG_Transient)
82 {
83 string x_section;
84 if (section)
85 x_section = '[' + string(section) + ']';
86 else
87 x_section = "<NULL>";
88 string x_name;
89 if (name)
90 x_name = '"' + string(name) + '"';
91 else
92 x_name = "<NULL>";
93 string x_value;
94 if (value)
95 x_value = "=\"" + string(value) + '"';
96 string x_storage;
97 if (value) {
98 switch (int(storage)) {
99 case eREG_Transient:
100 x_storage = ", <Transient>";
101 break;
102 case eREG_Persistent:
103 x_storage = ", <Persistent>";
104 break;
105 default:
106 x_storage = ", <" + NStr::IntToString(int(storage)) + '>';
107 break;
108 }
109 }
110 return x_section + x_name + x_value + x_storage;
111 }
112
113
114 extern "C" {
s_REG_Get(void * user_data,const char * section,const char * name,char * value,size_t value_size)115 static int s_REG_Get(void* user_data,
116 const char* section, const char* name,
117 char* value, size_t value_size) THROWS_NONE
118 {
119 if (s_TraceReg.Get()) {
120 _TRACE("s_REG_Get(" + NStr::PtrToString(user_data) + ", "
121 + x_Reg(section, name) + ')');
122 }
123 int result = 0/*assume error, including truncation*/;
124 try {
125 string item
126 = static_cast<const IRegistry*> (user_data)->Get(section, name);
127 if (!item.empty()) {
128 size_t len = item.size();
129 if (len >= value_size)
130 len = value_size - 1;
131 else
132 result = 1/*success*/;
133 strncpy0(value, item.data(), len);
134
135 if (s_TraceReg.Get()) {
136 _TRACE("s_REG_Get(" + NStr::PtrToString(user_data) + ", "
137 + x_Reg(section, name) + ") = \"" + string(value)
138 + (result ? "\"" : "\" <Truncated>"));
139 }
140 } else
141 result = -1/*unmodified*/;
142 }
143 NCBI_CATCH_ALL_X(1, "s_REG_Get(" + NStr::PtrToString(user_data) + ", "
144 + x_Reg(section, name)
145 + ") failed");
146 return result;
147 }
148 }
149
150
151 extern "C" {
s_REG_Set(void * user_data,const char * section,const char * name,const char * value,EREG_Storage storage)152 static int s_REG_Set(void* user_data,
153 const char* section, const char* name,
154 const char* value, EREG_Storage storage) THROWS_NONE
155 {
156 if (s_TraceReg.Get()) {
157 _TRACE("s_REG_" + string(value ? "Set" : "Unset") + '('
158 + NStr::PtrToString(user_data) + ", "
159 + x_Reg(section, name, value ? value : "", storage) + ')');
160 }
161 int result = 0;
162 try {
163 IRWRegistry* reg = static_cast<IRWRegistry*> (user_data);
164 result = value
165 ? reg->Set (section, name, value,
166 (storage == eREG_Persistent
167 ? CNcbiRegistry::fPersistent
168 | CNcbiRegistry::fTruncate
169 : CNcbiRegistry::fTruncate))
170 : reg->Unset(section, name,
171 (storage == eREG_Persistent
172 ? CNcbiRegistry::fPersistent
173 : CNcbiRegistry::fTransient));
174 }
175 NCBI_CATCH_ALL_X(2, "s_REG_" + string(value ? "Set" : "Unset") + '('
176 + NStr::PtrToString(user_data) + ", "
177 + x_Reg(section, name, value ? value : "", storage)
178 + ") failed");
179 return result;
180 }
181 }
182
183
184 extern "C" {
s_REG_Cleanup(void * user_data)185 static void s_REG_Cleanup(void* user_data) THROWS_NONE
186 {
187
188 if (s_TraceReg.Get())
189 _TRACE("s_REG_Cleanup(" + NStr::PtrToString(user_data) + ')');
190 try {
191 static_cast<const IRegistry*> (user_data)->RemoveReference();
192 }
193 NCBI_CATCH_ALL_X(3, "s_REG_Cleanup("
194 + NStr::PtrToString(user_data) + ") failed");
195 }
196 }
197
198
REG_cxx2c(IRWRegistry * reg,bool pass_ownership)199 extern REG REG_cxx2c(IRWRegistry* reg, bool pass_ownership)
200 {
201 if (s_TraceReg.Get())
202 _TRACE("REG_cxx2c(" + NStr::PtrToString(reg) + ')');
203 if (!reg)
204 return 0;
205 if (pass_ownership)
206 reg->AddReference();
207 return REG_Create(reg,
208 s_REG_Get, s_REG_Set,
209 pass_ownership ? s_REG_Cleanup : 0, 0);
210 }
211
212
REG_cxx2c(const IRWRegistry * reg,bool pass_ownership)213 extern REG REG_cxx2c(const IRWRegistry* reg, bool pass_ownership)
214 {
215 if (s_TraceReg.Get())
216 _TRACE("REG_cxx2c(const " + NStr::PtrToString(reg) + ')');
217 if (!reg)
218 return 0;
219 if (pass_ownership)
220 reg->AddReference();
221 return REG_Create(const_cast<IRWRegistry*> (reg),
222 s_REG_Get, 0/*no setter*/,
223 pass_ownership ? s_REG_Cleanup : 0, 0);
224 }
225
226
227 /***********************************************************************
228 * Logger *
229 ***********************************************************************/
230
231
x_Log(ELOG_Level level)232 static string x_Log(ELOG_Level level)
233 {
234 string x_level;
235 switch (int(level)) {
236 case eLOG_Trace:
237 x_level = "Trace";
238 break;
239 case eLOG_Note:
240 x_level = "Note";
241 break;
242 case eLOG_Warning:
243 x_level = "Warning";
244 break;
245 case eLOG_Error:
246 x_level = "Error";
247 break;
248 case eLOG_Critical:
249 x_level = "Critical";
250 break;
251 case eLOG_Fatal:
252 x_level = "Fatal";
253 break;
254 default:
255 x_level = NStr::IntToString(int(level));
256 break;
257 }
258 return x_level;
259 }
260
261
262 extern "C" {
s_LOG_Handler(void *,const SLOG_Message * mess)263 static void s_LOG_Handler(void* /*data*/,
264 const SLOG_Message* mess) THROWS_NONE
265 {
266 if (s_TraceLog.Get())
267 _TRACE("s_LOG_Handler(" + x_Log(mess->level) + ')');
268 try {
269 EDiagSev level;
270 switch (int(mess->level)) {
271 case eLOG_Trace:
272 level = eDiag_Trace;
273 break;
274 case eLOG_Note:
275 level = eDiag_Info;
276 break;
277 case eLOG_Warning:
278 level = eDiag_Warning;
279 break;
280 case eLOG_Error:
281 level = eDiag_Error;
282 break;
283 case eLOG_Critical:
284 level = eDiag_Critical;
285 break;
286 case eLOG_Fatal:
287 /*FALLTHRU*/
288 default:
289 level = eDiag_Fatal;
290 break;
291 }
292 if (!IsVisibleDiagPostLevel(level))
293 return;
294
295 CDiagCompileInfo info(mess->file,
296 mess->line,
297 mess->func,
298 mess->module);
299 CNcbiDiag diag(info, level);
300 diag.SetErrorCode(mess->err_code, mess->err_subcode);
301 diag << mess->message;
302 if (mess->raw_size) {
303 diag <<
304 "\n#################### [BEGIN] Raw Data (" <<
305 mess->raw_size <<
306 " byte" << (mess->raw_size != 1 ? "s" : "") << ")\n" <<
307 NStr::PrintableString
308 (CTempString(static_cast<const char*>(mess->raw_data),
309 mess->raw_size),
310 NStr::fNewLine_Passthru | NStr::fNonAscii_Quote) <<
311 "\n#################### [END] Raw Data";
312 }
313 }
314 NCBI_CATCH_ALL_X(4, "s_LOG_Handler(" + x_Log(mess->level) + ") failed");
315 }
316 }
317
318
LOG_cxx2c(void)319 extern LOG LOG_cxx2c(void)
320 {
321 if (s_TraceLog.Get())
322 _TRACE("LOG_cxx2c()");
323 return LOG_Create(0, s_LOG_Handler, 0, 0);
324 }
325
326
327 /***********************************************************************
328 * MT-Lock *
329 ***********************************************************************/
330
331
x_Lock(EMT_Lock how)332 static string x_Lock(EMT_Lock how)
333 {
334 string x_how;
335 switch (int(how)) {
336 case eMT_Lock:
337 x_how = "Lock";
338 break;
339 case eMT_LockRead:
340 x_how = "ReadLock";
341 break;
342 case eMT_Unlock:
343 x_how = "Unlock";
344 break;
345 case eMT_TryLock:
346 x_how = "TryLock";
347 break;
348 case eMT_TryLockRead:
349 x_how = "TryLockRead";
350 break;
351 default:
352 x_how = NStr::IntToString(int(how));
353 break;
354 }
355 return x_how;
356 }
357
358
359 extern "C" {
s_LOCK_Handler(void * user_data,EMT_Lock how)360 static int/*bool*/ s_LOCK_Handler(void* user_data, EMT_Lock how) THROWS_NONE
361 {
362 if (s_TraceLock.Get()) {
363 _TRACE("s_LOCK_Handler(" + NStr::PtrToString(user_data) + ", "
364 + x_Lock(how) + ')');
365 }
366 try {
367 CRWLock* lock = static_cast<CRWLock*> (user_data);
368 switch (int(how)) {
369 case eMT_Lock:
370 lock->WriteLock();
371 break;
372 case eMT_LockRead:
373 lock->ReadLock();
374 break;
375 case eMT_Unlock:
376 lock->Unlock();
377 break;
378 case eMT_TryLock:
379 if (!lock->TryWriteLock())
380 return 0/*false*/;
381 break;
382 case eMT_TryLockRead:
383 if (!lock->TryReadLock())
384 return 0/*false*/;
385 break;
386 default:
387 NCBI_THROW(CCoreException, eCore, "Lock used with unknown op #" +
388 NStr::UIntToString((unsigned int) how));
389 }
390 return 1/*true*/;
391 }
392 NCBI_CATCH_ALL_X(5, "s_LOCK_Handler(" + NStr::PtrToString(user_data) + ", "
393 + x_Lock(how) + ") failed");
394 return 0/*false*/;
395 }
396 }
397
398
399 extern "C" {
s_LOCK_Cleanup(void * user_data)400 static void s_LOCK_Cleanup(void* user_data) THROWS_NONE
401 {
402 if (s_TraceLock.Get())
403 _TRACE("s_LOCK_Cleanup(" + NStr::PtrToString(user_data) + ')');
404 try {
405 delete static_cast<CRWLock*> (user_data);
406 }
407 NCBI_CATCH_ALL_X(6, "s_LOCK_Cleanup("
408 + NStr::PtrToString(user_data) + ") failed");
409 }
410 }
411
412
MT_LOCK_cxx2c(CRWLock * lock,bool pass_ownership)413 extern MT_LOCK MT_LOCK_cxx2c(CRWLock* lock, bool pass_ownership)
414 {
415 if (s_TraceLock.Get())
416 _TRACE("MT_LOCK_cxx2c(" + NStr::PtrToString(lock) + ')');
417 return MT_LOCK_Create(static_cast<void*> (lock ? lock : new CRWLock),
418 s_LOCK_Handler,
419 !lock || pass_ownership ? s_LOCK_Cleanup : 0);
420 }
421
422
423 /***********************************************************************
424 * App Name *
425 ***********************************************************************/
426
427
428 extern "C" {
s_GetAppName(void)429 static const char* s_GetAppName(void)
430 {
431 CNcbiApplicationGuard app = CNcbiApplication::InstanceGuard();
432 return app ? app->GetProgramDisplayName().c_str() : 0;
433 }
434 }
435
436
437 /***********************************************************************
438 * NCBI Request ID *
439 ***********************************************************************/
440
441
442 extern "C" {
s_GetRequestID(ENcbiRequestID reqid)443 static char* s_GetRequestID(ENcbiRequestID reqid)
444 {
445 string id;
446 switch (reqid) {
447 case eNcbiRequestID_SID:
448 if (!CDiagContext::GetRequestContext().IsSetSessionID())
449 CDiagContext::GetRequestContext().SetSessionID();
450 CDiagContext::GetRequestContext().GetSessionID().swap(id);
451 break;
452 case eNcbiRequestID_HitID:
453 id = CDiagContext::GetRequestContext().GetNextSubHitID();
454 break;
455 default:
456 return 0;
457 }
458 return id.empty() ? 0 : strdup(id.c_str());
459 }
460 }
461
462
463 /***********************************************************************
464 * NCBI Request DTab *
465 ***********************************************************************/
466
467
468 extern "C" {
s_GetRequestDTab(void)469 static const char* s_GetRequestDTab(void)
470 {
471 if (!CDiagContext::GetRequestContext().IsSetDtab())
472 CDiagContext::GetRequestContext().SetDtab("");
473 return CDiagContext::GetRequestContext().GetDtab().c_str();
474 }
475 }
476
477
478 /***********************************************************************
479 * CRAZY MONKEY CALLS *
480 ***********************************************************************/
481
482
483 #ifdef NCBI_MONKEY
484 extern "C" {
485 static MONKEY_RETTYPE
s_MonkeySend(MONKEY_SOCKTYPE sock,const MONKEY_DATATYPE data,MONKEY_LENTYPE size,int flags,void * sock_ptr)486 MONKEY_STDCALL s_MonkeySend(MONKEY_SOCKTYPE sock,
487 const MONKEY_DATATYPE data,
488 MONKEY_LENTYPE size,
489 int flags,
490 void* /* SOCK* */ sock_ptr)
491 {
492 return CMonkey::Instance()->Send(sock, data, size, flags,
493 (SOCK*)sock_ptr);
494 }
495
496 static MONKEY_RETTYPE
s_MonkeyRecv(MONKEY_SOCKTYPE sock,MONKEY_DATATYPE buf,MONKEY_LENTYPE size,int flags,void * sock_ptr)497 MONKEY_STDCALL s_MonkeyRecv(MONKEY_SOCKTYPE sock,
498 MONKEY_DATATYPE buf,
499 MONKEY_LENTYPE size,
500 int flags,
501 void* /* SOCK* */ sock_ptr)
502 {
503 return CMonkey::Instance()->Recv(sock, buf, size, flags,
504 (SOCK*) sock_ptr);
505 }
506
507
s_MonkeyConnect(MONKEY_SOCKTYPE sock,const struct sockaddr * name,MONKEY_SOCKLENTYPE namelen)508 static int MONKEY_STDCALL s_MonkeyConnect(MONKEY_SOCKTYPE sock,
509 const struct sockaddr* name,
510 MONKEY_SOCKLENTYPE namelen)
511 {
512 return CMonkey::Instance()->Connect(sock, name, namelen);
513 }
514
515
s_MonkeyPoll(size_t * n,void * polls,EIO_Status * return_status)516 static int /*bool*/ s_MonkeyPoll(size_t* n,
517 void* /* SSOCK_Poll** */ polls,
518 EIO_Status* return_status)
519 {
520 return CMonkey::Instance()->
521 Poll(n, (SSOCK_Poll**) polls, return_status) ? 1 : 0;
522 }
523
524
s_MonkeyClose(SOCKET sock)525 static void s_MonkeyClose(SOCKET sock)
526 {
527 CMonkey::Instance()->Close(sock);
528 }
529
530
s_MonkeySockHasSocket(void * sock,MONKEY_SOCKTYPE socket)531 static void s_MonkeySockHasSocket(void* /* SOCK* */ sock,
532 MONKEY_SOCKTYPE socket)
533 {
534 CMonkey::Instance()->SockHasSocket((SOCK)sock, socket);
535 }
536 }
537
538
s_MONKEY_Poll_dummy(size_t * n,void * polls,EIO_Status * return_status)539 static int s_MONKEY_Poll_dummy(size_t* n,
540 void* polls,
541 EIO_Status* return_status)
542 {
543 return 0; /* call was not intercepted by Monkey*/
544 }
545
546
s_MONKEY_Close_dummy(SOCKET sock)547 static void s_MONKEY_Close_dummy(SOCKET sock)
548 {
549 return; /* call was not intercepted by Monkey*/
550 }
551
552
553 /* Chaos Monkey hooks for Connect library*/
s_SetMonkeyHooks(EMonkeyHookSwitch hook_switch)554 static void s_SetMonkeyHooks(EMonkeyHookSwitch hook_switch)
555 {
556 switch (hook_switch)
557 {
558 case eMonkeyHookSwitch_Disabled:
559 g_MONKEY_Send = 0;
560 g_MONKEY_Recv = 0;
561 g_MONKEY_Connect = 0;
562 g_MONKEY_Poll = 0;
563 g_MONKEY_Close = 0;
564 g_MONKEY_SockHasSocket = 0;
565 break;
566 case eMonkeyHookSwitch_Enabled:
567 g_MONKEY_Send = s_MonkeySend;
568 g_MONKEY_Recv = s_MonkeyRecv;
569 g_MONKEY_Connect = s_MonkeyConnect;
570 g_MONKEY_Poll = s_MonkeyPoll;
571 g_MONKEY_Close = s_MonkeyClose;
572 g_MONKEY_SockHasSocket = s_MonkeySockHasSocket;
573 break;
574 default:
575 break;
576 }
577 }
578 #endif //NCBI_MONKEY
579
580
581 static volatile enum EConnectInit {
582 eConnectInit_Weak = -1, ///< CConn_Initer
583 eConnectInit_Intact = 0, ///< Not yet visited
584 eConnectInit_Strong = 1, ///< User init detected
585 eConnectInit_Explicit = 2 ///< CONNECT_Init() called
586 } s_ConnectInit = eConnectInit_Intact;
587
588
589 /***********************************************************************
590 * Fini *
591 ***********************************************************************/
592
593
594 extern "C" {
s_Fini(void)595 static void s_Fini(void) THROWS_NONE
596 {
597 _TRACE("CONNECT::s_Fini()");
598 s_CORE_Set &= ~g_CORE_Set;
599 if (s_CORE_Set & eCORE_SetSSL)
600 SOCK_SetupSSL(0);
601 if (s_CORE_Set & eCORE_SetREG)
602 CORE_SetREG(0);
603 if (s_CORE_Set & eCORE_SetLOG)
604 CORE_SetLOG(0);
605 if (s_CORE_Set & eCORE_SetLOCK)
606 CORE_SetLOCK(&g_CORE_MT_Lock_default);
607 g_CORE_Set &= ~s_CORE_Set;
608 s_CORE_Set = 0;
609 }
610 }
611
612
613 /***********************************************************************
614 * Init *
615 ***********************************************************************/
616
617
618 DEFINE_STATIC_FAST_MUTEX(s_ConnectInitMutex);
619
620 /* NB: gets called under a lock */
s_Init(const IRWRegistry * reg=0,FSSLSetup ssl=0,CRWLock * lock=0,TConnectInitFlags flag=0,EConnectInit how=eConnectInit_Weak)621 static void s_Init(const IRWRegistry* reg = 0,
622 FSSLSetup ssl = 0,
623 CRWLock* lock = 0,
624 TConnectInitFlags flag = 0,
625 EConnectInit how = eConnectInit_Weak)
626 {
627 _TRACE("CONNECT::s_Init("
628 + NStr::PtrToString(reg) + ", "
629 + NStr::PtrToString((void*) ssl) + "(), "
630 + NStr::PtrToString(lock) + ", 0x"
631 + NStr::UIntToString((unsigned int) flag, 0, 16) + ", "
632 + NStr::IntToString(int(how)) + ')');
633 _ASSERT(how != eConnectInit_Intact);
634
635 TCORE_Set set = 0;
636 if (!(g_CORE_Set & eCORE_SetLOCK)) {
637 NCBI_LSAN_DISABLE_GUARD;
638 CORE_SetLOCK(MT_LOCK_cxx2c(lock, !!(flag & eConnectInit_OwnLock)));
639 set |= eCORE_SetLOCK;
640 }
641 if (!(g_CORE_Set & eCORE_SetLOG)) {
642 CORE_SetLOG(LOG_cxx2c());
643 set |= eCORE_SetLOG;
644 }
645 if (!(g_CORE_Set & eCORE_SetREG)) {
646 CORE_SetREG(REG_cxx2c(reg, !!(flag & eConnectInit_OwnRegistry)));
647 set |= eCORE_SetREG;
648 }
649 if (!(g_CORE_Set & eCORE_SetSSL)) {
650 SOCK_SetupSSLInternal(ssl, 1/*init*/);
651 set |= ssl ? eCORE_SetSSL : 0;
652 }
653 g_CORE_Set &= ~set;
654 s_CORE_Set |= set;
655
656 if (s_ConnectInit == eConnectInit_Intact) {
657 g_NCBI_ConnectRandomSeed
658 = (unsigned int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND;
659 srand(g_NCBI_ConnectRandomSeed);
660 atexit(s_Fini);
661 }
662
663 g_CORE_GetAppName = s_GetAppName;
664 g_CORE_GetRequestID = s_GetRequestID;
665 g_CORE_GetRequestDtab = s_GetRequestDTab;
666
667 #ifdef NCBI_MONKEY
668 /* Allow CMonkey to switch hooks to Connect library */
669 CMonkey::MonkeyHookSwitchSet(s_SetMonkeyHooks);
670 /* Create CMonkey instance. It loads config and sets hooks */
671 CMonkey::Instance();
672 #endif //NCBI_MONKEY
673
674 s_ConnectInit = g_CORE_Set ? eConnectInit_Strong : how;
675 }
676
677
678 /* PUBLIC */
CONNECT_Init(const IRWRegistry * reg,CRWLock * lock,TConnectInitFlags flag,FSSLSetup ssl)679 extern void CONNECT_Init(const IRWRegistry* reg,
680 CRWLock* lock,
681 TConnectInitFlags flag,
682 FSSLSetup ssl)
683 {
684 CFastMutexGuard guard(s_ConnectInitMutex);
685 _TRACE("CONNECT_Init("
686 + NStr::PtrToString(reg) + ", "
687 + NStr::PtrToString(lock) + ", 0x"
688 + NStr::UIntToString((unsigned int) flag, 0, 16) + ", "
689 + NStr::PtrToString((void*) ssl) + "())");
690 try {
691 g_CORE_Set = 0;
692 s_Init(reg, flag & eConnectInit_NoSSL ? 0 :
693 ssl ? ssl : NcbiSetupTls,
694 lock, flag, eConnectInit_Explicit);
695 }
696 NCBI_CATCH_ALL_X(8, "CONNECT_Init() failed");
697 }
698
699
CConnIniter(void)700 CConnIniter::CConnIniter(void)
701 {
702 if (s_ConnectInit != eConnectInit_Intact)
703 return;
704 CFastMutexGuard guard(s_ConnectInitMutex);
705 try {
706 if (s_ConnectInit == eConnectInit_Intact) {
707 CNcbiApplicationGuard app = CNcbiApplication::InstanceGuard();
708 s_Init(app ? &app->GetConfig() : 0, NcbiSetupTls);
709 }
710 }
711 NCBI_CATCH_ALL_X(7, "CConn_Initer::CConn_Initer() failed");
712 }
713
714
715 END_NCBI_SCOPE
716