Skip to content

Commit aa3d98a

Browse files
[Enhancement] support corrupt meta cache clear for bundle metadata (backport #63949) (#63988)
Signed-off-by: luohaha <18810541851@163.com> Co-authored-by: Yixin Luo <18810541851@163.com>
1 parent ada40c0 commit aa3d98a

4 files changed

Lines changed: 108 additions & 17 deletions

File tree

be/src/storage/lake/tablet_manager.cpp

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,22 @@ Status TabletManager::put_bundle_tablet_metadata(std::map<int64_t, TabletMetadat
378378
return Status::OK();
379379
}
380380

381+
Status TabletManager::corrupted_tablet_meta_handler(const Status& s, const std::string& metadata_location) {
382+
if (s.is_corruption() && config::lake_clear_corrupted_cache) {
383+
auto drop_status = drop_local_cache(metadata_location);
384+
TEST_SYNC_POINT_CALLBACK("TabletManager::corrupted_tablet_meta_handler", &drop_status);
385+
if (!drop_status.ok()) {
386+
LOG(WARNING) << "clear corrupted cache for " << metadata_location << " failed, "
387+
<< "error: " << drop_status;
388+
return s; // return error so load tablet meta can be retried
389+
}
390+
LOG(INFO) << "clear corrupted cache for " << metadata_location;
391+
return Status::OK();
392+
} else {
393+
return s;
394+
}
395+
}
396+
381397
StatusOr<TabletMetadataPtr> TabletManager::load_tablet_metadata(const string& metadata_location, bool fill_cache,
382398
int64_t expected_gtid,
383399
const std::shared_ptr<FileSystem>& fs) {
@@ -387,21 +403,11 @@ StatusOr<TabletMetadataPtr> TabletManager::load_tablet_metadata(const string& me
387403
ProtobufFile file(metadata_location, fs);
388404
auto s = file.load(metadata.get(), fill_cache);
389405
if (!s.ok()) {
390-
if (s.is_corruption() && config::lake_clear_corrupted_cache) {
391-
auto drop_status = drop_local_cache(metadata_location);
392-
if (!drop_status.ok()) {
393-
LOG(WARNING) << "clear corrupted cache for " << metadata_location << " failed, "
394-
<< "error: " << drop_status;
395-
return s; // return error so load tablet meta can be retried
396-
}
397-
LOG(INFO) << "clear corrupted cache for " << metadata_location;
398-
// reset metadata
399-
metadata = std::make_shared<TabletMetadataPB>();
400-
// read again
401-
RETURN_IF_ERROR(file.load(metadata.get(), fill_cache));
402-
} else {
403-
return s;
404-
}
406+
RETURN_IF_ERROR(corrupted_tablet_meta_handler(s, metadata_location));
407+
// reset metadata
408+
metadata = std::make_shared<TabletMetadataPB>();
409+
// read again
410+
RETURN_IF_ERROR(file.load(metadata.get(), fill_cache));
405411
}
406412

407413
if (expected_gtid > 0 && metadata->gtid() > 0 && expected_gtid != metadata->gtid()) {
@@ -502,7 +508,13 @@ StatusOr<BundleTabletMetadataPtr> TabletManager::parse_bundle_tablet_metadata(co
502508
std::string_view(serialized_string.data() + file_size - footer_size - bundle_metadata_size);
503509
RETURN_IF(!bundle_metadata->ParseFromArray(bundle_metadata_str.data(), bundle_metadata_size),
504510
Status::Corruption(strings::Substitute("deserialized shared metadata failed")));
505-
511+
#ifdef BE_TEST
512+
bool inject_error = false;
513+
TEST_SYNC_POINT_CALLBACK("TabletManager::parse_bundle_tablet_metadata::corruption", &inject_error);
514+
if (inject_error) {
515+
return Status::Corruption("injected error");
516+
}
517+
#endif
506518
return bundle_metadata;
507519
}
508520

@@ -581,7 +593,18 @@ StatusOr<TabletMetadataPtr> TabletManager::get_single_tablet_metadata(int64_t ta
581593
g_read_bundle_tablet_meta_latency << (butil::gettimeofday_us() - t0);
582594

583595
auto file_size = serialized_string.size();
584-
ASSIGN_OR_RETURN(auto bundle_metadata, parse_bundle_tablet_metadata(path, serialized_string));
596+
BundleTabletMetadataPtr bundle_metadata;
597+
auto bundle_metadata_status = parse_bundle_tablet_metadata(path, serialized_string);
598+
if (!bundle_metadata_status.ok()) {
599+
RETURN_IF_ERROR(corrupted_tablet_meta_handler(bundle_metadata_status.status(), path));
600+
// read bundle metadata again
601+
ASSIGN_OR_RETURN(auto input_file, file_system->new_random_access_file(opts, path));
602+
ASSIGN_OR_RETURN(serialized_string, input_file->read_all());
603+
file_size = serialized_string.size();
604+
ASSIGN_OR_RETURN(bundle_metadata, parse_bundle_tablet_metadata(path, serialized_string));
605+
} else {
606+
bundle_metadata = bundle_metadata_status.value();
607+
}
585608

586609
auto meta_it = bundle_metadata->tablet_meta_pages().find(tablet_id);
587610
size_t offset = 0;

be/src/storage/lake/tablet_manager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ class TabletManager {
249249
int64_t expected_gtid, const std::shared_ptr<FileSystem>& fs);
250250
StatusOr<TxnLogPtr> load_txn_log(const std::string& txn_log_location, bool fill_cache);
251251
StatusOr<CombinedTxnLogPtr> load_combined_txn_log(const std::string& path, bool fill_cache);
252+
Status corrupted_tablet_meta_handler(const Status& s, const std::string& metadata_location);
252253

253254
private:
254255
std::shared_ptr<LocationProvider> _location_provider;

be/src/storage/protobuf_file.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ Status ProtobufFile::load(::google::protobuf::Message* message, bool fill_cache)
176176
if (bool parsed = message->ParseFromString(serialized_string); !parsed) {
177177
return Status::Corruption(fmt::format("failed to parse protobuf file {}", _path));
178178
}
179+
#ifndef BE_TEST
179180
return Status::OK();
181+
#else
182+
Status st = Status::OK();
183+
TEST_SYNC_POINT_CALLBACK("ProtobufFile::load::corruption", &st);
184+
return st;
185+
#endif
180186
}
181187
} // namespace starrocks

be/test/storage/lake/tablet_manager_test.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,41 @@ TEST_F(LakeTabletManagerTest, tablet_meta_write_and_read) {
103103
EXPECT_TRUE(res.status().is_not_found());
104104
}
105105

106+
TEST_F(LakeTabletManagerTest, tablet_meta_read_corrupted_and_recover) {
107+
starrocks::TabletMetadata metadata;
108+
auto tablet_id = next_id();
109+
metadata.set_id(tablet_id);
110+
metadata.set_version(2);
111+
auto rowset_meta_pb = metadata.add_rowsets();
112+
rowset_meta_pb->set_id(2);
113+
rowset_meta_pb->set_overlapped(false);
114+
rowset_meta_pb->set_data_size(1024);
115+
rowset_meta_pb->set_num_rows(5);
116+
EXPECT_OK(_tablet_manager->put_tablet_metadata(metadata));
117+
auto res = _tablet_manager->get_tablet_metadata(tablet_id, 2);
118+
EXPECT_TRUE(res.ok());
119+
_tablet_manager->metacache()->prune();
120+
bool is_first_time = true;
121+
SyncPoint::GetInstance()->EnableProcessing();
122+
DeferOp defer([]() {
123+
SyncPoint::GetInstance()->ClearCallBack("ProtobufFile::load::corruption");
124+
SyncPoint::GetInstance()->ClearCallBack("TabletManager::corrupted_tablet_meta_handler");
125+
SyncPoint::GetInstance()->DisableProcessing();
126+
});
127+
SyncPoint::GetInstance()->SetCallBack("ProtobufFile::load::corruption", [&](void* arg) {
128+
if (is_first_time) {
129+
*(Status*)arg = Status::Corruption("injected error");
130+
is_first_time = false;
131+
}
132+
});
133+
SyncPoint::GetInstance()->SetCallBack("TabletManager::corrupted_tablet_meta_handler",
134+
[](void* arg) { *(Status*)arg = Status::OK(); });
135+
res = _tablet_manager->get_tablet_metadata(tablet_id, 2);
136+
EXPECT_TRUE(res.ok());
137+
EXPECT_EQ(res.value()->id(), tablet_id);
138+
EXPECT_EQ(res.value()->version(), 2);
139+
}
140+
106141
// NOLINTNEXTLINE
107142
TEST_F(LakeTabletManagerTest, txnlog_write_and_read) {
108143
starrocks::TxnLog txnLog;
@@ -690,6 +725,32 @@ TEST_F(LakeTabletManagerTest, put_bundle_tablet_metadata) {
690725
ASSERT_EQ(metadata->historical_schemas_size(), 2);
691726
}
692727

728+
{
729+
_tablet_manager->metacache()->prune();
730+
// inject corruption error
731+
SyncPoint::GetInstance()->EnableProcessing();
732+
bool is_first_time = true;
733+
DeferOp defer([]() {
734+
SyncPoint::GetInstance()->ClearCallBack("TabletManager::parse_bundle_tablet_metadata::corruption");
735+
SyncPoint::GetInstance()->ClearCallBack("TabletManager::corrupted_tablet_meta_handler");
736+
SyncPoint::GetInstance()->DisableProcessing();
737+
});
738+
SyncPoint::GetInstance()->SetCallBack("TabletManager::parse_bundle_tablet_metadata::corruption",
739+
[&](void* arg) {
740+
if (is_first_time) {
741+
*(bool*)arg = true;
742+
is_first_time = false;
743+
}
744+
});
745+
SyncPoint::GetInstance()->SetCallBack("TabletManager::corrupted_tablet_meta_handler",
746+
[](void* arg) { *(Status*)arg = Status::OK(); });
747+
auto res = _tablet_manager->get_tablet_metadata(1, 2);
748+
EXPECT_TRUE(res.ok()) << res.status().to_string();
749+
TabletMetadataPtr metadata = std::move(res).value();
750+
ASSERT_EQ(metadata->schema().id(), 10);
751+
ASSERT_EQ(metadata->historical_schemas_size(), 2);
752+
}
753+
693754
// multi thread read
694755
{
695756
std::vector<std::thread> threads;

0 commit comments

Comments
 (0)