mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-26 16:30:56 +00:00
00ee89b584
Summary: There are some tricky behaviors related to WAL sync: - When creating a WAL, the WAL might not be synced, if the WAL directory is not synced, the WAL file's metadata may not even be synced to disk, so during recovery, when listing the WAL directory, the WAL may not even show up. - During each DB::Write, the WriteOption can control whether the WAL should be synced, so a WAL previously not synced on creation can be synced during Write. For each `SyncWAL`, we'll track the synced status and the current WAL size. Previously, we only track the WAL size on closing. During recovery, we check that the on-disk WAL size is >= the last synced size. So this PR introduces `synced_size` and `closed` to `WalMetadata` for the above design update. Pull Request resolved: https://github.com/facebook/rocksdb/pull/7414 Test Plan: - updated wal_edit_test - updated version_edit_test Reviewed By: riversand963 Differential Revision: D23796127 Pulled By: cheng-chang fbshipit-source-id: 5498ab80f537c48a10157e71a4745716aef5cf30
141 lines
4.2 KiB
C++
141 lines
4.2 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
#include "db/wal_edit.h"
|
|
|
|
#include "port/port.h"
|
|
#include "port/stack_trace.h"
|
|
#include "test_util/testharness.h"
|
|
#include "test_util/testutil.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
TEST(WalSet, AddDeleteReset) {
|
|
WalSet wals;
|
|
ASSERT_TRUE(wals.GetWals().empty());
|
|
|
|
// Create WAL 1 - 10.
|
|
for (WalNumber log_number = 1; log_number <= 10; log_number++) {
|
|
wals.AddWal(WalAddition(log_number));
|
|
}
|
|
ASSERT_EQ(wals.GetWals().size(), 10);
|
|
|
|
// Close WAL 1 - 5.
|
|
for (WalNumber log_number = 1; log_number <= 5; log_number++) {
|
|
WalMetadata wal(100);
|
|
wal.SetClosed();
|
|
wals.AddWal(WalAddition(log_number, wal));
|
|
}
|
|
ASSERT_EQ(wals.GetWals().size(), 10);
|
|
|
|
// Delete WAL 1 - 5.
|
|
for (WalNumber log_number = 1; log_number <= 5; log_number++) {
|
|
wals.DeleteWal(WalDeletion(log_number));
|
|
}
|
|
ASSERT_EQ(wals.GetWals().size(), 5);
|
|
|
|
WalNumber expected_log_number = 6;
|
|
for (auto it : wals.GetWals()) {
|
|
WalNumber log_number = it.first;
|
|
ASSERT_EQ(log_number, expected_log_number++);
|
|
}
|
|
|
|
wals.Reset();
|
|
ASSERT_TRUE(wals.GetWals().empty());
|
|
}
|
|
|
|
TEST(WalSet, Overwrite) {
|
|
constexpr WalNumber kNumber = 100;
|
|
constexpr uint64_t kBytes = 200;
|
|
WalSet wals;
|
|
wals.AddWal(WalAddition(kNumber));
|
|
ASSERT_FALSE(wals.GetWals().at(kNumber).HasSyncedSize());
|
|
wals.AddWal(WalAddition(kNumber, WalMetadata(kBytes)));
|
|
ASSERT_TRUE(wals.GetWals().at(kNumber).HasSyncedSize());
|
|
ASSERT_EQ(wals.GetWals().at(kNumber).GetSyncedSizeInBytes(), kBytes);
|
|
}
|
|
|
|
TEST(WalSet, SmallerSyncedSize) {
|
|
constexpr WalNumber kNumber = 100;
|
|
constexpr uint64_t kBytes = 100;
|
|
WalSet wals;
|
|
ASSERT_OK(wals.AddWal(WalAddition(kNumber, WalMetadata(kBytes))));
|
|
Status s = wals.AddWal(WalAddition(kNumber, WalMetadata(0)));
|
|
ASSERT_TRUE(s.IsCorruption());
|
|
ASSERT_TRUE(
|
|
s.ToString().find(
|
|
"WAL 100 must not have smaller synced size than previous one") !=
|
|
std::string::npos);
|
|
}
|
|
|
|
TEST(WalSet, CloseTwice) {
|
|
constexpr WalNumber kNumber = 100;
|
|
constexpr uint64_t kBytes = 200;
|
|
WalSet wals;
|
|
ASSERT_OK(wals.AddWal(WalAddition(kNumber)));
|
|
WalMetadata wal(kBytes);
|
|
wal.SetClosed();
|
|
ASSERT_OK(wals.AddWal(WalAddition(kNumber, wal)));
|
|
Status s = wals.AddWal(WalAddition(kNumber, wal));
|
|
ASSERT_TRUE(s.IsCorruption());
|
|
ASSERT_TRUE(s.ToString().find("WAL 100 is closed more than once") !=
|
|
std::string::npos);
|
|
}
|
|
|
|
TEST(WalSet, CloseBeforeCreate) {
|
|
constexpr WalNumber kNumber = 100;
|
|
constexpr uint64_t kBytes = 200;
|
|
WalSet wals;
|
|
WalMetadata wal(kBytes);
|
|
wal.SetClosed();
|
|
Status s = wals.AddWal(WalAddition(kNumber, wal));
|
|
ASSERT_TRUE(s.IsCorruption());
|
|
ASSERT_TRUE(s.ToString().find("WAL 100 is not created before closing") !=
|
|
std::string::npos);
|
|
}
|
|
|
|
TEST(WalSet, CreateAfterClose) {
|
|
constexpr WalNumber kNumber = 100;
|
|
constexpr uint64_t kBytes = 200;
|
|
WalSet wals;
|
|
ASSERT_OK(wals.AddWal(WalAddition(kNumber)));
|
|
WalMetadata wal(kBytes);
|
|
wal.SetClosed();
|
|
ASSERT_OK(wals.AddWal(WalAddition(kNumber, wal)));
|
|
Status s = wals.AddWal(WalAddition(kNumber));
|
|
ASSERT_TRUE(s.IsCorruption());
|
|
ASSERT_TRUE(
|
|
s.ToString().find(
|
|
"WAL 100 must not have smaller synced size than previous one") !=
|
|
std::string::npos);
|
|
}
|
|
|
|
TEST(WalSet, DeleteNonExistingWal) {
|
|
constexpr WalNumber kNonExistingNumber = 100;
|
|
WalSet wals;
|
|
Status s = wals.DeleteWal(WalDeletion(kNonExistingNumber));
|
|
ASSERT_TRUE(s.IsCorruption());
|
|
ASSERT_TRUE(s.ToString().find("WAL 100 must exist before deletion") !=
|
|
std::string::npos);
|
|
}
|
|
|
|
TEST(WalSet, DeleteNonClosedWal) {
|
|
constexpr WalNumber kNonClosedWalNumber = 100;
|
|
WalSet wals;
|
|
ASSERT_OK(wals.AddWal(WalAddition(kNonClosedWalNumber)));
|
|
Status s = wals.DeleteWal(WalDeletion(kNonClosedWalNumber));
|
|
ASSERT_TRUE(s.IsCorruption());
|
|
ASSERT_TRUE(s.ToString().find("WAL 100 must be closed before deletion") !=
|
|
std::string::npos);
|
|
}
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|
|
|
|
int main(int argc, char** argv) {
|
|
ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|