DCL 4.0
Loading...
Searching...
No Matches
SQLConnection.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2#if __DCL_WINDOWS
3#include <windows.h>
4#endif
5// 2005.01.26
6
7#include <dcl/Object.h>
8
9#if __DCL_HAVE_ALLOC_DEBUG
10#undef __DCL_ALLOC_LEVEL
11#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
12#endif
13
14#include <dcl/Charset.h>
15#include <dcl/Thread.h> // for SQLConnectionPool
16#include <dcl/SQL.h>
17
18#if __DCL_DEBUG
19#undef __THIS_FILE__
20static const wchar_t __THIS_FILE__[] = __T("dcl/SQLConnection.cpp");
21#endif
22
23__DCL_BEGIN_NAMESPACE
24
27
28void SQLConnection::initialize(SQLDriver* _driver)
29{
30 __DCL_ASSERT_PARAM(_driver != NULL);
31
32 __handle = NULL;
33 __driver = NULL;
34 __connected = false;
35
36 SQL::Connection* _connHandle = _driver->createConnection();
37 __DCL_ASSERT(_connHandle != NULL);
38
39 __handle = _connHandle;
40 __driver = _driver;
41}
42
44{
45 __DCL_ASSERT_PARAM(_driver != NULL);
46 initialize(_driver);
47}
48
49SQLConnection::SQLConnection(const String& _driverName)
51{
52 __DCL_ASSERT_PARAM(!_driverName.isEmpty());
53
54 SQLDriver* _driver = SQLDriver::getDriver(_driverName);
55 initialize(_driver);
56}
57
59{
60 __DCL_ASSERT(__handle->refCount() == 0);
61 if (__connected) {
62 try {
63 //__DCL_TRACE0(__T("close()\n"));
64 close();
65 }
66 catch (SQLException* e) {
67 __DCL_TRACE1(__T("Warning! %ls\n"), e->toString().data());
68 e->destroy();
69 }
70 }
71
72 __driver->destroyConnection(__handle);
73 //__handle = NULL;
74 //__driver = NULL;
75}
76
77// Operations
78void SQLConnection::open(const String& _connString)
80{
81 __DCL_ASSERT(__handle != NULL);
83
84 ByteString bs = UTF8Encoder::encode(_connString);
85
86 if (!__handle->open(bs, bs.length())) {
87#ifdef __DCL_DEBUG
88 throw new SQLException(this, _connString);
89#else
90 throw new SQLException(this);
91#endif
92 }
93
95}
96
98{
100
101 if (__connected) {
102 if (inTransaction())
104
105 if (!__handle->close()) {
106 throw new SQLException(this);
107 }
108
109 __connected = false;
110 }
111}
112
113void SQLConnection::execute(const String& _strSQL)
115{
116 __DCL_ASSERT(__handle != NULL);
118
119 ByteString bstr = UTF8Encoder::encode(_strSQL);
120
121 if (!__handle->execute(bstr, bstr.length())) {
122 throw new SQLException(this, _strSQL);
123 }
124}
125
127{
130// __DCL_ASSERT(!inTransaction());
131
132 if (!__handle->startTrans()) {
133 throw new SQLException(this);
134 }
135}
136
138{
141// __DCL_ASSERT(inTransaction());
142
143 if (!__handle->commitTrans()) {
144 throw new SQLException(this);
145 }
146}
147
149{
152// __DCL_ASSERT(inTransaction());
153
154 if (!__handle->rollbackTrans()) {
155 throw new SQLException(this);
156 }
157}
158
160{
162
163 if (__connected) {
165 }
166 return false;
167}
168
171{
174
175 size_t len = 1024;
176 ByteBuffer* buf = ByteBuffer::create(len);
177 if (!__handle->getServerInfo(buf->data(), &len)) {
178 buf->release();
179 throw new SQLException(this);
180 }
181 buf->__dataLength = len;
182 ByteString r = buf;
183 buf->release();
184
185 return UTF8Decoder::decode(r);
186}
187
189{
192 return __handle->canTransact();
193}
194
196
197SQLConnectionPool::SQLConnectionPool(
198 const String& _connString,
199 const String& _driverName
201 // : __lock("SQLConnectionPoolLock")
202{
203 __DCL_ASSERT(!_connString.isEmpty());
204 __DCL_ASSERT(!_driverName.isEmpty());
205
206 __sqlDriver = SQLDriver::getDriver(_driverName);
207 __connString = _connString;
208 __idleMax = 0;
209 __allMax = (size_t)-1; // unlimited
210}
211
212SQLConnectionPool::~SQLConnectionPool()
213{
214 clear(4);
215}
216
217SQLConnection* SQLConnectionPool::getConnection()
219{
220 SQLConnection* r = NULL;
221 __lock.lock();
222
223 try {
224 if (__idleConns.isEmpty()) {
225 // idle 콘넥션이 비어 있고
226 // 최대 콘넥선 개수보다 작으면 새로운 콘넥션을 생성한다.
227 if (__allConns.size() < __allMax) {
228 r = new SQLConnection(__sqlDriver);
229 try {
230 r->open(__connString);
231 }
232 catch(SQLException* e) {
233 delete r;
234 r = NULL;
235 throw e;
236 }
237 __allConns.add(r);
238 }
239 }
240 else {
241 r = (SQLConnection*)__idleConns.removeHead();
242 }
243 }
244 catch (SQLException* e) {
245 __lock.unlock();
246 throw e;
247 }
248#ifdef __DCL_DEBUG
249 catch (AssertError* e) {
250 __lock.unlock();
251 throw e;
252 }
253#endif
254
255 __lock.unlock();
256 return r;
257}
258
259void SQLConnectionPool::release(SQLConnection* _conn)
260{
261 __DCL_ASSERT_PARAM(_conn != NULL);
262 __DCL_ASSERT(__allConns.find(_conn) != __allConns.end());
263 Exception* e = NULL;
264 __lock.lock();
265
266 try {
267 __idleConns.addTail(_conn);
268 if (__idleMax < __idleConns.size()) {
269 size_t nCloseCount = __idleConns.size() - __idleMax;
270 while(nCloseCount--) {
271 try {
272 _conn = (SQLConnection*)__idleConns.removeHead();
273 __allConns.erase(__allConns.find(_conn));
274 delete _conn;
275 }
276 catch(Exception* e) {
278 __T("SQLConnectionPool::clear(): %ls\n"),
279 e->toString().data()
280 );
281 e->destroy();
282 }
283 }
284 }
285 }
286 catch (Exception* _e) {
287 e = _e;
288 }
289
290 __lock.unlock();
291 if (e != NULL) {
292 throw e;
293 }
294}
295
296bool SQLConnectionPool::setMaxCount(size_t _idleMax, size_t _allMax
297 )
298{
299 __DCL_ASSERT_PARAM(_idleMax >= 0 && _allMax >= 0);
300
301 bool r = true;
302
303 __lock.lock();
304
305 __idleMax = _idleMax;
306 __allMax = _allMax;
307
308 __lock.unlock();
309
310 return r;
311}
312
313void SQLConnectionPool::clear(unsigned _waitSeconds)
314{
315 __allMax = -1; // set cleanup process
316
317 // 콘넥션들이 release되기를 최대 _waitSeconds 초를 기다린다.
318 // _waitSeconds초가 지나면 강제로 콘넥션을 제거한다.
319 __lock.lock();
320 while((__idleConns.size() < __allConns.size())
321 && (_waitSeconds-- > 0)) {
322 // 사용중인 콘넥션이 있다.
323 __lock.unlock();
324 Thread::sleep(1000); // 1초
325 __lock.lock();
326 }
327
328 if (__idleConns.size() < __allConns.size()) {
329 // 강제로 콘넥션들을 제거한다.
331 __T("Warning! SQLConnection 강제 삭제!!! count(%d)\n"),
332 __allConns.size() - __idleConns.size()
333 );
334 }
335 // else 모든 콘넥션이 idle 상태이다
336
337 PointerArray::Iterator it = __allConns.begin();
338 for(; it != __allConns.end(); it++) {
339 try {
340 delete (SQLConnection*)((*it));
341 }
342 catch(Exception* e) {
344 __T("SQLConnectionPool::clear(): %ls\n"),
345 e->toString().data()
346 );
347 e->destroy();
348 }
349 }
350 __allConns.clear();
351 __idleConns.clear();
352 __lock.unlock();
353}
354
355__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define __DCL_THROWS2(e1, e2)
Definition Config.h:168
#define __DCL_THROWS1(e)
Definition Config.h:167
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:384
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
ByteString r
ByteString bstr
size_t len
__connected
ByteString bs
ByteBuffer * buf
void CharsetConvertException *__fields clear()
virtual String toString() const
Definition Exception.cpp:40
virtual void destroy()
Definition Exception.cpp:74
bool getServerInfo(char *_pbuf, size_t *_pn)
Definition SQLCore.cpp:784
SQLDriver * __driver
Definition SQL.h:340
bool __connected
Definition SQL.h:341
void execute(const String &_sql) __DCL_THROWS2(SQLException *
String CharsetConvertException *bool canTransact() const
SQLConnection(SQLDriver *_driver)
void rollbackTrans() __DCL_THROWS1(SQLException *)
String getServerInfo() __DCL_THROWS2(SQLException *
bool inTransaction() const
SQL::Connection * __handle
Definition SQL.h:339
void open(const String &_connString) __DCL_THROWS2(SQLException *
virtual ~SQLConnection()
void commitTrans() __DCL_THROWS1(SQLException *)
void CharsetConvertException *void startTrans() __DCL_THROWS1(SQLException *)
void CharsetConvertException *void close() __DCL_THROWS1(SQLException *)
PointerList __idleConns
Definition SQL.h:371
Thread::Mutex __lock
Definition SQL.h:374
SQLDriver * __sqlDriver
Definition SQL.h:368
size_t __idleMax
Definition SQL.h:376
size_t __allMax
Definition SQL.h:377
String __connString
Definition SQL.h:369
PointerArray __allConns
Definition SQL.h:372
static SQLDriver * getDriver(const String &_name) __DCL_THROWS1(SQLDriverException *)
SQL::Connection * createConnection()
virtual String toString() const
static void sleep(unsigned int _mills)
Definition Thread.cpp:150