fix(tiering tests): introduce wait until tieting entries num EQ/GT (#2559)

Signed-off-by: adi_holden <adi@dragonflydb.io>
This commit is contained in:
adiholden 2024-02-14 09:59:11 +02:00 committed by GitHub
parent 4afe278487
commit 7b61b4a8fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 69 additions and 55 deletions

View file

@ -330,6 +330,17 @@ void BaseFamilyTest::WaitUntilLocked(DbIndex db_index, string_view key, double t
CHECK(IsLocked(db_index, key));
}
bool BaseFamilyTest::WaitUntilCondition(std::function<bool()> condition_cb,
std::chrono::milliseconds timeout_ms) {
auto step = 50us;
auto timeout_micro = chrono::duration_cast<chrono::microseconds>(timeout_ms);
int64_t steps = timeout_micro.count() / step.count();
do {
ThisFiber::SleepFor(step);
} while (!condition_cb() && --steps > 0);
return condition_cb();
}
RespExpr BaseFamilyTest::Run(ArgSlice list) {
if (!ProactorBase::IsProactorThread()) {
return pp_->at(0)->Await([&] { return this->Run(list); });

View file

@ -17,6 +17,7 @@
namespace dfly {
using namespace facade;
using namespace std;
class TestConnection : public facade::Connection {
public:
@ -124,6 +125,10 @@ class BaseFamilyTest : public ::testing::Test {
// Wait for a locked key to unlock. Aborts after timeout seconds passed.
void WaitUntilLocked(DbIndex db_index, std::string_view key, double timeout = 3);
// Wait until condition_cb returns true or timeout reached. Returns condition_cb value
bool WaitUntilCondition(std::function<bool()> condition_cb,
std::chrono::milliseconds timeout_ms = 100ms);
std::string GetId() const;
size_t SubscriberMessagesLen(std::string_view conn_id) const;

View file

@ -360,6 +360,8 @@ void TieredStorage::Free(PrimeIterator it, DbTableStats* stats) {
}
void TieredStorage::Shutdown() {
VLOG(1) << "Shutdown TieredStorage";
shutdown_ = true;
io_mgr_.Shutdown();
}
@ -372,6 +374,9 @@ TieredStats TieredStorage::GetStats() const {
}
void TieredStorage::FinishIoRequest(int io_res, InflightWriteRequest* req) {
if (shutdown_) {
return;
}
PerDb* db = db_arr_[req->db_index()];
auto& bin_record = db->bin_map[req->bin_index()];
if (io_res < 0) {
@ -574,6 +579,9 @@ void TieredStorage::WriteSingle(DbIndex db_index, PrimeIterator it, size_t blob_
it->second.SetIoPending(true);
auto cb = [this, req, db_index](int io_res) {
if (shutdown_) {
return;
}
PrimeTable* pt = db_slice_.GetTables(db_index).first;
absl::Cleanup cleanup = [this, req]() {

View file

@ -82,6 +82,7 @@ class TieredStorage {
TieredStats stats_;
size_t max_file_size_;
size_t allocated_size_ = 0;
bool shutdown_ = false;
};
} // namespace dfly

View file

@ -27,6 +27,8 @@ class TieredStorageTest : public BaseFamilyTest {
void FillExternalKeys(unsigned count, int val_size = 256);
void FillKeysWithExpire(unsigned count, int val_size = 256, uint32_t expire = 3);
bool WaitUntilTieredEntriesGT(size_t value, int db_index = 0);
bool WaitUntilTieredEntriesEQ(size_t value, int db_index = 0);
static void SetUpTestSuite();
};
@ -43,6 +45,22 @@ void TieredStorageTest::SetUpTestSuite() {
}
}
bool TieredStorageTest::WaitUntilTieredEntriesGT(size_t value, int db_index) {
auto cb = [&, value]() {
auto tiered_entries = GetMetrics().db_stats[db_index].tiered_entries;
return tiered_entries > value;
};
return WaitUntilCondition(std::move(cb));
}
bool TieredStorageTest::WaitUntilTieredEntriesEQ(size_t value, int db_index) {
auto cb = [&, value]() {
auto tiered_entries = GetMetrics().db_stats[db_index].tiered_entries;
return tiered_entries == value;
};
return WaitUntilCondition(std::move(cb));
}
void TieredStorageTest::FillExternalKeys(unsigned count, int val_size) {
string val(val_size, 'a');
@ -75,12 +93,11 @@ TEST_F(TieredStorageTest, Basic) {
FillExternalKeys(5000);
EXPECT_EQ(5000, CheckedInt({"dbsize"}));
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesGT(0));
Metrics m = GetMetrics();
unsigned tiered_entries = m.db_stats[0].tiered_entries;
EXPECT_GT(tiered_entries, 0u);
string resp = CheckedString({"debug", "object", "k1"});
EXPECT_THAT(resp, HasSubstr("spill_len"));
m = GetMetrics();
@ -95,9 +112,8 @@ TEST_F(TieredStorageTest, DelBeforeOffload) {
FillExternalKeys(100);
EXPECT_EQ(100, CheckedInt({"dbsize"}));
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesGT(0));
Metrics m = GetMetrics();
EXPECT_GT(m.db_stats[0].tiered_entries, 0u);
EXPECT_LT(m.db_stats[0].tiered_entries, 100);
for (unsigned i = 0; i < 100; ++i) {
@ -107,9 +123,8 @@ TEST_F(TieredStorageTest, DelBeforeOffload) {
EXPECT_EQ(m.db_stats[0].tiered_entries, 0u);
FillExternalKeys(100);
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesGT(0));
m = GetMetrics();
EXPECT_GT(m.db_stats[0].tiered_entries, 0u);
EXPECT_LT(m.db_stats[0].tiered_entries, 100);
}
@ -121,13 +136,12 @@ TEST_F(TieredStorageTest, AddMultiDb) {
FillExternalKeys(100);
EXPECT_EQ(100, CheckedInt({"dbsize"}));
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesGT(0, 1));
EXPECT_TRUE(WaitUntilTieredEntriesGT(0, 5));
Metrics m = GetMetrics();
EXPECT_GT(m.db_stats[1].tiered_entries, 0u);
EXPECT_LT(m.db_stats[1].tiered_entries, 100);
EXPECT_GT(m.db_stats[5].tiered_entries, 0u);
EXPECT_LT(m.db_stats[4].tiered_entries, 100);
EXPECT_LT(m.db_stats[5].tiered_entries, 100);
}
TEST_F(TieredStorageTest, FlushDBAfterSet) {
@ -142,9 +156,8 @@ TEST_F(TieredStorageTest, FlushDBAfterSet) {
FillExternalKeys(100);
EXPECT_EQ(100, CheckedInt({"dbsize"}));
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesGT(0, 5));
m = GetMetrics();
EXPECT_GT(m.db_stats[5].tiered_entries, 0u);
EXPECT_LT(m.db_stats[5].tiered_entries, 100);
}
@ -160,9 +173,8 @@ TEST_F(TieredStorageTest, FlushAllAfterSet) {
FillExternalKeys(100);
EXPECT_EQ(100, CheckedInt({"dbsize"}));
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesGT(0, 5));
m = GetMetrics();
EXPECT_GT(m.db_stats[5].tiered_entries, 0u);
EXPECT_LT(m.db_stats[5].tiered_entries, 100);
}
@ -177,9 +189,7 @@ TEST_F(TieredStorageTest, AddBigValues) {
FillExternalKeys(100, 5000);
EXPECT_EQ(100, CheckedInt({"dbsize"}));
usleep(20000); // 20 milliseconds
m = GetMetrics();
EXPECT_GT(m.db_stats[0].tiered_entries, 0u);
EXPECT_TRUE(WaitUntilTieredEntriesGT(0));
}
TEST_F(TieredStorageTest, DelBigValues) {
@ -195,26 +205,21 @@ TEST_F(TieredStorageTest, DelBigValues) {
FillExternalKeys(100, 5000);
EXPECT_EQ(100, CheckedInt({"dbsize"}));
usleep(20000); // 20 milliseconds
m = GetMetrics();
EXPECT_GT(m.db_stats[0].tiered_entries, 0u);
EXPECT_TRUE(WaitUntilTieredEntriesGT(0));
}
TEST_F(TieredStorageTest, AddBigValuesWithExpire) {
const int kKeyNum = 10;
FillKeysWithExpire(kKeyNum, 8000);
usleep(20000); // 20 milliseconds
Metrics m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 10);
EXPECT_TRUE(WaitUntilTieredEntriesEQ(10));
for (int i = 0; i < kKeyNum; ++i) {
auto resp = Run({"ttl", StrCat("k", i)});
EXPECT_GT(resp.GetInt(), 0);
}
m = GetMetrics();
Metrics m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 10);
}
@ -222,34 +227,28 @@ TEST_F(TieredStorageTest, AddSmallValuesWithExpire) {
const int kKeyNum = 100;
FillKeysWithExpire(kKeyNum);
usleep(20000); // 20 milliseconds
Metrics m = GetMetrics();
EXPECT_GT(m.db_stats[0].tiered_entries, 0);
EXPECT_TRUE(WaitUntilTieredEntriesGT(0));
for (int i = 0; i < kKeyNum; ++i) {
auto resp = Run({"ttl", StrCat("k", i)});
EXPECT_GT(resp.GetInt(), 0);
}
m = GetMetrics();
Metrics m = GetMetrics();
EXPECT_GT(m.db_stats[0].tiered_entries, 0);
}
TEST_F(TieredStorageTest, SetAndExpire) {
string val(5000, 'a');
Run({"set", "key", val});
usleep(20000); // 20 milliseconds
Metrics m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 1);
EXPECT_TRUE(WaitUntilTieredEntriesEQ(1));
Run({"expire", "key", "3"});
m = GetMetrics();
Metrics m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 1);
Run({"set", "key", val});
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesEQ(0));
m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 0);
Run({"expire", "key", "3"});
}
@ -259,36 +258,30 @@ TEST_F(TieredStorageTest, SetAndGet) {
Run({"set", "key1", val1});
Run({"set", "key2", val1});
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesEQ(2));
Metrics m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 2);
EXPECT_EQ(m.db_stats[0].obj_memory_usage, 0);
EXPECT_EQ(Run({"get", "key1"}), val1);
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesEQ(1));
m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 1);
EXPECT_GT(m.db_stats[0].obj_memory_usage, 0);
Run({"set", "key1", val2});
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesEQ(1));
m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 1);
EXPECT_GT(m.db_stats[0].obj_memory_usage, 0);
Run({"set", "key2", val2});
usleep(20000); // 20 milliseconds
EXPECT_TRUE(WaitUntilTieredEntriesEQ(0));
m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 0);
EXPECT_GT(m.db_stats[0].obj_memory_usage, 0);
EXPECT_EQ(Run({"get", "key1"}), val2);
EXPECT_EQ(Run({"get", "key2"}), val2);
Run({"set", "key3", val1});
usleep(20000); // 20 milliseconds
m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 1);
EXPECT_TRUE(WaitUntilTieredEntriesEQ(1));
Run({"del", "key1"});
Run({"del", "key2"});
@ -304,22 +297,18 @@ TEST_F(TieredStorageTest, GetValueValidation) {
Run({"set", "key1", val1});
Run({"set", "key2", val2});
usleep(20000); // 20 milliseconds
Metrics m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 2);
EXPECT_TRUE(WaitUntilTieredEntriesEQ(2));
EXPECT_EQ(Run({"get", "key1"}), val1);
EXPECT_EQ(Run({"get", "key2"}), val2);
m = GetMetrics();
Metrics m = GetMetrics();
EXPECT_EQ(m.db_stats[0].tiered_entries, 0);
for (unsigned i = 0; i < 100; ++i) {
string val(100, i); // small entries
Run({"set", StrCat("k", i), val});
}
usleep(20000); // 20 milliseconds
m = GetMetrics();
EXPECT_GE(m.db_stats[0].tiered_entries, 0);
EXPECT_TRUE(WaitUntilTieredEntriesGT(0));
for (unsigned i = 0; i < 100; ++i) {
string val(100, i); // small entries