tizen 2.3.1 release
[framework/web/wearable/wrt-security.git] / commons / modules / db / include / dpl / db / thread_database_support.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /*
17  * @file    thread_database_support.h
18  * @author  Przemyslaw Dobrowolski (p.dobrowolsk)
19  * @version 1.0
20  * @brief   This file contains the declaration of thread database support
21  */
22
23 #ifndef DPL_THREAD_DATABASE_SUPPORT_H
24 #define DPL_THREAD_DATABASE_SUPPORT_H
25
26 #include <string>
27 #include <dpl/db/sql_connection.h>
28 #include <dpl/db/orm_interface.h>
29 #include <dpl/thread.h>
30 #include <dpl/assert.h>
31 #include <stdint.h>
32
33 namespace DPL {
34 namespace DB {
35 /**
36  * Thread database support
37  *
38  * Associate database connection with thread lifecycle
39  *
40  */
41
42 class ThreadDatabaseSupport :
43     public DPL::DB::ORM::IOrmInterface
44 {
45   private:
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;
50
51     TLVSqlConnectionPtr m_connection;
52     TLVBool m_linger;
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;
59
60     TLVSqlConnectionPtr &Connection()
61     {
62         return m_connection;
63     }
64
65     TLVBool &Linger()
66     {
67         return m_linger;
68     }
69
70     TLVSizeT &RefCounter()
71     {
72         return m_refCounter;
73     }
74
75     TLVSizeT &TransactionDepth()
76     {
77         return m_transactionDepth;
78     }
79
80     TLVSizeT &AttachCount()
81     {
82         return m_attachCount;
83     }
84
85     TLVBool &TransactionCancel()
86     {
87         return m_transactionCancel;
88     }
89
90     void CheckedConnectionDelete()
91     {
92         Assert(!Connection().IsNull());
93         Assert(*Linger() == true);
94
95         if (*RefCounter() > 0 || *AttachCount() > 0) {
96             return;
97         }
98
99         // Destroy connection
100         LogDebug("Destroying thread database connection: " << m_address);
101
102         delete *Connection();
103
104         // Blocking destroy
105         Connection().GuardValue(false);
106         Linger().GuardValue(false);
107         RefCounter().GuardValue(false);
108         TransactionCancel().GuardValue(false);
109         TransactionDepth().GuardValue(false);
110         AttachCount().GuardValue(false);
111
112         Connection().Reset();
113         Linger().Reset();
114         RefCounter().Reset();
115         TransactionCancel().Reset();
116         TransactionDepth().Reset();
117         AttachCount().Reset();
118     }
119
120     void TransactionUnref()
121     {
122         LogPedantic("Unref transaction");
123
124         if (--(*TransactionDepth()) == 0) {
125             LogPedantic("Transaction is finalized");
126
127             if (*TransactionCancel()) {
128                 LogPedantic("Transaction will be rolled back");
129                 (*Connection())->RollbackTransaction();
130             } else {
131                 LogPedantic("Transaction will be commited");
132                 (*Connection())->CommitTransaction();
133             }
134         }
135     }
136
137   public:
138     ThreadDatabaseSupport(const std::string &address,
139                           DPL::DB::SqlConnection::Flag::Type flags) :
140         m_address(address),
141         m_flags(flags)
142     {}
143
144     virtual ~ThreadDatabaseSupport()
145     {}
146
147     void AttachToThread(
148         DPL::DB::SqlConnection::Flag::Option options =
149             DPL::DB::SqlConnection::Flag::RO)
150     {
151         Linger() = false;
152
153         if (!Connection().IsNull()) {
154             // Add reference
155             ++*AttachCount();
156             return;
157         }
158
159         // Initialize SQL connection described in traits
160         LogDebug("Attaching thread database connection: " << m_address);
161
162         Connection() = new DPL::DB::SqlConnection(
163                 m_address.c_str(), m_flags, options);
164
165         RefCounter() = 0;
166
167         AttachCount() = 1;
168
169         //Init Transaction related variables
170         TransactionDepth() = 0;
171         TransactionCancel() = false;
172
173         // Blocking destroy
174         Connection().GuardValue(true);
175         Linger().GuardValue(true);
176         RefCounter().GuardValue(true);
177         TransactionDepth().GuardValue(true);
178         AttachCount().GuardValue(true);
179         TransactionCancel().GuardValue(true);
180     }
181
182     void DetachFromThread()
183     {
184         // Calling thread must support thread database connections
185         Assert(!Connection().IsNull());
186
187         // Remove reference
188         --*AttachCount();
189
190         if (*AttachCount() > 0) {
191             return;
192         }
193
194         // It must not be in linger state yet
195         Assert(*Linger() == false);
196
197         LogDebug("Detaching thread database connection: " << m_address);
198
199         // Enter linger state
200         *Linger() = true;
201
202         // Checked delete
203         CheckedConnectionDelete();
204     }
205
206     bool IsAttached()
207     {
208         return !AttachCount().IsNull() && *AttachCount() > 0;
209     }
210
211     DPL::DB::SqlConnection::DataCommand *AllocDataCommand(
212         const std::string &statement)
213     {
214         // Calling thread must support thread database connections
215         Assert(!Connection().IsNull());
216
217         // Calling thread must not be in linger state
218         Assert(*Linger() == false);
219
220         // Add reference
221         ++*RefCounter();
222
223         // Create new unmanaged data command
224         return (*Connection())->PrepareDataCommand(statement.c_str()).release();
225     }
226
227     void FreeDataCommand(DPL::DB::SqlConnection::DataCommand *command)
228     {
229         // Calling thread must support thread database connections
230         Assert(!Connection().IsNull());
231
232         // Delete data command
233         delete command;
234
235         // Unreference SQL connection
236         --*RefCounter();
237
238         // If it is linger state, connection may be destroyed
239         if (*Linger() == true) {
240             CheckedConnectionDelete();
241         }
242     }
243
244     void TransactionBegin()
245     {
246         // Calling thread must support thread database connections
247         Assert(!Connection().IsNull());
248
249         LogPedantic("Begin transaction");
250
251         // Addref transaction
252         if (++(*TransactionDepth()) == 1) {
253             LogPedantic("Transaction is initialized");
254
255             TransactionCancel() = false;
256             (*Connection())->BeginTransaction();
257         }
258     }
259
260     void TransactionCommit()
261     {
262         // Calling thread must support thread database connections
263         Assert(!Connection().IsNull());
264
265         LogPedantic("Commit transaction");
266
267         // Unref transation
268         TransactionUnref();
269     }
270
271     void TransactionRollback()
272     {
273         // Calling thread must support thread database connections
274         Assert(!Connection().IsNull());
275
276         // Cancel and unref transaction
277         TransactionCancel() = true;
278         TransactionUnref();
279     }
280
281     DPL::DB::SqlConnection::RowID GetLastInsertRowID()
282     {
283         // Calling thread must support thread database connections
284         Assert(!Connection().IsNull());
285
286         return (*Connection())->GetLastInsertRowID();
287     }
288
289     bool CheckTableExist(const char *name)
290     {
291         // Calling thread must support thread database connections
292         Assert(!Connection().IsNull());
293
294         return (*Connection())->CheckTableExist(name);
295     }
296 };
297 }
298 }
299
300 #endif // DPL_THREAD_DATABASE_SUPPORT_H