63104c3bf012fc5bb247dad78d5ffe019caff3be
[platform/core/appfw/aul-1.git] / server / database.cc
1 /*
2  * Copyright (c) 2021 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 #include <unistd.h>
18
19 #include <memory>
20
21 #include "server/common_private.hh"
22 #include "server/database.hh"
23 #include "server/exception.hh"
24 #include "server/log_private.hh"
25
26 namespace aul {
27 namespace {
28
29 const int BUSY_WAITING_USEC = 50000;
30 const int BUSY_WAITING_MAX = 40;
31
32 }  // namespace
33
34 Database::Database(std::string path) : path_(std::move(path)) {
35 }
36
37 Database::~Database() {
38   Close();
39 }
40
41 void Database::BeginTransaction() {
42   int ret = sqlite3_exec(db_, "BEGIN TRANSACTION", nullptr, nullptr, nullptr);
43   if (ret != SQLITE_OK)
44     _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
45 }
46
47 void Database::EndTransaction() {
48   int ret = sqlite3_exec(db_, "END TRANSACTION", nullptr, nullptr, nullptr);
49   if (ret != SQLITE_OK)
50     _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
51 }
52
53 void Database::Rollback() {
54   int ret = sqlite3_exec(db_, "ROLLBACK", nullptr, nullptr, nullptr);
55   if (ret != SQLITE_OK)
56     _E("sqlite3_exec() is failed. error(%s:%d", sqlite3_errmsg(db_), ret);
57 }
58
59 void Database::Open(int flags) {
60   sqlite3* db;
61   int ret = sqlite3_open_v2(path_.c_str(), &db, flags, nullptr);
62   if (ret != SQLITE_OK) {
63     _E("sqlite3_open_v2() is failed. path(%s), error(%d)", path_.c_str(), ret);
64     THROW(-ret);
65   }
66
67   ret = sqlite3_busy_handler(db, BusyHandler,
68       static_cast<void*>(const_cast<char*>(path_.c_str())));
69   if (ret != SQLITE_OK) {
70     _E("sqlite3_busy_handler() is failed. error(%s:%d)",
71         sqlite3_errmsg(db), ret);
72     sqlite3_close_v2(db);
73     THROW(-ret);
74   }
75
76   ret = sqlite3_exec(db, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
77   if (ret != SQLITE_OK) {
78     _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db), ret);
79     sqlite3_close_v2(db);
80     THROW(-ret);
81   }
82
83   db_ = db;
84 }
85
86 void Database::Close() {
87   if (db_) {
88     sqlite3_close(db_);
89     db_ = nullptr;
90   }
91 }
92
93 sqlite3* Database::GetHandle() {
94   return db_;
95 }
96
97 std::string Database::ColumnText(sqlite3_stmt* stmt, int index) {
98   auto* text = reinterpret_cast<const char*>(sqlite3_column_text(stmt, index));
99   if (text)
100     return std::string(text);
101
102   return {};
103 }
104
105 bool Database::IntegrityCheck() {
106   static const char query[] = "PRAGMA integrity_check";
107   sqlite3_stmt* stmt;
108   int ret = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, nullptr);
109   if (ret != SQLITE_OK) {
110     _E("sqlite3_prepare_v2() is failed. error(%s:%d)",
111         sqlite3_errmsg(db_), ret);
112     return false;
113   }
114
115   std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*> stmt_ptr(
116       stmt, sqlite3_finalize);
117
118   ret = sqlite3_step(stmt);
119   if (ret != SQLITE_ROW) {
120     _E("sqlite3_step() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
121     return false;
122   }
123
124   auto* res = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
125   if (res == nullptr) {
126     _E("sqlite3_column_text() is failed. error(%s)", sqlite3_errmsg(db_));
127     return false;
128   }
129
130   if (strcmp(res, "ok") != 0)
131     return false;
132
133   return true;
134 }
135
136 std::string Database::GetPath(const std::string& name, uid_t uid) {
137   std::string path = std::string(tzplatform_getenv(TZ_SYS_DB)) + "/";
138   if (uid >= REGULAR_UID_MIN)
139     path += "user/" + std::to_string(uid) + "/";
140
141   path += name;
142   return path;
143 }
144
145 int Database::BusyHandler(void* data, int count) {
146   if (count < BUSY_WAITING_MAX) {
147     usleep(BUSY_WAITING_USEC);
148     return 1;
149   }
150
151   auto* path = static_cast<char*>(data);
152   _E("Database(%s) is busy", path);
153   return 0;
154 }
155
156 }  // namespace aul