#include <utility>
#include <vector>
+#include <database.hpp>
#include <shared-queue.hpp>
#include "lib/amd_api.h"
class Cursor {
public:
- Cursor(sqlite3* db, const std::string& query,
- const std::vector<std::string>& bind_text) {
- sqlite3_stmt* stmt;
- int ret = sqlite3_prepare_v2(db, query.c_str(), query.length(), &stmt,
- nullptr);
- auto stmt_auto = std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*>(
- stmt, sqlite3_finalize);
- if (ret != SQLITE_OK) {
- _E("sqlite3_prepare_v2() is failed. error(%s:%d)",
- sqlite3_errmsg(db), ret);
- THROW(-ret);
+ Cursor(tizen_base::Database db, const std::string& query,
+ const std::vector<std::string>& bind_text)
+ : db_(std::move(db)), sql_(tizen_base::Database::Sql(query)) {
+ for (auto& text : bind_text) {
+ sql_.Bind(text);
}
-
- int index = 1;
- for (auto const& text : bind_text) {
- ret = sqlite3_bind_text(stmt, index++, text.c_str(), -1,
- SQLITE_TRANSIENT);
- if (ret != SQLITE_OK) {
- _E("sqlite3_bind_text() is failed. index(%d), error(%s:%d)",
- index - 1, sqlite3_errmsg(db), ret);
- THROW(-ret);
- }
- }
-
- stmt_ = stmt_auto.release();
}
- ~Cursor() {
- if (stmt_ != nullptr)
- sqlite3_finalize(stmt_);
- }
+ ~Cursor() = default;
Cursor(const Cursor&) = delete;
Cursor& operator=(const Cursor&) = delete;
void Next() {
- int ret = sqlite3_step(stmt_);
- if (ret == SQLITE_ROW)
- return;
-
- if (ret == SQLITE_DONE)
- _D("SQLITE_DONE");
- else if (ret == SQLITE_BUSY)
- _E("SQLITE_BUSY");
- else if (ret == SQLITE_ERROR)
- _E("SQLITE_ERROR");
- else if (ret == SQLITE_MISUSE)
- _E("SQLITE_MISUSE");
-
- done_ = true;
+ ++iter_;
+ if (!(iter_ != result_.end())) {
+ done_ = true;
+ }
}
bool IsDone() const {
}
bool Execute() {
- int ret = sqlite3_step(stmt_);
- if (ret != SQLITE_DONE) {
- if (ret != SQLITE_ROW) {
- _E("sqlite3_step() is failed. error(%d)", ret);
- done_ = true;
- }
+ result_ = db_.Exec(sql_);
+ iter_ = result_.begin();
- return false;
- }
+ if (!(iter_ != result_.end()))
+ done_ = true;
- done_ = true;
- return true;
+ return static_cast<bool>(result_);
}
const char* GetColumn(int index) {
- return reinterpret_cast<const char*>(sqlite3_column_text(stmt_, index));
+ return reinterpret_cast<const char*>(sqlite3_column_text(result_.GetRaw(), index));
}
private:
- sqlite3_stmt* stmt_ = nullptr;
+ tizen_base::Database db_;
+ tizen_base::Database::Sql sql_;
+ tizen_base::Database::Result result_;
+ tizen_base::Database::Result::Iterator iter_ = tizen_base::Database::Result::Iterator(nullptr);
bool done_ = false;
};
amd_database_query_cb cb, void* user_data, bool sync) {
if (sync) {
try {
- amd::Database db(PATH_AMD_DB);
- db.Open(SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE);
- auto cursor = std::make_unique<Cursor>(db.GetHandle(),
- std::move(query), std::move(bind_text));
+ tizen_base::Database db(PATH_AMD_DB,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE);
+ auto cursor = std::make_unique<Cursor>(std::move(db), std::move(query),
+ std::move(bind_text));
return cb(cursor.get(), user_data);
} catch (const amd::Exception& e) {
_E("Exception(%d) occurs", e.GetErrorCode());
if (!disposed_)
return;
- db_.reset(new amd::Database(PATH_AMD_DB));
- thread_ = std::thread([&]{
- SetComm("DBWriter+");
- do {
- auto job = queue_.WaitAndPop();
- if (job.IsDone())
- break;
-
- try {
- db_->Open(SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE);
- } catch (const amd::Exception& e) {
- _E("Open() is failed. error(%d)", e.GetErrorCode());
- continue;
- }
-
- db_->BeginTransaction();
-
- std::unique_ptr<Cursor> cursor;
- try {
- cursor = std::make_unique<Cursor>(db_->GetHandle(),
- job.GetQuery(), job.GetBindText());
- } catch (const amd::Exception& e) {
- _E("Failed to create Cursor. error(%s)", e.what());
- db_->EndTransaction();
- db_->Close();
- queue_.Push(std::move(job));
- continue;
- }
-
+ thread_ = std::thread([&] {
+ SetComm("DBWriter+");
+ int retry = 0;
+ do {
+ auto job = queue_.WaitAndPop();
+ if (job.IsDone())
+ break;
+
+ try {
+ tizen_base::Database db(PATH_AMD_DB,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE);
+
+ std::unique_ptr<Cursor> cursor;
+ {
+ auto guard = db.CreateTransactionGuard();
+ cursor = std::make_unique<Cursor>(std::move(db), job.GetQuery(),
+ job.GetBindText());
int ret = job.Invoke(cursor.get());
- if (ret != 0)
- db_->Rollback();
-
- db_->EndTransaction();
- db_->Close();
- } while (true);
- });
+ if (ret == 0)
+ guard.Commit();
+ }
+ retry = 0;
+ } catch (const std::exception& e) {
+ _E("Failed to execute a job: %s", e.what());
+ retry++;
+ if (retry < 5) {
+ _W("retry(%d)", retry);
+ queue_.Push(std::move(job));
+ }
+ }
+ } while (true);
+ });
disposed_ = false;
}
timer_ = 0;
}
- db_->Close();
+ queue_.Push(Job(true));
+ thread_.join();
disposed_ = true;
}
private:
bool disposed_ = true;
- std::unique_ptr<amd::Database> db_;
std::thread thread_;
tizen_base::SharedQueue<Job> queue_;
guint timer_ = 0;
auto* h = static_cast<Cursor*>(cursor);
*value = h->GetColumn(index);
- return 0;
+ return *value == nullptr ? -1 : 0;
}
extern "C" EXPORT_API int amd_database_execute(const char* query,