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