Skip to content

Commit 3ce8682

Browse files
committed
fix: should checkpoint the whole page
1 parent 3df4400 commit 3ce8682

File tree

5 files changed

+39
-28
lines changed

5 files changed

+39
-28
lines changed

source/concurrency-recovery/Recovery.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ inline bool Recovery::Run() {
9191

9292
Analysis();
9393

94-
// Redo();
94+
Redo();
9595

9696
// if (Undo()) {
9797
// return true;

source/storage/btree/core/BTreeGeneric.hpp

+16-13
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ class BTreeGeneric : public leanstore::storage::BufferManagedTree {
107107
/// Called by buffer manager before eviction
108108
virtual SpaceCheckResult checkSpaceUtilization(BufferFrame& bf) override;
109109

110-
// pre: source buffer frame is shared latched
111-
virtual void checkpoint(BufferFrame& bf, u8* dest) override;
110+
/// Flush the page content in the buffer frame to disk
111+
///
112+
/// NOTE: The source buffer frame should be shared latched
113+
virtual void Checkpoint(BufferFrame& bf, void* dest) override;
112114

113115
virtual void undo(const u8*, const u64) override {
114116
LOG(FATAL) << "undo is unsupported";
@@ -386,22 +388,23 @@ inline SpaceCheckResult BTreeGeneric::checkSpaceUtilization(BufferFrame& bf) {
386388
}
387389
}
388390

389-
inline void BTreeGeneric::checkpoint(BufferFrame& bf, u8* dest) {
390-
std::memcpy(dest, bf.page.mPayload, EFFECTIVE_PAGE_SIZE);
391-
auto& destNode = *reinterpret_cast<BTreeNode*>(dest);
391+
inline void BTreeGeneric::Checkpoint(BufferFrame& bf, void* dest) {
392+
std::memcpy(dest, &bf.page, PAGE_SIZE);
393+
auto destPage = reinterpret_cast<Page*>(dest);
394+
auto destNode = reinterpret_cast<BTreeNode*>(destPage->mPayload);
392395

393-
if (!destNode.mIsLeaf) {
396+
if (!destNode->mIsLeaf) {
394397
// Replace all child swip to their page ID
395-
for (u64 i = 0; i < destNode.mNumSeps; i++) {
396-
if (!destNode.getChild(i).isEVICTED()) {
397-
auto& childBf = destNode.getChild(i).asBufferFrameMasked();
398-
destNode.getChild(i).evict(childBf.header.mPageId);
398+
for (u64 i = 0; i < destNode->mNumSeps; i++) {
399+
if (!destNode->getChild(i).isEVICTED()) {
400+
auto& childBf = destNode->getChild(i).asBufferFrameMasked();
401+
destNode->getChild(i).evict(childBf.header.mPageId);
399402
}
400403
}
401404
// Replace right most child swip to page id
402-
if (!destNode.mRightMostChildSwip.isEVICTED()) {
403-
auto& childBf = destNode.mRightMostChildSwip.asBufferFrameMasked();
404-
destNode.mRightMostChildSwip.evict(childBf.header.mPageId);
405+
if (!destNode->mRightMostChildSwip.isEVICTED()) {
406+
auto& childBf = destNode->mRightMostChildSwip.asBufferFrameMasked();
407+
destNode->mRightMostChildSwip.evict(childBf.header.mPageId);
405408
}
406409
}
407410
}

source/storage/buffer-manager/BufferManager.cpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,10 @@ void BufferManager::writeAllBufferFrames() {
136136
auto& bf = mBfs[i];
137137
bf.header.mLatch.mutex.lock();
138138
if (!bf.isFree()) {
139-
page.mBTreeId = bf.page.mBTreeId;
140-
page.mMagicDebuging = bf.header.mPageId;
141-
TreeRegistry::sInstance->checkpoint(bf.page.mBTreeId, bf,
142-
page.mPayload);
143-
s64 ret = pwrite(mPageFd, &page, PAGE_SIZE, bf.header.mPageId * PAGE_SIZE);
144-
ENSURE(ret == PAGE_SIZE);
139+
TreeRegistry::sInstance->Checkpoint(bf.page.mBTreeId, bf, &page);
140+
s64 ret =
141+
pwrite(mPageFd, &page, PAGE_SIZE, bf.header.mPageId * PAGE_SIZE);
142+
DCHECK(ret == PAGE_SIZE);
145143
}
146144
bf.header.mLatch.mutex.unlock();
147145
}
@@ -152,9 +150,7 @@ void BufferManager::WriteBufferFrame(BufferFrame& bf) {
152150
Page page;
153151
bf.header.mLatch.mutex.lock();
154152
if (!bf.isFree()) {
155-
page.mBTreeId = bf.page.mBTreeId;
156-
page.mMagicDebuging = bf.header.mPageId;
157-
TreeRegistry::sInstance->checkpoint(bf.page.mBTreeId, bf, page.mPayload);
153+
TreeRegistry::sInstance->Checkpoint(bf.page.mBTreeId, bf, &page);
158154
s64 ret = pwrite(mPageFd, &page, PAGE_SIZE, bf.header.mPageId * PAGE_SIZE);
159155
ENSURE(ret == PAGE_SIZE);
160156
}

source/storage/buffer-manager/TreeRegistry.hpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ class BufferManagedTree {
5959
LOG(FATAL) << "BufferManagedTree::checkSpaceUtilization is unimplemented ";
6060
}
6161

62-
virtual void checkpoint(BufferFrame&, u8*) {
63-
LOG(FATAL) << "BufferManagedTree::checkpoint is unimplemented";
62+
virtual void Checkpoint(BufferFrame&, void*) {
63+
LOG(FATAL) << "BufferManagedTree::Checkpoint is unimplemented";
6464
}
6565

6666
virtual void undo(const u8*, const u64) {
@@ -228,13 +228,13 @@ class TreeRegistry {
228228
}
229229

230230
// Pre: bf is shared/exclusive latched
231-
inline void checkpoint(TREEID treeId, BufferFrame& bf, u8* dest) {
231+
inline void Checkpoint(TREEID treeId, BufferFrame& bf, void* dest) {
232232
std::shared_lock sharedGuard(mMutex);
233233
auto it = mTrees.find(treeId);
234234
DLOG_IF(FATAL, it == mTrees.end())
235235
<< "BufferManagedTree not find, treeId=" << treeId;
236236
auto& [tree, treeName] = it->second;
237-
return tree->checkpoint(bf, dest);
237+
return tree->Checkpoint(bf, dest);
238238
}
239239

240240
// Recovery / SI

tests/BTreeVILoggingAndRecoveryTest.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ TEST_F(BTreeVILoggingAndRecoveryTest, SerializeAndDeserialize) {
4646
storage::btree::BTreeVI* btree;
4747

4848
// prepare key-value pairs to insert
49-
size_t numKVs(1);
49+
size_t numKVs(10);
5050
std::vector<std::tuple<std::string, std::string>> kvToTest;
5151
for (size_t i = 0; i < numKVs; ++i) {
5252
std::string key("key_xxxxxxxxxxxx_" + std::to_string(i));
@@ -78,6 +78,12 @@ TEST_F(BTreeVILoggingAndRecoveryTest, SerializeAndDeserialize) {
7878
}
7979
});
8080

81+
cr::CRManager::sInstance->scheduleJobSync(0, [&]() {
82+
rapidjson::Document doc(rapidjson::kObjectType);
83+
leanstore::storage::btree::BTreeGeneric::ToJSON(*btree, &doc);
84+
LOG(INFO) << "btree before destroy: " << leanstore::utils::JsonToStr(&doc);
85+
});
86+
8187
// meta file should be serialized during destructor.
8288
mLeanStore.reset(nullptr);
8389
FLAGS_recover = true;
@@ -87,6 +93,12 @@ TEST_F(BTreeVILoggingAndRecoveryTest, SerializeAndDeserialize) {
8793
EXPECT_TRUE(mLeanStore->GetBTreeVI(btreeName, &btree));
8894
EXPECT_NE(btree, nullptr);
8995

96+
cr::CRManager::sInstance->scheduleJobSync(0, [&]() {
97+
rapidjson::Document doc(rapidjson::kObjectType);
98+
leanstore::storage::btree::BTreeGeneric::ToJSON(*btree, &doc);
99+
LOG(INFO) << "btree after recovery: " << leanstore::utils::JsonToStr(&doc);
100+
});
101+
90102
// lookup the restored btree
91103
cr::CRManager::sInstance->scheduleJobSync(0, [&]() {
92104
std::string copiedValue;

0 commit comments

Comments
 (0)