2 * Copyright (c) 2015 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 #include "common/app_db.h"
19 // #define USE_APP_PREFERENCE;
20 #ifdef USE_APP_PREFERENCE
21 #include <app_preference.h>
31 #include "common/logger.h"
32 #include "common/string_utils.h"
33 #include "common/file_utils.h"
34 #include "common/picojson.h"
36 #ifndef USE_APP_PREFERENCE
37 #include "common/app_db_sqlite.h"
43 #ifdef USE_APP_PREFERENCE
44 const char* kSectionPrefix = "_SECT_";
45 const char* kSectionSuffix = "_SECT_";
47 const char* kCreateDbQuery = "CREATE TABLE IF NOT EXISTS appdb ("
51 "PRIMARY KEY(section, key));";
55 #ifdef USE_APP_PREFERENCE
57 class PreferenceAppDB : public AppDB {
60 virtual bool HasKey(const std::string& section,
61 const std::string& key) const;
62 virtual std::string Get(const std::string& section,
63 const std::string& key) const;
64 virtual void Set(const std::string& section,
65 const std::string& key,
66 const std::string& value);
67 virtual void GetKeys(const std::string& section,
68 std::list<std::string>* keys) const;
69 virtual void Remove(const std::string& section,
70 const std::string& key);
73 PreferenceAppDB::PreferenceAppDB() {
76 bool PreferenceAppDB::HasKey(const std::string& section,
77 const std::string& key) const {
79 std::string combined_key = kSectionPrefix + section + kSectionSuffix + key;
80 return preference_is_existing(combined_key.c_str(), &existed) == 0 && existed;
83 std::string PreferenceAppDB::Get(const std::string& section,
84 const std::string& key) const {
85 std::string combined_key = kSectionPrefix + section + kSectionSuffix + key;
87 if (preference_get_string(combined_key.c_str(), &value) == 0) {
88 std::unique_ptr<char, decltype(std::free)*> ptr {value, std::free};
89 return std::string(value);
94 void PreferenceAppDB::Set(const std::string& section,
95 const std::string& key,
96 const std::string& value) {
97 std::string combined_key = kSectionPrefix + section + kSectionSuffix + key;
98 preference_set_string(combined_key.c_str(), value.c_str());
101 void PreferenceAppDB::GetKeys(const std::string& section,
102 std::list<std::string>* keys) const {
103 auto callback = [](const char* key, void *user_data) {
104 auto list = static_cast<std::list<std::string>*>(user_data);
105 if (utils::StartsWith(key, list->front())) {
106 list->push_back(key+list->front().size());
110 std::string key_prefix = kSectionPrefix + section + kSectionSuffix;
111 keys->push_front(key_prefix);
112 preference_foreach_item(callback, keys);
116 void PreferenceAppDB::Remove(const std::string& section,
117 const std::string& key) {
118 std::string combined_key = kSectionPrefix + section + kSectionSuffix + key;
119 preference_remove(combined_key.c_str());
122 #else // end of USE_APP_PREFERENCE
124 SqliteDB::SqliteDB(const std::string& app_data_path)
125 : app_data_path_(app_data_path),
127 if (app_data_path_.empty()) {
128 std::unique_ptr<char, decltype(std::free)*>
129 path {app_get_data_path(), std::free};
130 if (path.get() != NULL)
131 app_data_path_ = path.get();
136 SqliteDB::~SqliteDB() {
137 if (sqldb_ != NULL) {
138 sqlite3_close(sqldb_);
143 void SqliteDB::MigrationAppdb() {
145 std::string migration_path = app_data_path_ + ".runtime.migration";
146 if (!common::utils::Exists(migration_path)) {
149 LOGGER(DEBUG) << "Migration file found : " << migration_path;
152 std::ifstream migration_file(migration_path);
153 if (!migration_file.is_open()) {
154 LOGGER(ERROR) << "Fail to open file";
159 err = picojson::parse(v, migration_file);
161 LOGGER(ERROR) << "Fail to parse file :" << err;
165 LOGGER(DEBUG) << "Start to get list data";
167 picojson::array data_list;
169 if (!v.get("preference").is<picojson::null>()) {
170 picojson::array preference_list
171 = v.get("preference").get<picojson::array>();
172 data_list.insert(data_list.end(),
173 preference_list.begin(),
174 preference_list.end());
176 if (!v.get("certificate").is<picojson::null>()) {
177 picojson::array certificate_list
178 = v.get("certificate").get<picojson::array>();
179 data_list.insert(data_list.end(),
180 certificate_list.begin(),
181 certificate_list.end());
183 if (!v.get("security_origin").is<picojson::null>()) {
184 picojson::array security_origin_list
185 = v.get("security_origin").get<picojson::array>();
186 data_list.insert(data_list.end(),
187 security_origin_list.begin(),
188 security_origin_list.end());
191 for (auto it = data_list.begin(); it != data_list.end(); ++it) {
192 if (!it->is<picojson::object>()) continue;
193 std::string section = it->get("section").to_str();
194 std::string key = it->get("key").to_str();
195 std::string value = it->get("value").to_str();
197 LOGGER(DEBUG) << "INPUT[" << section << "][" << key << "][" << value << "]";
198 Set(section, key, value);
201 LOGGER(DEBUG) << "Migration complete";
203 if (0 != remove(migration_path.c_str())) {
204 LOGGER(ERROR) << "Fail to remove migration file";
209 void SqliteDB::Initialize() {
210 if (app_data_path_.empty()) {
211 LOGGER(ERROR) << "app data path was empty";
214 std::string db_path = app_data_path_ + "/.appdb.db";
215 int ret = sqlite3_open(db_path.c_str(), &sqldb_);
216 if (ret != SQLITE_OK) {
217 LOGGER(ERROR) << "Fail to open app db :" << sqlite3_errmsg(sqldb_);
221 sqlite3_busy_handler(sqldb_, [](void *, int count) {
223 LOGGER(ERROR) << "App db was busy, Wait the lock count(" << count << ")";
224 usleep(100000*(count+1));
227 LOGGER(ERROR) << "App db was busy, Fail to access";
233 ret = sqlite3_exec(sqldb_, kCreateDbQuery, NULL, NULL, &errmsg);
234 if (ret != SQLITE_OK) {
235 LOGGER(ERROR) << "Error to create appdb : " << (errmsg ? errmsg : "");
237 sqlite3_free(errmsg);
242 bool SqliteDB::HasKey(const std::string& section,
243 const std::string& key) const {
245 sqlite3_stmt *stmt = NULL;
249 buffer = sqlite3_mprintf(
250 "select count(*) from appdb where section = %Q and key = %Q",
253 if (buffer == NULL) {
254 LOGGER(ERROR) << "error to make query";
258 std::unique_ptr<char, decltype(sqlite3_free)*>
259 scoped_data {buffer, sqlite3_free};
261 ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
262 if (ret != SQLITE_OK) {
263 LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
267 ret = sqlite3_step(stmt);
268 if (ret == SQLITE_ROW) {
269 int value = sqlite3_column_int(stmt, 0);
273 sqlite3_finalize(stmt);
277 std::string SqliteDB::Get(const std::string& section,
278 const std::string& key) const {
280 sqlite3_stmt *stmt = NULL;
284 buffer = sqlite3_mprintf(
285 "select value from appdb where section = %Q and key = %Q",
288 if (buffer == NULL) {
289 LOGGER(ERROR) << "error to make query";
293 std::unique_ptr<char, decltype(sqlite3_free)*>
294 scoped_data {buffer, sqlite3_free};
296 ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
297 if (ret != SQLITE_OK) {
298 LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
302 ret = sqlite3_step(stmt);
303 if (ret == SQLITE_ROW) {
304 result = std::string(
305 reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
308 sqlite3_finalize(stmt);
312 void SqliteDB::Set(const std::string& section,
313 const std::string& key,
314 const std::string& value) {
316 sqlite3_stmt *stmt = NULL;
319 buffer = sqlite3_mprintf(
320 "replace into appdb (section, key, value) values (?, ?, ?);");
321 if (buffer == NULL) {
322 LOGGER(ERROR) << "error to make query";
326 std::unique_ptr<char, decltype(sqlite3_free)*>
327 scoped_data {buffer, sqlite3_free};
329 ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
330 if (ret != SQLITE_OK) {
331 LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
335 std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*>
336 scoped_stmt {stmt, sqlite3_finalize};
338 ret = sqlite3_bind_text(stmt,
343 if (ret != SQLITE_OK) {
344 LOGGER(ERROR) << "Fail to prepare query bind argument : "
345 << sqlite3_errmsg(sqldb_);
348 ret = sqlite3_bind_text(stmt,
353 if (ret != SQLITE_OK) {
354 LOGGER(ERROR) << "Fail to prepare query bind argument : "
355 << sqlite3_errmsg(sqldb_);
358 ret = sqlite3_bind_text(stmt,
363 if (ret != SQLITE_OK) {
364 LOGGER(ERROR) << "Fail to prepare query bind argument : "
365 << sqlite3_errmsg(sqldb_);
368 ret = sqlite3_step(stmt);
369 if (ret != SQLITE_DONE) {
370 LOGGER(ERROR) << "Fail to insert data : " << sqlite3_errmsg(sqldb_);
374 void SqliteDB::Remove(const std::string& section,
375 const std::string& key) {
378 buffer = sqlite3_mprintf(
379 "delete from appdb where section = %Q and key = %Q",
383 if (buffer == NULL) {
384 LOGGER(ERROR) << "error to make query";
388 std::unique_ptr<char, decltype(sqlite3_free)*>
389 scoped_data {buffer, sqlite3_free};
392 int ret = sqlite3_exec(sqldb_, buffer, NULL, NULL, &errmsg);
393 if (ret != SQLITE_OK) {
394 LOGGER(ERROR) << "Error to delete value : " << (errmsg ? errmsg : "");
396 sqlite3_free(errmsg);
400 void SqliteDB::GetKeys(const std::string& section,
401 std::list<std::string>* keys) const {
403 sqlite3_stmt *stmt = NULL;
406 buffer = sqlite3_mprintf(
407 "select key from appdb where section = %Q",
409 if (buffer == NULL) {
410 LOGGER(ERROR) << "error to make query";
414 std::unique_ptr<char, decltype(sqlite3_free)*>
415 scoped_data {buffer, sqlite3_free};
417 ret = sqlite3_prepare(sqldb_, buffer, strlen(buffer), &stmt, NULL);
418 if (ret != SQLITE_OK) {
419 LOGGER(ERROR) << "Fail to prepare query : " << sqlite3_errmsg(sqldb_);
423 ret = sqlite3_step(stmt);
424 while (ret == SQLITE_ROW) {
426 reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
427 keys->push_back(std::string(value));
428 ret = sqlite3_step(stmt);
431 sqlite3_finalize(stmt);
435 #endif // end of else
437 AppDB* AppDB::GetInstance() {
438 #ifdef USE_APP_PREFERENCE
439 static PreferenceAppDB instance;
441 static SqliteDB instance;
446 } // namespace common