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>
36 * Thread database support
38 * Associate database connection with thread lifecycle
42 class ThreadDatabaseSupport :
43 public DPL::DB::ORM::IOrmInterface
46 typedef DPL::DB::SqlConnection *SqlConnectionPtr;
47 typedef DPL::ThreadLocalVariable<SqlConnectionPtr> TLVSqlConnectionPtr;
48 typedef DPL::ThreadLocalVariable<size_t> TLVSizeT;
49 typedef DPL::ThreadLocalVariable<bool> TLVBool;
51 TLVSqlConnectionPtr m_connection;
53 TLVSizeT m_refCounter;
54 TLVSizeT m_transactionDepth;
55 TLVSizeT m_attachCount;
56 TLVBool m_transactionCancel;
57 std::string m_address;
58 DPL::DB::SqlConnection::Flag::Type m_flags;
60 TLVSqlConnectionPtr &Connection()
70 TLVSizeT &RefCounter()
75 TLVSizeT &TransactionDepth()
77 return m_transactionDepth;
80 TLVSizeT &AttachCount()
85 TLVBool &TransactionCancel()
87 return m_transactionCancel;
90 void CheckedConnectionDelete()
92 Assert(!Connection().IsNull());
93 Assert(*Linger() == true);
95 if (*RefCounter() > 0 || *AttachCount() > 0) {
100 LogDebug("Destroying thread database connection: " << m_address);
102 delete *Connection();
105 Connection().GuardValue(false);
106 Linger().GuardValue(false);
107 RefCounter().GuardValue(false);
108 TransactionCancel().GuardValue(false);
109 TransactionDepth().GuardValue(false);
110 AttachCount().GuardValue(false);
112 Connection().Reset();
114 RefCounter().Reset();
115 TransactionCancel().Reset();
116 TransactionDepth().Reset();
117 AttachCount().Reset();
120 void TransactionUnref()
122 LogPedantic("Unref transaction");
124 if (--(*TransactionDepth()) == 0) {
125 LogPedantic("Transaction is finalized");
127 if (*TransactionCancel()) {
128 LogPedantic("Transaction will be rolled back");
129 (*Connection())->RollbackTransaction();
131 LogPedantic("Transaction will be commited");
132 (*Connection())->CommitTransaction();
138 ThreadDatabaseSupport(const std::string &address,
139 DPL::DB::SqlConnection::Flag::Type flags) :
144 virtual ~ThreadDatabaseSupport()
148 DPL::DB::SqlConnection::Flag::Option options =
149 DPL::DB::SqlConnection::Flag::RO)
153 if (!Connection().IsNull()) {
159 // Initialize SQL connection described in traits
160 LogDebug("Attaching thread database connection: " << m_address);
162 Connection() = new DPL::DB::SqlConnection(
163 m_address.c_str(), m_flags, options);
169 //Init Transaction related variables
170 TransactionDepth() = 0;
171 TransactionCancel() = false;
174 Connection().GuardValue(true);
175 Linger().GuardValue(true);
176 RefCounter().GuardValue(true);
177 TransactionDepth().GuardValue(true);
178 AttachCount().GuardValue(true);
179 TransactionCancel().GuardValue(true);
182 void DetachFromThread()
184 // Calling thread must support thread database connections
185 Assert(!Connection().IsNull());
190 if (*AttachCount() > 0) {
194 // It must not be in linger state yet
195 Assert(*Linger() == false);
197 LogDebug("Detaching thread database connection: " << m_address);
199 // Enter linger state
203 CheckedConnectionDelete();
208 return !AttachCount().IsNull() && *AttachCount() > 0;
211 DPL::DB::SqlConnection::DataCommand *AllocDataCommand(
212 const std::string &statement)
214 // Calling thread must support thread database connections
215 Assert(!Connection().IsNull());
217 // Calling thread must not be in linger state
218 Assert(*Linger() == false);
223 // Create new unmanaged data command
224 return (*Connection())->PrepareDataCommand(statement.c_str()).release();
227 void FreeDataCommand(DPL::DB::SqlConnection::DataCommand *command)
229 // Calling thread must support thread database connections
230 Assert(!Connection().IsNull());
232 // Delete data command
235 // Unreference SQL connection
238 // If it is linger state, connection may be destroyed
239 if (*Linger() == true) {
240 CheckedConnectionDelete();
244 void TransactionBegin()
246 // Calling thread must support thread database connections
247 Assert(!Connection().IsNull());
249 LogPedantic("Begin transaction");
251 // Addref transaction
252 if (++(*TransactionDepth()) == 1) {
253 LogPedantic("Transaction is initialized");
255 TransactionCancel() = false;
256 (*Connection())->BeginTransaction();
260 void TransactionCommit()
262 // Calling thread must support thread database connections
263 Assert(!Connection().IsNull());
265 LogPedantic("Commit transaction");
271 void TransactionRollback()
273 // Calling thread must support thread database connections
274 Assert(!Connection().IsNull());
276 // Cancel and unref transaction
277 TransactionCancel() = true;
281 DPL::DB::SqlConnection::RowID GetLastInsertRowID()
283 // Calling thread must support thread database connections
284 Assert(!Connection().IsNull());
286 return (*Connection())->GetLastInsertRowID();
289 bool CheckTableExist(const char *name)
291 // Calling thread must support thread database connections
292 Assert(!Connection().IsNull());
294 return (*Connection())->CheckTableExist(name);
300 #endif // DPL_THREAD_DATABASE_SUPPORT_H