1 /* $Id: ds_impl.cpp 570898 2018-09-17 17:45:17Z ucko $
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:  Michael Kholodov
27 *
28 * File Description:
29 *   DataSource implementation
30 *
31 */
32 
33 #include <ncbi_pch.hpp>
34 #include <dbapi/error_codes.hpp>
35 #include "ds_impl.hpp"
36 #include "conn_impl.hpp"
37 #include "err_handler.hpp"
38 
39 
40 #define NCBI_USE_ERRCODE_X   Dbapi_ObjImpls
41 
42 
43 BEGIN_NCBI_SCOPE
44 
45 
CDataSource(I_DriverContext * ctx)46 CDataSource::CDataSource(I_DriverContext *ctx)
47     : m_loginTimeout(30), m_context(ctx), m_poolUsed(false),
48       m_multiExH(0)
49 {
50     SetIdent("CDataSource");
51 }
52 
~CDataSource()53 CDataSource::~CDataSource()
54 {
55     try {
56         _TRACE("Deleting " << GetIdent() << " " << (void*)this);
57         Notify(CDbapiDeletedEvent(this));
58 
59         if (m_multiExH) {
60             // Unregister a msg handler with a context ...
61             m_context->PopCntxMsgHandler(m_multiExH);
62             m_context->PopDefConnMsgHandler(m_multiExH);
63         }
64 
65         delete m_multiExH;
66 
67         // We won't delete context unless all connections are closed.
68         // This will cause a memory leak but it also will prevent from
69         // accessing an already freed memory.  Closing unused connections
70         // before checking is fair game, though!
71         m_context->CloseUnusedConnections();
72         if (m_context->NofConnections() == 0) {
73             delete m_context;
74         }
75 
76         _TRACE(GetIdent() << " " << (void*)this << " deleted.");
77     }
78     NCBI_CATCH_ALL_X( 5, kEmptyStr )
79 }
80 
SetLoginTimeout(unsigned int i)81 void CDataSource::SetLoginTimeout(unsigned int i)
82 {
83     m_loginTimeout = i;
84     if( m_context != 0 ) {
85         m_context->SetLoginTimeout(i);
86     }
87 }
88 
SetLogStream(CNcbiOstream * out)89 void CDataSource::SetLogStream(CNcbiOstream* out)
90 {
91     if( out != 0 ) {
92         // Clear the previous handlers if present
93         if( m_multiExH != 0 ) {
94             m_context->PopCntxMsgHandler(m_multiExH);
95             m_context->PopDefConnMsgHandler(m_multiExH);
96             delete m_multiExH;
97             _TRACE("SetLogStream(): CDataSource " << (void*)this
98                 << ": message handler " << (void*)m_multiExH
99                 << " removed from context " << (void*)m_context);
100             m_multiExH = 0;
101         }
102 
103         CDB_UserHandler *newH = new CDB_UserHandler_Stream(out);
104         CDB_UserHandler *h = CDB_UserHandler::SetDefault(newH);
105         delete h;
106         _TRACE("SetLogStream(): CDataSource " << (void*)this
107                 << ": new default message handler " << (void*)newH
108                 << " installed");
109    }
110     else {
111         if( m_multiExH == 0 ) {
112             m_multiExH = new CToMultiExHandler;
113 
114             m_context->PushCntxMsgHandler(m_multiExH);
115             m_context->PushDefConnMsgHandler(m_multiExH);
116             _TRACE("SetLogStream(): CDataSource " << (void*)this
117                 << ": message handler " << (void*)m_multiExH
118                 << " installed on context " << (void*)m_context);
119         }
120     }
121 }
122 
GetHandler()123 CToMultiExHandler* CDataSource::GetHandler()
124 {
125     return m_multiExH;
126 }
127 
GetErrorAsEx()128 CDB_MultiEx* CDataSource::GetErrorAsEx()
129 {
130     return GetHandler() == 0 ? 0 : GetHandler()->GetMultiEx();
131 }
132 
GetErrorInfo()133 string CDataSource::GetErrorInfo()
134 {
135     if( m_multiExH != 0 ) {
136         CNcbiOstrstream out;
137         CDB_UserHandler_Stream h(&out);
138         h.HandleIt(GetHandler()->GetMultiEx());
139 
140         // Replace MultiEx
141         GetHandler()->ReplaceMultiEx();
142 /*
143         m_context->PopCntxMsgHandler(m_multiExH);
144         m_context->PopDefConnMsgHandler(m_multiExH);
145         delete m_multiExH;
146         m_multiExH = new CToMultiExHandler;
147         m_context->PushCntxMsgHandler(m_multiExH);
148         m_context->PushDefConnMsgHandler(m_multiExH);
149 */
150         return CNcbiOstrstreamToString(out);
151     }
152     else
153         return kEmptyStr;
154 }
155 
156 
157 
GetDriverContext()158 I_DriverContext* CDataSource::GetDriverContext() {
159     CHECK_NCBI_DBAPI(
160         m_context == 0,
161         "CDataSource::GetDriverContext(): no valid context"
162         );
163 
164     return m_context;
165 }
166 
GetDriverContext() const167 const I_DriverContext* CDataSource::GetDriverContext() const
168 {
169     //CHECK_NCBI_DBAPI(
170     //    m_context == 0,
171     //    "CDataSource::GetDriverContext(): no valid context"
172     //    );
173 
174     //return m_context;
175 	return const_cast<CDataSource*>(this)->GetDriverContext();
176 }
177 
CreateConnection(EOwnership ownership)178 IConnection* CDataSource::CreateConnection(EOwnership ownership)
179 {
180     CConnection *conn = new CConnection(this, ownership);
181     AddListener(conn);
182     conn->AddListener(this);
183     return conn;
184 }
185 
Action(const CDbapiEvent & e)186 void CDataSource::Action(const CDbapiEvent& e)
187 {
188     _TRACE(GetIdent() << " " << (void*)this << ": '" << e.GetName()
189            << "' from " << e.GetSource()->GetIdent());
190 
191     if( dynamic_cast<const CDbapiDeletedEvent*>(&e) != 0 ) {
192         RemoveListener(e.GetSource());
193     }
194 }
195 
196 
197 END_NCBI_SCOPE
198