2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file thread_database_support.h
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk)
20 * @brief This file contains the declaration of thread database support
23 #ifndef DPL_THREAD_DATABASE_SUPPORT_H
24 #define DPL_THREAD_DATABASE_SUPPORT_H
27 #include <dpl/db/sql_connection.h>
28 #include <dpl/db/orm_interface.h>
29 #include <dpl/thread.h>
30 #include <dpl/assert.h>
39 * Thread database support
41 * Associate database connection with thread lifecycle
45 class ThreadDatabaseSupport :
46 public DPL::DB::ORM::IOrmInterface
49 typedef DPL::DB::SqlConnection *SqlConnectionPtr;
50 typedef DPL::ThreadLocalVariable<SqlConnectionPtr> TLVSqlConnectionPtr;
51 typedef DPL::ThreadLocalVariable<size_t> TLVSizeT;
52 typedef DPL::ThreadLocalVariable<bool> TLVBool;
54 TLVSqlConnectionPtr m_connection;
56 TLVSizeT m_refCounter;
57 TLVSizeT m_transactionDepth;
58 TLVSizeT m_attachCount;
59 TLVBool m_transactionCancel;
60 std::string m_address;
61 DPL::DB::SqlConnection::Flag::Type m_flags;
63 TLVSqlConnectionPtr &Connection()
73 TLVSizeT &RefCounter()
78 TLVSizeT &TransactionDepth()
80 return m_transactionDepth;
83 TLVSizeT &AttachCount()
88 TLVBool &TransactionCancel()
90 return m_transactionCancel;
93 void CheckedConnectionDelete()
95 Assert(!Connection().IsNull());
96 Assert(*Linger() == true);
98 if (*RefCounter() > 0 || *AttachCount() > 0) {
102 // Destroy connection
103 LogInfo("Destroying thread database connection: " << m_address);
105 delete *Connection();
108 Connection().GuardValue(false);
109 Linger().GuardValue(false);
110 RefCounter().GuardValue(false);
111 TransactionCancel().GuardValue(false);
112 TransactionDepth().GuardValue(false);
113 AttachCount().GuardValue(false);
115 Connection().Reset();
117 RefCounter().Reset();
118 TransactionCancel().Reset();
119 TransactionDepth().Reset();
120 AttachCount().Reset();
123 void TransactionUnref()
125 LogPedantic("Unref transaction");
127 if (--(*TransactionDepth()) == 0) {
128 LogPedantic("Transaction is finalized");
130 if (*TransactionCancel()) {
131 LogPedantic("Transaction will be rolled back");
132 (*Connection())->ExecCommand("ROLLBACK;");
134 LogPedantic("Transaction will be commited");
135 (*Connection())->ExecCommand("COMMIT;");
141 ThreadDatabaseSupport(const std::string &address,
142 DPL::DB::SqlConnection::Flag::Type flags) :
148 virtual ~ThreadDatabaseSupport()
153 DPL::DB::SqlConnection::Flag::Option options =
154 DPL::DB::SqlConnection::Flag::RO)
158 if (!Connection().IsNull()) {
164 // Initialize SQL connection described in traits
165 LogInfo("Attaching thread database connection: " << m_address);
167 Connection() = new DPL::DB::SqlConnection(m_address.c_str(), m_flags, options);
173 //Init Transaction related variables
174 TransactionDepth() = 0;
175 TransactionCancel() = false;
178 Connection().GuardValue(true);
179 Linger().GuardValue(true);
180 RefCounter().GuardValue(true);
181 TransactionDepth().GuardValue(true);
182 AttachCount().GuardValue(true);
183 TransactionCancel().GuardValue(true);
186 void DetachFromThread()
188 // Calling thread must support thread database connections
189 Assert(!Connection().IsNull());
194 if (*AttachCount() > 0) {
198 // It must not be in linger state yet
199 Assert(*Linger() == false);
201 LogInfo("Detaching thread database connection: " << m_address);
203 // Enter linger state
207 CheckedConnectionDelete();
212 return !AttachCount().IsNull() && *AttachCount() > 0;
215 DPL::DB::SqlConnection::DataCommand *AllocDataCommand(
216 const std::string &statement)
218 // Calling thread must support thread database connections
219 Assert(!Connection().IsNull());
221 // Calling thread must not be in linger state
222 Assert(*Linger() == false);
227 // Create new unmanaged data command
228 return (*Connection())->PrepareDataCommand(statement.c_str()).release();
231 void FreeDataCommand(DPL::DB::SqlConnection::DataCommand *command)
233 // Calling thread must support thread database connections
234 Assert(!Connection().IsNull());
236 // Delete data command
239 // Unreference SQL connection
242 // If it is linger state, connection may be destroyed
243 if (*Linger() == true) {
244 CheckedConnectionDelete();
248 void TransactionBegin()
250 // Calling thread must support thread database connections
251 Assert(!Connection().IsNull());
253 LogPedantic("Begin transaction");
255 // Addref transaction
256 if (++(*TransactionDepth()) == 1) {
257 LogPedantic("Transaction is initialized");
259 TransactionCancel() = false;
260 (*Connection())->ExecCommand("BEGIN;");
264 void TransactionCommit()
266 // Calling thread must support thread database connections
267 Assert(!Connection().IsNull());
269 LogPedantic("Commit transaction");
275 void TransactionRollback()
277 // Calling thread must support thread database connections
278 Assert(!Connection().IsNull());
280 // Cancel and unref transaction
281 TransactionCancel() = true;
285 DPL::DB::SqlConnection::RowID GetLastInsertRowID()
287 // Calling thread must support thread database connections
288 Assert(!Connection().IsNull());
290 return (*Connection())->GetLastInsertRowID();
293 bool CheckTableExist(const char *name)
295 // Calling thread must support thread database connections
296 Assert(!Connection().IsNull());
298 return (*Connection())->CheckTableExist(name);
305 #endif // DPL_THREAD_DATABASE_SUPPORT_H