1 /* $Id: driver_mgr.cpp 535289 2017-05-08 13:38:35Z 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: Vladimir Soussov
27 *
28 * File Description: Driver manager
29 *
30 */
31
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbidll.hpp>
34 #include <corelib/ncbireg.hpp>
35
36 #include <corelib/plugin_manager.hpp>
37 #include <corelib/plugin_manager_impl.hpp>
38 #include <corelib/plugin_manager_store.hpp>
39 #include <corelib/ncbi_safe_static.hpp>
40
41 #include <dbapi/driver/driver_mgr.hpp>
42
43
44 BEGIN_NCBI_SCOPE
45
46
47 ///////////////////////////////////////////////////////////////////////////////
48 TPluginManagerParamTree*
MakePluginManagerParamTree(const string & driver_name,const map<string,string> * attr)49 MakePluginManagerParamTree(const string& driver_name, const map<string, string>* attr)
50 {
51 typedef map<string, string>::const_iterator TCIter;
52 CMemoryRegistry reg;
53 TCIter citer = attr->begin();
54 TCIter cend = attr->end();
55
56 for ( ; citer != cend; ++citer ) {
57 reg.Set( driver_name, citer->first, citer->second );
58 }
59
60 TPluginManagerParamTree* const tr = CConfig::ConvertRegToTree(reg);
61
62 return tr;
63 }
64
65
66 ///////////////////////////////////////////////////////////////////////////////
67 TPluginManagerParamTree*
MakePluginManagerParamTree(const CDBConnParams & params)68 MakePluginManagerParamTree(const CDBConnParams& params)
69 {
70 unique_ptr<TPluginManagerParamTree> tr(new TPluginManagerParamTree);
71
72 tr->GetKey() = params.GetDriverName();
73
74 string param_value;
75
76 param_value = params.GetParam("reuse_context");
77 if (!param_value.empty()) {
78 tr->AddNode(CConfig::TParamValue(
79 "reuse_context",
80 param_value
81 ));
82 }
83
84 param_value = params.GetParam("packet");
85 if (!param_value.empty()) {
86 tr->AddNode(CConfig::TParamValue(
87 "packet",
88 param_value
89 ));
90 }
91
92 param_value = params.GetParam("prog_name");
93 if (!param_value.empty()) {
94 tr->AddNode(CConfig::TParamValue(
95 "prog_name",
96 param_value
97 ));
98 }
99
100 param_value = params.GetParam("host_name");
101 if (!param_value.empty()) {
102 tr->AddNode(CConfig::TParamValue(
103 "host_name",
104 param_value
105 ));
106 }
107
108 if (params.GetProtocolVersion() != 0) {
109 tr->AddNode(CConfig::TParamValue("version" ,
110 NStr::IntToString(params.GetProtocolVersion())));
111 }
112
113 switch (params.GetEncoding()) {
114 case eEncoding_UTF8:
115 tr->AddNode(CConfig::TParamValue("client_charset" , "UTF8"));
116 break;
117 default:
118 break;
119 };
120
121 return tr.release();
122 }
123
124
125 ///////////////////////////////////////////////////////////////////////////////
126 CPluginManager_DllResolver*
operator ()(void)127 CDllResolver_Getter<I_DriverContext>::operator()(void)
128 {
129 CPluginManager_DllResolver* resolver =
130 new CPluginManager_DllResolver
131 (CInterfaceVersion<I_DriverContext>::GetName(),
132 kEmptyStr,
133 CVersionInfo::kAny,
134 CDll::eNoAutoUnload);
135 resolver->SetDllNamePrefix("ncbi");
136 return resolver;
137 }
138
139 ///////////////////////////////////////////////////////////////////////////////
140 class C_xDriverMgr
141 {
142 public:
143 C_xDriverMgr(void);
144 virtual ~C_xDriverMgr(void);
145
146 public:
147 /// Add path for the DLL lookup
148 void AddDllSearchPath(const string& path);
149 /// Delete all user-installed paths for the DLL lookup (for all resolvers)
150 /// @param previous_paths
151 /// If non-NULL, store the prevously set search paths in this container
152 void ResetDllSearchPath(vector<string>* previous_paths = NULL);
153
154 /// Specify which standard locations should be used for the DLL lookup
155 /// (for all resolvers). If standard locations are not set explicitelly
156 /// using this method CDllResolver::fDefaultDllPath will be used by default.
157 CDllResolver::TExtraDllPath
158 SetDllStdSearchPath(CDllResolver::TExtraDllPath standard_paths);
159
160 /// Get standard locations which should be used for the DLL lookup.
161 /// @sa SetDllStdSearchPath
162 CDllResolver::TExtraDllPath GetDllStdSearchPath(void) const;
163
164 I_DriverContext* GetDriverContext(
165 const string& driver_name,
166 const TPluginManagerParamTree* const attr = NULL);
167
168 I_DriverContext* GetDriverContext(
169 const string& driver_name,
170 const map<string, string>* attr = NULL);
171
172 private:
173 struct SDrivers {
174 typedef I_DriverContext* (*FDBAPI_CreateContext)(const map<string,string>* attr);
175
SDriversC_xDriverMgr::SDrivers176 SDrivers(const string& name, FDBAPI_CreateContext func) :
177 drv_name(name),
178 drv_func(func)
179 {
180 }
181
182 string drv_name;
183 FDBAPI_CreateContext drv_func;
184 };
185 vector<SDrivers> m_Drivers;
186
187 mutable CFastMutex m_Mutex;
188
189 private:
190 typedef CPluginManager<I_DriverContext> TContextManager;
191 typedef CPluginManagerGetter<I_DriverContext> TContextManagerStore;
192
193 CRef<TContextManager> m_ContextManager;
194 };
195
C_xDriverMgr(void)196 C_xDriverMgr::C_xDriverMgr(void)
197 {
198 m_ContextManager.Reset( TContextManagerStore::Get() );
199 #ifndef NCBI_COMPILER_COMPAQ
200 // For some reason, Compaq's compiler thinks m_ContextManager is
201 // inaccessible here!
202 _ASSERT( m_ContextManager );
203 #endif
204 }
205
206
~C_xDriverMgr(void)207 C_xDriverMgr::~C_xDriverMgr(void)
208 {
209 }
210
211
212 void
AddDllSearchPath(const string & path)213 C_xDriverMgr::AddDllSearchPath(const string& path)
214 {
215 CFastMutexGuard mg(m_Mutex);
216
217 m_ContextManager->AddDllSearchPath( path );
218 }
219
220
221 void
ResetDllSearchPath(vector<string> * previous_paths)222 C_xDriverMgr::ResetDllSearchPath(vector<string>* previous_paths)
223 {
224 CFastMutexGuard mg(m_Mutex);
225
226 m_ContextManager->ResetDllSearchPath( previous_paths );
227 }
228
229
230 CDllResolver::TExtraDllPath
SetDllStdSearchPath(CDllResolver::TExtraDllPath standard_paths)231 C_xDriverMgr::SetDllStdSearchPath(CDllResolver::TExtraDllPath standard_paths)
232 {
233 CFastMutexGuard mg(m_Mutex);
234
235 return m_ContextManager->SetDllStdSearchPath( standard_paths );
236 }
237
238
239 CDllResolver::TExtraDllPath
GetDllStdSearchPath(void) const240 C_xDriverMgr::GetDllStdSearchPath(void) const
241 {
242 CFastMutexGuard mg(m_Mutex);
243
244 return m_ContextManager->GetDllStdSearchPath();
245 }
246
247
248 I_DriverContext*
GetDriverContext(const string & driver_name,const TPluginManagerParamTree * const attr)249 C_xDriverMgr::GetDriverContext(
250 const string& driver_name,
251 const TPluginManagerParamTree* const attr)
252 {
253 I_DriverContext* drv = NULL;
254
255 try {
256 CFastMutexGuard mg(m_Mutex);
257
258 drv = m_ContextManager->CreateInstance(
259 driver_name,
260 NCBI_INTERFACE_VERSION(I_DriverContext),
261 attr
262 );
263 }
264 catch( const CPluginManagerException& ) {
265 throw;
266 }
267 catch ( const exception& e ) {
268 DATABASE_DRIVER_ERROR( driver_name + " is not available :: " + e.what(), 300 );
269 }
270 catch ( ... ) {
271 DATABASE_DRIVER_ERROR( driver_name + " was unable to load due an unknown error", 300 );
272 }
273
274 return drv;
275 }
276
277 I_DriverContext*
GetDriverContext(const string & driver_name,const map<string,string> * attr)278 C_xDriverMgr::GetDriverContext(
279 const string& driver_name,
280 const map<string, string>* attr)
281 {
282 unique_ptr<TPluginManagerParamTree> pt;
283 const TPluginManagerParamTree* nd = NULL;
284
285 if ( attr != NULL ) {
286 pt.reset( MakePluginManagerParamTree(driver_name, attr) );
287 _ASSERT(pt.get());
288 nd = pt->FindNode( driver_name );
289 }
290
291 return GetDriverContext(driver_name, nd);
292 }
293
294 ////////////////////////////////////////////////////////////////////////////////
295 static CSafeStatic<C_xDriverMgr> s_DrvMgr;
296
297
298 ////////////////////////////////////////////////////////////////////////////////
C_DriverMgr(unsigned int)299 C_DriverMgr::C_DriverMgr(unsigned int /* nof_drivers */)
300 {
301 }
302
303
~C_DriverMgr()304 C_DriverMgr::~C_DriverMgr()
305 {
306 }
307
GetDriverContext(const string & driver_name,string *,const map<string,string> * attr)308 I_DriverContext* C_DriverMgr::GetDriverContext(const string& driver_name,
309 string* /* err_msg */,
310 const map<string,string>* attr)
311 {
312 return s_DrvMgr->GetDriverContext( driver_name, attr );
313 }
314
315
316 void
AddDllSearchPath(const string & path)317 C_DriverMgr::AddDllSearchPath(const string& path)
318 {
319 s_DrvMgr->AddDllSearchPath( path );
320 }
321
322
323 void
ResetDllSearchPath(vector<string> * previous_paths)324 C_DriverMgr::ResetDllSearchPath(vector<string>* previous_paths)
325 {
326 s_DrvMgr->ResetDllSearchPath( previous_paths );
327 }
328
329
330 CDllResolver::TExtraDllPath
SetDllStdSearchPath(CDllResolver::TExtraDllPath standard_paths)331 C_DriverMgr::SetDllStdSearchPath(CDllResolver::TExtraDllPath standard_paths)
332 {
333 return s_DrvMgr->SetDllStdSearchPath( standard_paths );
334 }
335
336
337 CDllResolver::TExtraDllPath
GetDllStdSearchPath(void) const338 C_DriverMgr::GetDllStdSearchPath(void) const
339 {
340 return s_DrvMgr->GetDllStdSearchPath();
341 }
342
343
344 I_DriverContext*
GetDriverContextFromTree(const string & driver_name,const TPluginManagerParamTree * const attr)345 C_DriverMgr::GetDriverContextFromTree(
346 const string& driver_name,
347 const TPluginManagerParamTree* const attr)
348 {
349 return s_DrvMgr->GetDriverContext( driver_name, attr );
350 }
351
352
353 I_DriverContext*
GetDriverContextFromMap(const string & driver_name,const map<string,string> * attr)354 C_DriverMgr::GetDriverContextFromMap(
355 const string& driver_name,
356 const map<string, string>* attr)
357 {
358 return s_DrvMgr->GetDriverContext( driver_name, attr );
359 }
360
361
362 ///////////////////////////////////////////////////////////////////////////////
363 I_DriverContext*
Get_I_DriverContext(const string & driver_name,const map<string,string> * attr)364 Get_I_DriverContext(const string& driver_name, const map<string, string>* attr)
365 {
366 typedef CPluginManager<I_DriverContext> TReaderManager;
367 typedef CPluginManagerGetter<I_DriverContext> TReaderManagerStore;
368 I_DriverContext* drv = NULL;
369 const TPluginManagerParamTree* nd = NULL;
370
371 CRef<TReaderManager> ReaderManager(TReaderManagerStore::Get());
372 _ASSERT(ReaderManager);
373
374 try {
375 unique_ptr<TPluginManagerParamTree> pt;
376
377 if ( attr != NULL ) {
378 pt.reset( MakePluginManagerParamTree(driver_name, attr) );
379
380 _ASSERT( pt.get() );
381
382 nd = pt->FindNode( driver_name );
383 }
384 drv = ReaderManager->CreateInstance(
385 driver_name,
386 NCBI_INTERFACE_VERSION(I_DriverContext),
387 nd
388 );
389 }
390 catch( const CPluginManagerException& ) {
391 throw;
392 }
393 catch ( const exception& e ) {
394 DATABASE_DRIVER_ERROR( driver_name + " is not available :: " + e.what(), 300 );
395 }
396 catch ( ... ) {
397 DATABASE_DRIVER_ERROR( driver_name + " was unable to load due an unknown error", 300 );
398 }
399
400 return drv;
401 }
402
403
404 ///////////////////////////////////////////////////////////////////////////////
MakeDriverContext(const CDBConnParams & params)405 I_DriverContext* MakeDriverContext(const CDBConnParams& params)
406 {
407 typedef CPluginManager<I_DriverContext> TReaderManager;
408 typedef CPluginManagerGetter<I_DriverContext> TReaderManagerStore;
409 I_DriverContext* drv = NULL;
410
411 CRef<TReaderManager> ReaderManager(TReaderManagerStore::Get());
412 _ASSERT(ReaderManager);
413
414 try {
415 unique_ptr<TPluginManagerParamTree> pt;
416
417 pt.reset(MakePluginManagerParamTree(params));
418 _ASSERT( pt.get() );
419
420 drv = ReaderManager->CreateInstance(
421 params.GetDriverName(),
422 NCBI_INTERFACE_VERSION(I_DriverContext),
423 pt.get()
424 );
425 }
426 catch( const CPluginManagerException& ) {
427 throw;
428 }
429 catch ( const exception& e ) {
430 DATABASE_DRIVER_ERROR( params.GetDriverName() + " is not available :: " + e.what(), 300 );
431 }
432 catch ( ... ) {
433 DATABASE_DRIVER_ERROR( params.GetDriverName() + " was unable to load due an unknown error", 300 );
434 }
435
436 return drv;
437 }
438
439
440 END_NCBI_SCOPE
441
442
443