Newer
Older
#include <vereign/kvstore/errors.hh>
#include <vereign/kvstore/lock.hh>
#include <vereign/encoding/binary.hh>
#include <boost/optional.hpp>
#include <vereign/core/lock_guard.hh>
#include <vereign/sqlite/errors.hh>
#include <sqlite3.h>
namespace {
constexpr int createTableRetryCount = 10;
constexpr auto createTableRetrySleep = std::chrono::milliseconds{1000};
}
SqliteStorage::SqliteStorage(const std::string& db_path)
: db_{db_path}
{
kvstore::Lock l{*this, createTableRetryCount, createTableRetrySleep};
db_.Execute(R"(
CREATE TABLE IF NOT EXISTS storage (
key TEXT PRIMARY KEY NOT NULL,
value BLOB
);
)");
}
SqliteStorage::~SqliteStorage() {
if (lock_count_ != 0) {
db_.Commit();
void SqliteStorage::Lock() {
if (lock_count_ != 0) {
lock_count_++;
try {
db_.BeginExplicitTransaction();
lock_count_++;
} catch (const sqlite::Error& err) {
if (err.code() == SQLITE_BUSY) {
throw LockError{};
void SqliteStorage::Unlock() {
if (lock_count_ == 0) {
throw Error{"unexpected call Unlock with non existent lock"};
}
lock_count_--;
if (lock_count_ == 0) {
db_.Commit();
}
void SqliteStorage::DeleteAll() {
kvstore::Lock l{*this};
void SqliteStorage::PutBytes(const std::string& key, bytes::View value) {
auto stmt = db_.Prepare("REPLACE INTO storage(key, value) VALUES(?, ?);");
stmt.BindText(1, key);
stmt.BindBlob(2, value);
stmt.Step();
}
void SqliteStorage::GetBytes(const std::string& key, bytes::Buffer& value) {
auto stmt = db_.Prepare("SELECT value FROM storage WHERE key = ?");
stmt.BindText(1, key);
auto end = stmt.Step();
if (!end) {
value.Write(stmt.GetColumnBlob(0));
}
}
void SqliteStorage::PutInt64(const std::string& key, int64_t value) {
std::array<uint8_t, 8> encoded;
encoding::binary::EncodeUint64(encoded.data(), value);
auto stmt = db_.Prepare("REPLACE INTO storage(key, value) VALUES(?, ?);");
stmt.BindText(1, key);
stmt.BindBlob(2, bytes::View(encoded.data(), 8));
stmt.Step();
}
auto SqliteStorage::GetInt64(const std::string& key) -> int64_t {
auto stmt = db_.Prepare("SELECT value FROM storage WHERE key = ?");
stmt.BindText(1, key);
auto end = stmt.Step();
if (end) {
return 0;
}
auto buf = stmt.GetColumnBlob(0);
if (buf.Size() != 8) {
throw Error("cannot decode bytes size");
}
int64_t result = encoding::binary::DecodeUint64(buf);
return result;
}
} // namespace vereign::kvstore