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