778962642363e3bf1765609ac96dcf045ccd70e3
[platform/core/appfw/aul-1.git] / parser / metadata / common / database.cc
1 /*
2  * Copyright (c) 2020 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 "common/database.hh"
22 #include "common/exception.hh"
23 #include "common/log_private.hh"
24
25 namespace plugin {
26
27 static const int BUSY_WAITING_USEC = 50000;
28 static const int BUSY_WAITING_MAX = 40;
29
30 Database::Database(std::string path) : path_(std::move(path)) {
31 }
32
33 Database::~Database() {
34   Close();
35 }
36
37 void Database::BeginTransaction() {
38   int ret = sqlite3_exec(db_, "BEGIN TRANSACTION", nullptr, nullptr, nullptr);
39   if (ret != SQLITE_OK) {
40     _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
41     THROW(-ret);
42   }
43 }
44
45 void Database::EndTransaction() {
46   int ret = sqlite3_exec(db_, "END TRANSACTION", nullptr, nullptr, nullptr);
47   if (ret != SQLITE_OK) {
48     _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
49     THROW(-ret);
50   }
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     THROW(-ret);
58   }
59 }
60
61 void Database::Open() {
62   sqlite3* db;
63   int ret = sqlite3_open_v2(path_.c_str(), &db, SQLITE_OPEN_READWRITE, nullptr);
64   if (ret != SQLITE_OK) {
65     _E("sqlite3_open_v2() is failed. error(%d)", ret);
66     THROW(-ret);
67   }
68
69   ret = sqlite3_busy_handler(db, BusyHandler,
70       static_cast<void*>(const_cast<char*>(path_.c_str())));
71   if (ret != SQLITE_OK) {
72     _E("sqlite3_busy_handler() is failed. error(%s:%d)",
73         sqlite3_errmsg(db), ret);
74     sqlite3_close_v2(db);
75     THROW(-ret);
76   }
77
78   ret = sqlite3_exec(db, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
79   if (ret != SQLITE_OK) {
80     _E("sqlite3_exec() is failed. error(%s:%d)", sqlite3_errmsg(db), ret);
81     sqlite3_close_v2(db);
82     THROW(-ret);
83   }
84
85   db_ = db;
86 }
87
88 void Database::Close() {
89   if (db_) {
90     sqlite3_close(db_);
91     db_ = nullptr;
92   }
93 }
94
95 sqlite3* Database::GetHandle() {
96   return db_;
97 }
98
99 bool Database::IntegrityCheck() {
100   static const char query[] = "PRAGMA integrity_check";
101   sqlite3_stmt* stmt;
102   int ret = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, nullptr);
103   if (ret != SQLITE_OK) {
104     _E("sqlite3_prepare_v2() is failed. error(%s:%d)",
105         sqlite3_errmsg(db_), ret);
106     return false;
107   }
108
109   std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*> stmt_ptr(
110       stmt, sqlite3_finalize);
111
112   ret = sqlite3_step(stmt);
113   if (ret != SQLITE_ROW) {
114     _E("sqlite3_step() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
115     return false;
116   }
117
118   auto* res = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
119   if (res == nullptr) {
120     _E("sqlite3_column_text() is failed. error(%s)", sqlite3_errmsg(db_));
121     return false;
122   }
123
124   if (strcmp(res, "ok") != 0)
125     return false;
126
127   return true;
128 }
129
130 int Database::BusyHandler(void* data, int count) {
131   if (count < BUSY_WAITING_MAX) {
132     usleep(BUSY_WAITING_USEC);
133     return 1;
134   }
135   auto* path = static_cast<char*>(data);
136   _E("Database(%s) is busy", path);
137   return 0;
138 }
139
140 }  // namespace plugin