Fix Metadata Plugin Parser
[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 std::string Database::ColumnText(sqlite3_stmt* stmt, int index) {
100   auto* text = reinterpret_cast<const char*>(sqlite3_column_text(stmt, index));
101   if (text)
102     return std::string(text);
103
104   return {};
105 }
106
107 bool Database::IntegrityCheck() {
108   static const char query[] = "PRAGMA integrity_check";
109   sqlite3_stmt* stmt;
110   int ret = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, nullptr);
111   if (ret != SQLITE_OK) {
112     _E("sqlite3_prepare_v2() is failed. error(%s:%d)",
113         sqlite3_errmsg(db_), ret);
114     return false;
115   }
116
117   std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*> stmt_ptr(
118       stmt, sqlite3_finalize);
119
120   ret = sqlite3_step(stmt);
121   if (ret != SQLITE_ROW) {
122     _E("sqlite3_step() is failed. error(%s:%d)", sqlite3_errmsg(db_), ret);
123     return false;
124   }
125
126   auto* res = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
127   if (res == nullptr) {
128     _E("sqlite3_column_text() is failed. error(%s)", sqlite3_errmsg(db_));
129     return false;
130   }
131
132   if (strcmp(res, "ok") != 0)
133     return false;
134
135   return true;
136 }
137
138 int Database::BusyHandler(void* data, int count) {
139   if (count < BUSY_WAITING_MAX) {
140     usleep(BUSY_WAITING_USEC);
141     return 1;
142   }
143   auto* path = static_cast<char*>(data);
144   _E("Database(%s) is busy", path);
145   return 0;
146 }
147
148 }  // namespace plugin