github-actions[bot] commented on code in PR #69264:
URL: https://github.com/apache/doris/pull/69264#discussion_r4374716578
##########
cloud/src/recycler/checker.cpp:
##########
@@ -1249,6 +1249,156 @@ int InstanceChecker::collect_tablet_rowsets(
return 0;
}
+std::pair<MetaServiceCode, std::string> check_delete_bitmap_orphan(
+ const std::shared_ptr<TxnKv>& txn_kv, const std::string& instance_id,
int64_t tablet_id,
+ int64_t max_scan_keys, DeleteBitmapOrphanCheckResult* result,
+ const std::function<bool()>& should_cancel) {
+ *result = {};
+ auto check_cancelled = [&] {
+ result->cancelled = should_cancel();
+ return result->cancelled;
+ };
+ std::unique_ptr<Transaction> txn;
+ auto err = txn_kv->create_txn(&txn);
+ if (check_cancelled()) {
+ return {MetaServiceCode::OK, ""};
+ }
+ if (err != TxnErrorCode::TXN_OK) {
+ return {cast_as<ErrCategory::CREATE>(err), "failed to create check
transaction"};
+ }
+ std::string instance_value;
+ err = txn->get(instance_key({instance_id}), &instance_value);
+ if (check_cancelled()) {
+ return {MetaServiceCode::OK, ""};
+ }
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ return {MetaServiceCode::INVALID_ARGUMENT, "instance not found"};
+ }
+ if (err != TxnErrorCode::TXN_OK) {
+ return {cast_as<ErrCategory::READ>(err), "failed to read instance"};
+ }
+
+ auto begin = meta_delete_bitmap_key({instance_id, tablet_id, "", 0, 0});
+ auto end = meta_delete_bitmap_key(
+ {instance_id, tablet_id == 0 ? INT64_MAX : tablet_id + 1, "", 0,
0});
+ RangeGetOptions options;
+ options.reverse = true;
+ options.snapshot = true;
+ int64_t cached_tablet_id = -1;
+ std::unordered_set<std::string> rowsets;
+ while (true) {
+ if (max_scan_keys > 0 && result->scanned_kvs >= max_scan_keys) {
+ return {MetaServiceCode::OK, ""};
+ }
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ return {cast_as<ErrCategory::CREATE>(err), "failed to create check
transaction"};
+ }
+ // Small pages bound bitmap value traffic before an early return. No
next-page prefetch.
+ options.batch_limit = max_scan_keys > 0
+ ? std::min<int64_t>(128, max_scan_keys -
result->scanned_kvs)
+ : 128;
+ std::unique_ptr<RangeGetIterator> it;
+ err = txn->get(begin, end, &it, options);
+ TEST_SYNC_POINT_CALLBACK("check_delete_bitmap_orphan::get_bitmap",
&err);
+ if (check_cancelled()) {
+ return {MetaServiceCode::OK, ""};
+ }
+ if (err == TxnErrorCode::TXN_TOO_OLD) {
+ continue;
+ }
+ if (err != TxnErrorCode::TXN_OK) {
+ return {cast_as<ErrCategory::READ>(err), "failed to scan v1 delete
bitmaps"};
+ }
+ bool retry_current_bitmap = false;
+ while (!check_cancelled() && it->has_next()) {
+ auto [key, value] = it->next();
+ ++result->scanned_kvs;
+ auto encoded_key = key.substr(1);
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int,
int>> fields;
+ // Legacy keys have seven fields; blob keys have an additional
encoded suffix.
+ if (decode_key(&encoded_key, &fields) != 0 ||
+ (fields.size() != 7 && fields.size() != 8)) {
+ return {MetaServiceCode::UNDEFINED_ERR,
+ fmt::format("malformed delete bitmap key: {}",
hex(key))};
+ }
+ const auto* current_tablet_id =
std::get_if<int64_t>(&std::get<0>(fields[3]));
+ const auto* rowset_id =
std::get_if<std::string>(&std::get<0>(fields[4]));
+ const auto* version =
std::get_if<int64_t>(&std::get<0>(fields[5]));
+ const auto* segment_id =
std::get_if<int64_t>(&std::get<0>(fields[6]));
+ if (current_tablet_id == nullptr || rowset_id == nullptr ||
version == nullptr ||
+ segment_id == nullptr) {
+ return {MetaServiceCode::UNDEFINED_ERR,
+ fmt::format("invalid delete bitmap key fields: {}",
hex(key))};
+ }
+
+ if (cached_tablet_id != *current_tablet_id) {
Review Comment:
[P2] Refresh the rowset cache when the bitmap snapshot changes
Each bitmap page creates a new transaction, but this condition keeps the
previous page's rowset set whenever the tablet is unchanged. For example, start
with 129 bitmap KVs for live rowset A, then fully publish rowset B and its own
intra-rowset bitmap between pages. B can sort below A because rowset-ID
counters restart per BE, so page 2 reads B's bitmap after its formal rowset is
committed. The cache still predates B, and `rowsets.contains()` returns false,
stopping the diagnostic on a healthy rowset before reaching any lower orphan.
This also occurs without `TXN_TOO_OLD`; it is separate from the documented
pending/tmp-rowset suspicion. Refresh the cache for the new read version, or
revalidate a miss in the current bitmap transaction, before reporting it. Add a
successful-page-boundary publication test.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]