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