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()
152 void AttachToThread()
156 if (!Connection().IsNull()) {
162 // Initialize SQL connection described in traits
163 LogInfo("Attaching thread database connection: " << m_address);
165 Connection() = new DPL::DB::SqlConnection(m_address.c_str(), m_flags);
171 //Init Transaction related variables
172 TransactionDepth() = 0;
173 TransactionCancel() = false;
176 Connection().GuardValue(true);
177 Linger().GuardValue(true);
178 RefCounter().GuardValue(true);
179 TransactionDepth().GuardValue(true);
180 AttachCount().GuardValue(true);
181 TransactionCancel().GuardValue(true);
184 void DetachFromThread()
186 // Calling thread must support thread database connections
187 Assert(!Connection().IsNull());
192 if (*AttachCount() > 0) {
196 // It must not be in linger state yet
197 Assert(*Linger() == false);
199 LogInfo("Detaching thread database connection: " << m_address);
201 // Enter linger state
205 CheckedConnectionDelete();
210 return !AttachCount().IsNull() && *AttachCount() > 0;
213 DPL::DB::SqlConnection::DataCommand *AllocDataCommand(
214 const std::string &statement)
216 // Calling thread must support thread database connections
217 Assert(!Connection().IsNull());
219 // Calling thread must not be in linger state
220 Assert(*Linger() == false);
225 // Create new unmanaged data command
226 return (*Connection())->PrepareDataCommand(statement.c_str()).release();
229 void FreeDataCommand(DPL::DB::SqlConnection::DataCommand *command)
231 // Calling thread must support thread database connections
232 Assert(!Connection().IsNull());
234 // Delete data command
237 // Unreference SQL connection
240 // If it is linger state, connection may be destroyed
241 if (*Linger() == true) {
242 CheckedConnectionDelete();
246 void TransactionBegin()
248 // Calling thread must support thread database connections
249 Assert(!Connection().IsNull());
251 LogPedantic("Begin transaction");
253 // Addref transaction
254 if (++(*TransactionDepth()) == 1) {
255 LogPedantic("Transaction is initialized");
257 TransactionCancel() = false;
258 (*Connection())->ExecCommand("BEGIN;");
262 void TransactionCommit()
264 // Calling thread must support thread database connections
265 Assert(!Connection().IsNull());
267 LogPedantic("Commit transaction");
273 void TransactionRollback()
275 // Calling thread must support thread database connections
276 Assert(!Connection().IsNull());
278 // Cancel and unref transaction
279 TransactionCancel() = true;
283 DPL::DB::SqlConnection::RowID GetLastInsertRowID()
285 // Calling thread must support thread database connections
286 Assert(!Connection().IsNull());
288 return (*Connection())->GetLastInsertRowID();
291 bool CheckTableExist(const char *name)
293 // Calling thread must support thread database connections
294 Assert(!Connection().IsNull());
296 return (*Connection())->CheckTableExist(name);
303 #endif // DPL_THREAD_DATABASE_SUPPORT_H