summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/test/db.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/test/db.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/test/db.cpp512
1 files changed, 342 insertions, 170 deletions
diff --git a/protocols/Telegram/tdlib/td/test/db.cpp b/protocols/Telegram/tdlib/td/test/db.cpp
index 8917dd65b8..61757e9893 100644
--- a/protocols/Telegram/tdlib/td/test/db.cpp
+++ b/protocols/Telegram/tdlib/td/test/db.cpp
@@ -1,17 +1,29 @@
//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
+#include "data.h"
+
#include "td/db/binlog/BinlogHelper.h"
+#include "td/db/binlog/ConcurrentBinlog.h"
#include "td/db/BinlogKeyValue.h"
+#include "td/db/DbKey.h"
#include "td/db/SeqKeyValue.h"
+#include "td/db/SqliteConnectionSafe.h"
+#include "td/db/SqliteDb.h"
#include "td/db/SqliteKeyValue.h"
#include "td/db/SqliteKeyValueSafe.h"
#include "td/db/TsSeqKeyValue.h"
+#include "td/actor/actor.h"
+#include "td/actor/ConcurrentScheduler.h"
+
+#include "td/utils/base64.h"
#include "td/utils/common.h"
+#include "td/utils/filesystem.h"
+#include "td/utils/FlatHashMap.h"
#include "td/utils/logging.h"
#include "td/utils/port/FileFd.h"
#include "td/utils/port/thread.h"
@@ -24,144 +36,239 @@
#include <map>
#include <memory>
-REGISTER_TESTS(db);
-
-using namespace td;
-
template <class ContainerT>
static typename ContainerT::value_type &rand_elem(ContainerT &cont) {
- CHECK(0 < cont.size() && cont.size() <= static_cast<size_t>(std::numeric_limits<int>::max()));
- return cont[Random::fast(0, static_cast<int>(cont.size()) - 1)];
+ CHECK(0 < cont.size() && cont.size() <= static_cast<std::size_t>(std::numeric_limits<int>::max()));
+ return cont[td::Random::fast(0, static_cast<int>(cont.size()) - 1)];
+}
+
+TEST(DB, binlog_encryption_bug) {
+ td::CSlice binlog_name = "test_binlog";
+ td::Binlog::destroy(binlog_name).ignore();
+
+ auto cucumber = td::DbKey::password("cucu'\"mb er");
+ auto empty = td::DbKey::empty();
+ {
+ td::Binlog binlog;
+ binlog
+ .init(
+ binlog_name.str(), [&](const td::BinlogEvent &x) {}, cucumber)
+ .ensure();
+ }
+ {
+ td::Binlog binlog;
+ binlog
+ .init(
+ binlog_name.str(), [&](const td::BinlogEvent &x) {}, cucumber)
+ .ensure();
+ }
}
TEST(DB, binlog_encryption) {
- CSlice binlog_name = "test_binlog";
- Binlog::destroy(binlog_name).ignore();
+ td::CSlice binlog_name = "test_binlog";
+ td::Binlog::destroy(binlog_name).ignore();
- auto hello = DbKey::raw_key(std::string(32, 'A'));
- auto cucumber = DbKey::password("cucumber");
- auto empty = DbKey::empty();
- auto long_data = string(10000, 'Z');
+ auto hello = td::DbKey::raw_key(td::string(32, 'A'));
+ auto cucumber = td::DbKey::password("cucu'\"mb er");
+ auto empty = td::DbKey::empty();
+ auto long_data = td::string(10000, 'Z');
{
- Binlog binlog;
- binlog.init(binlog_name.str(), [](const BinlogEvent &x) {}).ensure();
- binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer("AAAA")));
- binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer("BBBB")));
- binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer(long_data)));
+ td::Binlog binlog;
+ binlog.init(binlog_name.str(), [](const td::BinlogEvent &x) {}).ensure();
+ binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer("AAAA")),
+ td::BinlogDebugInfo{__FILE__, __LINE__});
+ binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer("BBBB")),
+ td::BinlogDebugInfo{__FILE__, __LINE__});
+ binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer(long_data)),
+ td::BinlogDebugInfo{__FILE__, __LINE__});
LOG(INFO) << "SET PASSWORD";
binlog.change_key(cucumber);
binlog.change_key(hello);
LOG(INFO) << "OK";
- binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer("CCCC")));
+ binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer("CCCC")),
+ td::BinlogDebugInfo{__FILE__, __LINE__});
binlog.close().ensure();
}
+ return;
+
auto add_suffix = [&] {
- auto fd = FileFd::open(binlog_name, FileFd::Flags::Write | FileFd::Flags::Append).move_as_ok();
+ auto fd = td::FileFd::open(binlog_name, td::FileFd::Flags::Write | td::FileFd::Flags::Append).move_as_ok();
fd.write("abacabadaba").ensure();
};
add_suffix();
{
- std::vector<string> v;
+ td::vector<td::string> v;
LOG(INFO) << "RESTART";
- Binlog binlog;
- binlog.init(binlog_name.str(), [&](const BinlogEvent &x) { v.push_back(x.data_.str()); }, hello).ensure();
- CHECK(v == std::vector<string>({"AAAA", "BBBB", long_data, "CCCC"}));
+ td::Binlog binlog;
+ binlog
+ .init(
+ binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.data_.str()); }, hello)
+ .ensure();
+ CHECK(v == td::vector<td::string>({"AAAA", "BBBB", long_data, "CCCC"}));
}
add_suffix();
{
- std::vector<string> v;
+ td::vector<td::string> v;
LOG(INFO) << "RESTART";
- Binlog binlog;
- auto status = binlog.init(binlog_name.str(), [&](const BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber);
+ td::Binlog binlog;
+ auto status = binlog.init(
+ binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber);
CHECK(status.is_error());
}
add_suffix();
{
- std::vector<string> v;
+ td::vector<td::string> v;
LOG(INFO) << "RESTART";
- Binlog binlog;
- auto status =
- binlog.init(binlog_name.str(), [&](const BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber, hello);
- CHECK(v == std::vector<string>({"AAAA", "BBBB", long_data, "CCCC"}));
+ td::Binlog binlog;
+ auto status = binlog.init(
+ binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber, hello);
+ CHECK(v == td::vector<td::string>({"AAAA", "BBBB", long_data, "CCCC"}));
}
-};
+}
TEST(DB, sqlite_lfs) {
- string path = "test_sqlite_db";
- SqliteDb::destroy(path).ignore();
- SqliteDb db;
- db.init(path).ensure();
+ td::string path = "test_sqlite_db";
+ td::SqliteDb::destroy(path).ignore();
+ auto db = td::SqliteDb::open_with_key(path, true, td::DbKey::empty()).move_as_ok();
db.exec("PRAGMA journal_mode=WAL").ensure();
db.exec("PRAGMA user_version").ensure();
+ td::SqliteDb::destroy(path).ignore();
}
TEST(DB, sqlite_encryption) {
- string path = "test_sqlite_db";
- SqliteDb::destroy(path).ignore();
+ td::string path = "test_sqlite_db";
+ td::SqliteDb::destroy(path).ignore();
- auto empty = DbKey::empty();
- auto cucumber = DbKey::password("cucumber");
- auto tomato = DbKey::raw_key(string(32, 'a'));
+ auto empty = td::DbKey::empty();
+ auto cucumber = td::DbKey::password("cucu'\"mb er");
+ auto tomato = td::DbKey::raw_key(td::string(32, 'a'));
{
- auto db = SqliteDb::open_with_key(path, empty).move_as_ok();
- db.set_user_version(123);
- auto kv = SqliteKeyValue();
- kv.init_with_connection(db.clone(), "kv");
+ auto db = td::SqliteDb::open_with_key(path, true, empty).move_as_ok();
+ db.set_user_version(123).ensure();
+ auto kv = td::SqliteKeyValue();
+ kv.init_with_connection(db.clone(), "kv").ensure();
kv.set("a", "b");
}
- SqliteDb::open_with_key(path, cucumber).ensure_error(); // key was set...
+ td::SqliteDb::open_with_key(path, false, cucumber).ensure_error();
- SqliteDb::change_key(path, cucumber, empty).ensure();
+ td::SqliteDb::change_key(path, false, cucumber, empty).ensure();
+ td::SqliteDb::change_key(path, false, cucumber, empty).ensure();
- SqliteDb::open_with_key(path, tomato).ensure_error();
+ td::SqliteDb::open_with_key(path, false, tomato).ensure_error();
{
- auto db = SqliteDb::open_with_key(path, cucumber).move_as_ok();
- auto kv = SqliteKeyValue();
- kv.init_with_connection(db.clone(), "kv");
+ auto db = td::SqliteDb::open_with_key(path, false, cucumber).move_as_ok();
+ auto kv = td::SqliteKeyValue();
+ kv.init_with_connection(db.clone(), "kv").ensure();
CHECK(kv.get("a") == "b");
CHECK(db.user_version().ok() == 123);
}
- SqliteDb::change_key(path, tomato, cucumber).ensure();
- SqliteDb::change_key(path, tomato, cucumber).ensure();
+ td::SqliteDb::change_key(path, false, tomato, cucumber).ensure();
+ td::SqliteDb::change_key(path, false, tomato, cucumber).ensure();
- SqliteDb::open_with_key(path, cucumber).ensure_error();
+ td::SqliteDb::open_with_key(path, false, cucumber).ensure_error();
{
- auto db = SqliteDb::open_with_key(path, tomato).move_as_ok();
- auto kv = SqliteKeyValue();
- kv.init_with_connection(db.clone(), "kv");
+ auto db = td::SqliteDb::open_with_key(path, false, tomato).move_as_ok();
+ auto kv = td::SqliteKeyValue();
+ kv.init_with_connection(db.clone(), "kv").ensure();
CHECK(kv.get("a") == "b");
CHECK(db.user_version().ok() == 123);
}
- SqliteDb::change_key(path, empty, tomato).ensure();
- SqliteDb::change_key(path, empty, tomato).ensure();
+ td::SqliteDb::change_key(path, false, empty, tomato).ensure();
+ td::SqliteDb::change_key(path, false, empty, tomato).ensure();
{
- auto db = SqliteDb::open_with_key(path, empty).move_as_ok();
- auto kv = SqliteKeyValue();
- kv.init_with_connection(db.clone(), "kv");
+ auto db = td::SqliteDb::open_with_key(path, false, empty).move_as_ok();
+ auto kv = td::SqliteKeyValue();
+ kv.init_with_connection(db.clone(), "kv").ensure();
CHECK(kv.get("a") == "b");
CHECK(db.user_version().ok() == 123);
}
- SqliteDb::open_with_key(path, cucumber).ensure_error();
+ td::SqliteDb::open_with_key(path, false, cucumber).ensure_error();
+ td::SqliteDb::destroy(path).ignore();
+}
+
+TEST(DB, sqlite_encryption_migrate_v3) {
+ td::string path = "test_sqlite_db";
+ td::SqliteDb::destroy(path).ignore();
+ auto cucumber = td::DbKey::password("cucumber");
+ auto empty = td::DbKey::empty();
+ if (false) {
+ // sqlite_sample_db was generated by the following code using SQLCipher based on SQLite 3.15.2
+ {
+ auto db = td::SqliteDb::change_key(path, true, cucumber, empty).move_as_ok();
+ db.set_user_version(123).ensure();
+ auto kv = td::SqliteKeyValue();
+ kv.init_with_connection(db.clone(), "kv").ensure();
+ kv.set("hello", "world");
+ }
+ LOG(ERROR) << td::base64_encode(td::read_file(path).move_as_ok());
+ }
+ td::write_file(path, td::base64_decode(td::Slice(sqlite_sample_db_v3, sqlite_sample_db_v3_size)).move_as_ok())
+ .ensure();
+ {
+ auto db = td::SqliteDb::open_with_key(path, true, cucumber).move_as_ok();
+ auto kv = td::SqliteKeyValue();
+ kv.init_with_connection(db.clone(), "kv").ensure();
+ CHECK(kv.get("hello") == "world");
+ CHECK(db.user_version().ok() == 123);
+ }
+ td::SqliteDb::destroy(path).ignore();
+}
+
+TEST(DB, sqlite_encryption_migrate_v4) {
+ td::string path = "test_sqlite_db";
+ td::SqliteDb::destroy(path).ignore();
+ auto cucumber = td::DbKey::password("cucu'\"mb er");
+ auto empty = td::DbKey::empty();
+ if (false) {
+ // sqlite_sample_db was generated by the following code using SQLCipher 4.4.0
+ {
+ auto db = td::SqliteDb::change_key(path, true, cucumber, empty).move_as_ok();
+ db.set_user_version(123).ensure();
+ auto kv = td::SqliteKeyValue();
+ kv.init_with_connection(db.clone(), "kv").ensure();
+ kv.set("hello", "world");
+ }
+ LOG(ERROR) << td::base64_encode(td::read_file(path).move_as_ok());
+ }
+ td::write_file(path, td::base64_decode(td::Slice(sqlite_sample_db_v4, sqlite_sample_db_v4_size)).move_as_ok())
+ .ensure();
+ {
+ auto r_db = td::SqliteDb::open_with_key(path, true, cucumber);
+ if (r_db.is_error()) {
+ LOG(ERROR) << r_db.error();
+ return;
+ }
+ auto db = r_db.move_as_ok();
+ auto kv = td::SqliteKeyValue();
+ auto status = kv.init_with_connection(db.clone(), "kv");
+ if (status.is_error()) {
+ LOG(ERROR) << status;
+ } else {
+ CHECK(kv.get("hello") == "world");
+ CHECK(db.user_version().ok() == 123);
+ }
+ }
+ td::SqliteDb::destroy(path).ignore();
}
-using SeqNo = uint64;
+using SeqNo = td::uint64;
struct DbQuery {
- enum Type { Get, Set, Erase } type;
+ enum class Type { Get, Set, Erase } type = Type::Get;
SeqNo tid = 0;
- int32 id = 0;
- string key;
- string value;
+ td::int32 id = 0;
+ td::string key;
+ td::string value;
};
template <class ImplT>
@@ -172,13 +279,39 @@ class QueryHandler {
}
void do_query(DbQuery &query) {
switch (query.type) {
- case DbQuery::Get:
+ case DbQuery::Type::Get:
+ query.value = impl_.get(query.key);
+ return;
+ case DbQuery::Type::Set:
+ impl_.set(query.key, query.value);
+ query.tid = 1;
+ return;
+ case DbQuery::Type::Erase:
+ impl_.erase(query.key);
+ query.tid = 1;
+ return;
+ }
+ }
+
+ private:
+ ImplT impl_;
+};
+
+template <class ImplT>
+class SeqQueryHandler {
+ public:
+ ImplT &impl() {
+ return impl_;
+ }
+ void do_query(DbQuery &query) {
+ switch (query.type) {
+ case DbQuery::Type::Get:
query.value = impl_.get(query.key);
return;
- case DbQuery::Set:
+ case DbQuery::Type::Set:
query.tid = impl_.set(query.key, query.value);
return;
- case DbQuery::Erase:
+ case DbQuery::Type::Erase:
query.tid = impl_.erase(query.key);
return;
}
@@ -190,93 +323,93 @@ class QueryHandler {
class SqliteKV {
public:
- string get(string key) {
+ td::string get(const td::string &key) {
return kv_->get().get(key);
}
- SeqNo set(string key, string value) {
+ SeqNo set(const td::string &key, const td::string &value) {
kv_->get().set(key, value);
return 0;
}
- SeqNo erase(string key) {
+ SeqNo erase(const td::string &key) {
kv_->get().erase(key);
return 0;
}
- Status init(string name) {
- auto sql_connection = std::make_shared<SqliteConnectionSafe>(name);
- kv_ = std::make_shared<SqliteKeyValueSafe>("kv", sql_connection);
- return Status::OK();
+ td::Status init(const td::string &name) {
+ auto sql_connection = std::make_shared<td::SqliteConnectionSafe>(name, td::DbKey::empty());
+ kv_ = std::make_shared<td::SqliteKeyValueSafe>("kv", sql_connection);
+ return td::Status::OK();
}
void close() {
kv_.reset();
}
private:
- std::shared_ptr<SqliteKeyValueSafe> kv_;
+ std::shared_ptr<td::SqliteKeyValueSafe> kv_;
};
class BaselineKV {
public:
- string get(string key) {
+ td::string get(const td::string &key) {
return map_[key];
}
- SeqNo set(string key, string value) {
- map_[key] = value;
+ SeqNo set(const td::string &key, td::string value) {
+ map_[key] = std::move(value);
return ++current_tid_;
}
- SeqNo erase(string key) {
+ SeqNo erase(const td::string &key) {
map_.erase(key);
return ++current_tid_;
}
private:
- std::map<string, string> map_;
+ std::map<td::string, td::string> map_;
SeqNo current_tid_ = 0;
};
TEST(DB, key_value) {
- SET_VERBOSITY_LEVEL(VERBOSITY_NAME(INFO));
- std::vector<std::string> keys;
- std::vector<std::string> values;
+ td::vector<td::string> keys;
+ td::vector<td::string> values;
for (int i = 0; i < 100; i++) {
- keys.push_back(rand_string('a', 'b', Random::fast(1, 10)));
+ keys.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
}
- for (int i = 0; i < 1000; i++) {
- values.push_back(rand_string('a', 'b', Random::fast(1, 10)));
+ for (int i = 0; i < 10; i++) {
+ values.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
}
- int queries_n = 300000;
- std::vector<DbQuery> queries(queries_n);
+ int queries_n = 1000;
+ td::vector<DbQuery> queries(queries_n);
for (auto &q : queries) {
- int op = Random::fast(0, 2);
+ int op = td::Random::fast(0, 2);
const auto &key = rand_elem(keys);
const auto &value = rand_elem(values);
if (op == 0) {
- q.type = DbQuery::Get;
+ q.type = DbQuery::Type::Get;
q.key = key;
} else if (op == 1) {
- q.type = DbQuery::Erase;
+ q.type = DbQuery::Type::Erase;
q.key = key;
} else if (op == 2) {
- q.type = DbQuery::Set;
+ q.type = DbQuery::Type::Set;
q.key = key;
q.value = value;
}
}
QueryHandler<BaselineKV> baseline;
- QueryHandler<SeqKeyValue> kv;
- QueryHandler<TsSeqKeyValue> ts_kv;
- QueryHandler<BinlogKeyValue<Binlog>> new_kv;
+ QueryHandler<td::SeqKeyValue> kv;
+ QueryHandler<td::TsSeqKeyValue> ts_kv;
+ QueryHandler<td::BinlogKeyValue<td::Binlog>> new_kv;
- CSlice new_kv_name = "test_new_kv";
- Binlog::destroy(new_kv_name).ignore();
+ td::CSlice new_kv_name = "test_new_kv";
+ td::Binlog::destroy(new_kv_name).ignore();
new_kv.impl().init(new_kv_name.str()).ensure();
- QueryHandler<SqliteKeyValue> sqlite_kv;
- CSlice name = "test_sqlite_kv";
- SqliteDb::destroy(name).ignore();
- sqlite_kv.impl().init(name.str()).ensure();
+ QueryHandler<td::SqliteKeyValue> sqlite_kv;
+ td::CSlice path = "test_sqlite_kv";
+ td::SqliteDb::destroy(path).ignore();
+ auto db = td::SqliteDb::open_with_key(path, true, td::DbKey::empty()).move_as_ok();
+ sqlite_kv.impl().init_with_connection(std::move(db), "KV").ensure();
int cnt = 0;
for (auto &q : queries) {
@@ -294,41 +427,82 @@ TEST(DB, key_value) {
ASSERT_EQ(a.value, c.value);
ASSERT_EQ(a.value, d.value);
ASSERT_EQ(a.value, e.value);
- if (cnt++ % 10000 == 0) {
+ if (cnt++ % 200 == 0) {
new_kv.impl().init(new_kv_name.str()).ensure();
}
}
+ td::SqliteDb::destroy(path).ignore();
+ td::Binlog::destroy(new_kv_name).ignore();
+}
+
+TEST(DB, key_value_set_all) {
+ td::vector<td::string> keys;
+ td::vector<td::string> values;
+
+ for (int i = 0; i < 100; i++) {
+ keys.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
+ }
+ for (int i = 0; i < 10; i++) {
+ values.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
+ }
+
+ td::SqliteKeyValue sqlite_kv;
+ td::CSlice sqlite_kv_name = "test_sqlite_kv";
+ td::SqliteDb::destroy(sqlite_kv_name).ignore();
+ auto db = td::SqliteDb::open_with_key(sqlite_kv_name, true, td::DbKey::empty()).move_as_ok();
+ sqlite_kv.init_with_connection(std::move(db), "KV").ensure();
+
+ BaselineKV kv;
+
+ int queries_n = 100;
+ while (queries_n-- > 0) {
+ int cnt = td::Random::fast(0, 10);
+ td::FlatHashMap<td::string, td::string> key_values;
+ for (int i = 0; i < cnt; i++) {
+ auto key = rand_elem(keys);
+ auto value = rand_elem(values);
+ key_values[key] = value;
+ kv.set(key, value);
+ }
+
+ sqlite_kv.set_all(key_values);
+
+ for (auto &key : keys) {
+ CHECK(kv.get(key) == sqlite_kv.get(key));
+ }
+ }
+ td::SqliteDb::destroy(sqlite_kv_name).ignore();
}
-TEST(DB, thread_key_value) {
#if !TD_THREAD_UNSUPPORTED
- std::vector<std::string> keys;
- std::vector<std::string> values;
+TEST(DB, thread_key_value) {
+ td::vector<td::string> keys;
+ td::vector<td::string> values;
for (int i = 0; i < 100; i++) {
- keys.push_back(rand_string('a', 'b', Random::fast(1, 10)));
+ keys.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
}
for (int i = 0; i < 1000; i++) {
- values.push_back(rand_string('a', 'b', Random::fast(1, 10)));
+ values.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
}
int threads_n = 4;
- int queries_n = 100000;
+ int queries_n = 10000;
- std::vector<std::vector<DbQuery>> queries(threads_n, std::vector<DbQuery>(queries_n));
+ td::vector<td::vector<DbQuery>> queries(threads_n, td::vector<DbQuery>(queries_n));
for (auto &qs : queries) {
for (auto &q : qs) {
- int op = Random::fast(0, 10);
+ int op = td::Random::fast(0, 10);
const auto &key = rand_elem(keys);
const auto &value = rand_elem(values);
if (op > 1) {
- q.type = DbQuery::Get;
+ q.type = DbQuery::Type::Get;
q.key = key;
} else if (op == 0) {
- q.type = DbQuery::Erase;
+ q.type = DbQuery::Type::Erase;
q.key = key;
} else if (op == 1) {
- q.type = DbQuery::Set;
+ q.type = DbQuery::Type::Set;
q.key = key;
q.value = value;
}
@@ -336,12 +510,12 @@ TEST(DB, thread_key_value) {
}
QueryHandler<BaselineKV> baseline;
- QueryHandler<TsSeqKeyValue> ts_kv;
+ SeqQueryHandler<td::TsSeqKeyValue> ts_kv;
- std::vector<thread> threads(threads_n);
- std::vector<std::vector<DbQuery>> res(threads_n);
+ td::vector<td::thread> threads(threads_n);
+ td::vector<td::vector<DbQuery>> res(threads_n);
for (int i = 0; i < threads_n; i++) {
- threads[i] = thread([&ts_kv, &queries, &res, i]() {
+ threads[i] = td::thread([&ts_kv, &queries, &res, i] {
for (auto q : queries[i]) {
ts_kv.do_query(q);
res[i].push_back(q);
@@ -352,7 +526,7 @@ TEST(DB, thread_key_value) {
thread.join();
}
- std::vector<std::size_t> pos(threads_n);
+ td::vector<std::size_t> pos(threads_n);
while (true) {
bool was = false;
for (int i = 0; i < threads_n; i++) {
@@ -362,7 +536,7 @@ TEST(DB, thread_key_value) {
}
auto &q = res[i][p];
if (q.tid == 0) {
- if (q.type == DbQuery::Get) {
+ if (q.type == DbQuery::Type::Get) {
auto nq = q;
baseline.do_query(nq);
if (nq.value == q.value) {
@@ -402,25 +576,23 @@ TEST(DB, thread_key_value) {
baseline.do_query(res[best][pos[best]]);
pos[best]++;
}
-#endif
}
+#endif
TEST(DB, persistent_key_value) {
- using KeyValue = BinlogKeyValue<ConcurrentBinlog>;
- // using KeyValue = PersistentKeyValue;
- // using KeyValue = SqliteKV;
- SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING));
- std::vector<std::string> keys;
- std::vector<std::string> values;
- CSlice name = "test_pmc";
- Binlog::destroy(name).ignore();
- SqliteDb::destroy(name).ignore();
+ using KeyValue = td::BinlogKeyValue<td::ConcurrentBinlog>;
+ // using KeyValue = td::SqliteKeyValue;
+ td::vector<td::string> keys;
+ td::vector<td::string> values;
+ td::CSlice path = "test_pmc";
+ td::Binlog::destroy(path).ignore();
+ td::SqliteDb::destroy(path).ignore();
for (int i = 0; i < 100; i++) {
- keys.push_back(rand_string('a', 'b', Random::fast(1, 10)));
+ keys.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
}
for (int i = 0; i < 1000; i++) {
- values.push_back(rand_string('a', 'b', Random::fast(1, 10)));
+ values.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
}
QueryHandler<BaselineKV> baseline;
@@ -429,34 +601,34 @@ TEST(DB, persistent_key_value) {
int threads_n = 4;
int queries_n = 3000 / threads_n;
- std::vector<std::vector<DbQuery>> queries(threads_n, std::vector<DbQuery>(queries_n));
+ td::vector<td::vector<DbQuery>> queries(threads_n, td::vector<DbQuery>(queries_n));
for (auto &qs : queries) {
for (auto &q : qs) {
- int op = Random::fast(0, 10);
+ int op = td::Random::fast(0, 10);
const auto &key = rand_elem(keys);
const auto &value = rand_elem(values);
if (op > 1) {
- q.type = DbQuery::Get;
+ q.type = DbQuery::Type::Get;
q.key = key;
} else if (op == 0) {
- q.type = DbQuery::Erase;
+ q.type = DbQuery::Type::Erase;
q.key = key;
} else if (op == 1) {
- q.type = DbQuery::Set;
+ q.type = DbQuery::Type::Set;
q.key = key;
q.value = value;
}
}
}
- std::vector<std::vector<DbQuery>> res(threads_n);
- class Worker : public Actor {
+ td::vector<td::vector<DbQuery>> res(threads_n);
+ class Worker final : public td::Actor {
public:
- Worker(ActorShared<> parent, std::shared_ptr<QueryHandler<KeyValue>> kv, const std::vector<DbQuery> *queries,
- std::vector<DbQuery> *res)
+ Worker(td::ActorShared<> parent, std::shared_ptr<SeqQueryHandler<KeyValue>> kv,
+ const td::vector<DbQuery> *queries, td::vector<DbQuery> *res)
: parent_(std::move(parent)), kv_(std::move(kv)), queries_(queries), res_(res) {
}
- void loop() override {
+ void loop() final {
for (auto q : *queries_) {
kv_->do_query(q);
res_->push_back(q);
@@ -465,55 +637,54 @@ TEST(DB, persistent_key_value) {
}
private:
- ActorShared<> parent_;
- std::shared_ptr<QueryHandler<KeyValue>> kv_;
- const std::vector<DbQuery> *queries_;
- std::vector<DbQuery> *res_;
+ td::ActorShared<> parent_;
+ std::shared_ptr<SeqQueryHandler<KeyValue>> kv_;
+ const td::vector<DbQuery> *queries_;
+ td::vector<DbQuery> *res_;
};
- class Main : public Actor {
+ class Main final : public td::Actor {
public:
- Main(int threads_n, const std::vector<std::vector<DbQuery>> *queries, std::vector<std::vector<DbQuery>> *res)
- : threads_n_(threads_n), queries_(queries), res_(res) {
+ Main(int threads_n, const td::vector<td::vector<DbQuery>> *queries, td::vector<td::vector<DbQuery>> *res)
+ : threads_n_(threads_n), queries_(queries), res_(res), ref_cnt_(threads_n) {
}
- void start_up() override {
- LOG(INFO) << "start_up";
+ void start_up() final {
+ LOG(INFO) << "Start up";
kv_->impl().init("test_pmc").ensure();
- ref_cnt_ = threads_n_;
for (int i = 0; i < threads_n_; i++) {
- create_actor_on_scheduler<Worker>("Worker", i + 1, actor_shared(this, 2), kv_, &queries_->at(i), &res_->at(i))
+ td::create_actor_on_scheduler<Worker>("Worker", i + 1, actor_shared(this, 2), kv_, &queries_->at(i),
+ &res_->at(i))
.release();
}
}
- void tear_down() override {
- LOG(INFO) << "tear_down";
+ void tear_down() final {
+ LOG(INFO) << "Tear down";
// kv_->impl().close();
}
- void hangup_shared() override {
- LOG(INFO) << "hangup";
+ void hangup_shared() final {
+ LOG(INFO) << "Hang up";
ref_cnt_--;
if (ref_cnt_ == 0) {
kv_->impl().close();
- Scheduler::instance()->finish();
+ td::Scheduler::instance()->finish();
stop();
}
}
- void hangup() override {
+ void hangup() final {
LOG(ERROR) << "BAD HANGUP";
}
private:
int threads_n_;
- const std::vector<std::vector<DbQuery>> *queries_;
- std::vector<std::vector<DbQuery>> *res_;
+ const td::vector<td::vector<DbQuery>> *queries_;
+ td::vector<td::vector<DbQuery>> *res_;
- std::shared_ptr<QueryHandler<KeyValue>> kv_{new QueryHandler<KeyValue>()};
+ std::shared_ptr<SeqQueryHandler<KeyValue>> kv_{new SeqQueryHandler<KeyValue>()};
int ref_cnt_;
};
- ConcurrentScheduler sched;
- sched.init(threads_n);
+ td::ConcurrentScheduler sched(threads_n, 0);
sched.create_actor_unsafe<Main>(0, "Main", threads_n, &queries, &res).release();
sched.start();
while (sched.run_main(10)) {
@@ -521,7 +692,7 @@ TEST(DB, persistent_key_value) {
}
sched.finish();
- std::vector<std::size_t> pos(threads_n);
+ td::vector<std::size_t> pos(threads_n);
while (true) {
bool was = false;
for (int i = 0; i < threads_n; i++) {
@@ -531,7 +702,7 @@ TEST(DB, persistent_key_value) {
}
auto &q = res[i][p];
if (q.tid == 0) {
- if (q.type == DbQuery::Get) {
+ if (q.type == DbQuery::Type::Get) {
auto nq = q;
baseline.do_query(nq);
if (nq.value == q.value) {
@@ -572,4 +743,5 @@ TEST(DB, persistent_key_value) {
pos[best]++;
}
}
+ td::SqliteDb::destroy(path).ignore();
}