From 6f1195922e496e9e5552f06b9c0458a608ffd186 Mon Sep 17 00:00:00 2001 From: Peter Mattis Date: Thu, 11 Oct 2018 16:04:59 -0400 Subject: [PATCH] Extend PartialRangeTombstone to use InternalKeys Change `RangeDelAggregator::GetTombstone,ShouldDeleteRange` to take internal keys instead of user keys. --- db/dbformat.h | 16 ++-- db/range_del_aggregator.cc | 23 ++++-- db/range_del_aggregator.h | 12 +-- db/range_del_aggregator_test.cc | 124 +++++++++++++++++++----------- table/block_based_table_reader.cc | 60 +++++++++------ tools/ldb_cmd.cc | 4 +- 6 files changed, 144 insertions(+), 95 deletions(-) diff --git a/db/dbformat.h b/db/dbformat.h index 72b5ac48833..083c0b10ea1 100644 --- a/db/dbformat.h +++ b/db/dbformat.h @@ -635,13 +635,15 @@ class PartialRangeTombstone { PartialRangeTombstone() : start_key_valid_(false), end_key_valid_(false), seq_(0) {} - PartialRangeTombstone(const Slice* sk, const Slice* ek, SequenceNumber sq) + PartialRangeTombstone(const ParsedInternalKey* sk, + const ParsedInternalKey* ek, + SequenceNumber sq) : seq_(sq) { SetStartKey(sk); SetEndKey(ek); } - void SetStartKey(const Slice* sk) { + void SetStartKey(const ParsedInternalKey* sk) { if (sk != nullptr) { start_key_ = *sk; start_key_valid_ = true; @@ -650,7 +652,7 @@ class PartialRangeTombstone { } } - void SetEndKey(const Slice* ek) { + void SetEndKey(const ParsedInternalKey* ek) { if (ek != nullptr) { end_key_ = *ek; end_key_valid_ = true; @@ -659,15 +661,15 @@ class PartialRangeTombstone { } } - const Slice* start_key() const { + const ParsedInternalKey* start_key() const { return start_key_valid_ ? &start_key_ : nullptr; } - const Slice* end_key() const { return end_key_valid_ ? &end_key_ : nullptr; } + const ParsedInternalKey* end_key() const { return end_key_valid_ ? &end_key_ : nullptr; } SequenceNumber seq() const { return seq_; } private: - Slice start_key_; - Slice end_key_; + ParsedInternalKey start_key_; + ParsedInternalKey end_key_; bool start_key_valid_; bool end_key_valid_; SequenceNumber seq_; diff --git a/db/range_del_aggregator.cc b/db/range_del_aggregator.cc index ec3e618ba15..832c763e8f6 100644 --- a/db/range_del_aggregator.cc +++ b/db/range_del_aggregator.cc @@ -298,17 +298,17 @@ class CollapsedRangeDelMap : public RangeDelMap { if (!ParseInternalKey(end, &parsed_end)) { assert(false); } - if (ucmp_->Compare(parsed_start.user_key, parsed_end.user_key) > 0) { + if (icmp_->Compare(parsed_start, parsed_end) > 0) { return false; } - auto iter = rep_.upper_bound(parsed_start.user_key); + auto iter = rep_.upper_bound(parsed_start); if (iter == rep_.begin()) { // before start of deletion intervals return false; } --iter; - if (ucmp_->Compare(parsed_start.user_key, iter->first) < 0) { + if (icmp_->Compare(parsed_start, iter->first) < 0) { assert(false); return false; } @@ -316,7 +316,7 @@ class CollapsedRangeDelMap : public RangeDelMap { // number, or we determine that our range is completely covered by newer // tombstones. for (; iter != rep_.end(); ++iter) { - if (ucmp_->Compare(parsed_end.user_key, iter->first) < 0) { + if (icmp_->Compare(parsed_end, iter->first) < 0) { return true; } if (seqno >= iter->second) { @@ -327,9 +327,16 @@ class CollapsedRangeDelMap : public RangeDelMap { return false; } - PartialRangeTombstone GetTombstone(const Slice& user_key, + PartialRangeTombstone GetTombstone(const Slice& key, SequenceNumber seqno) override { - auto iter = rep_.upper_bound(user_key); + ParsedInternalKey parsed_key; + if (!ParseInternalKey(key, &parsed_key)) { + assert(false); + // Fail open. + return PartialRangeTombstone(); + } + + auto iter = rep_.upper_bound(parsed_key); if (iter == rep_.begin()) { // before start of deletion intervals return PartialRangeTombstone(nullptr, &iter->first, 0); @@ -583,7 +590,7 @@ bool RangeDelAggregator::ShouldDeleteRange( return tombstone_map.ShouldDeleteRange(start, end, seqno); } -PartialRangeTombstone RangeDelAggregator::GetTombstone(const Slice& user_key, +PartialRangeTombstone RangeDelAggregator::GetTombstone(const Slice& key, SequenceNumber seqno) { if (rep_ == nullptr) { return PartialRangeTombstone(); @@ -592,7 +599,7 @@ PartialRangeTombstone RangeDelAggregator::GetTombstone(const Slice& user_key, if (tombstone_map.IsEmpty()) { return PartialRangeTombstone(); } - return tombstone_map.GetTombstone(user_key, seqno); + return tombstone_map.GetTombstone(key, seqno); } bool RangeDelAggregator::IsRangeOverlapped(const Slice& start, diff --git a/db/range_del_aggregator.h b/db/range_del_aggregator.h index ef32cbbd634..30f6731b499 100644 --- a/db/range_del_aggregator.h +++ b/db/range_del_aggregator.h @@ -95,7 +95,7 @@ class RangeDelMap { RangeDelPositioningMode mode) = 0; virtual bool ShouldDeleteRange(const Slice& start, const Slice& end, SequenceNumber seqno) = 0; - virtual PartialRangeTombstone GetTombstone(const Slice& user_key, + virtual PartialRangeTombstone GetTombstone(const Slice& key, SequenceNumber seqno) = 0; virtual bool IsRangeOverlapped(const ParsedInternalKey& start, const ParsedInternalKey& end) = 0; @@ -171,11 +171,11 @@ class RangeDelAggregator { bool ShouldDeleteRange(const Slice& start, const Slice& end, SequenceNumber seqno); - // Get the range tombstone at the specified user_key and sequence number. A - // valid tombstone is always returned, though it may cover an empty range of - // keys or the sequence number may be 0 to indicate that no tombstone covers - // the specified key. - PartialRangeTombstone GetTombstone(const Slice& user_key, + // Get the range tombstone at the specified internal key and sequence + // number. A valid tombstone is always returned, though it may cover an + // empty range of keys or the sequence number may be 0 to indicate that no + // tombstone covers the specified key. + PartialRangeTombstone GetTombstone(const Slice& key, SequenceNumber seqno); // Checks whether range deletions cover any keys between `start` and `end`, diff --git a/db/range_del_aggregator_test.cc b/db/range_del_aggregator_test.cc index 1a551150710..dc865332b32 100644 --- a/db/range_del_aggregator_test.cc +++ b/db/range_del_aggregator_test.cc @@ -66,12 +66,16 @@ void VerifyPartialTombstonesEq(const PartialRangeTombstone& a, const PartialRangeTombstone& b) { ASSERT_EQ(a.seq(), b.seq()); if (a.start_key() != nullptr) { - ASSERT_EQ(*a.start_key(), *b.start_key()); + ASSERT_EQ(a.start_key()->user_key, b.start_key()->user_key); + ASSERT_EQ(a.start_key()->sequence, b.start_key()->sequence); + ASSERT_EQ(a.start_key()->type, b.start_key()->type); } else { ASSERT_EQ(b.start_key(), nullptr); } if (a.end_key() != nullptr) { - ASSERT_EQ(*a.end_key(), *b.end_key()); + ASSERT_EQ(a.end_key()->user_key, b.end_key()->user_key); + ASSERT_EQ(a.end_key()->sequence, b.end_key()->sequence); + ASSERT_EQ(a.end_key()->type, b.end_key()->type); } else { ASSERT_EQ(b.end_key(), nullptr); } @@ -170,18 +174,11 @@ void VerifyRangeDels( } } -bool ShouldDeleteRange(const std::vector& range_dels, +bool ShouldDeleteRange(const AddTombstonesArgs& range_dels, const ExpectedRange& expected_range) { RangeDelAggregator range_del_agg(bytewise_icmp, {} /* snapshots */, true); - std::vector keys, values; - for (const auto& range_del : range_dels) { - auto key_and_value = range_del.Serialize(); - keys.push_back(key_and_value.first.Encode().ToString()); - values.push_back(key_and_value.second.ToString()); - } - std::unique_ptr range_del_iter( - new test::VectorIterator(keys, values)); - range_del_agg.AddTombstones(std::move(range_del_iter)); + AddTombstones(&range_del_agg, range_dels.tombstones, + range_dels.smallest, range_dels.largest); std::string begin, end; AppendInternalKey(&begin, {expected_range.begin, expected_range.seq, kTypeValue}); @@ -189,22 +186,16 @@ bool ShouldDeleteRange(const std::vector& range_dels, return range_del_agg.ShouldDeleteRange(begin, end, expected_range.seq); } -void VerifyGetTombstone(const std::vector& range_dels, +void VerifyGetTombstone(const AddTombstonesArgs& range_dels, const ExpectedPoint& expected_point, const PartialRangeTombstone& expected_tombstone) { RangeDelAggregator range_del_agg(bytewise_icmp, {} /* snapshots */, true); ASSERT_TRUE(range_del_agg.IsEmpty()); - std::vector keys, values; - for (const auto& range_del : range_dels) { - auto key_and_value = range_del.Serialize(); - keys.push_back(key_and_value.first.Encode().ToString()); - values.push_back(key_and_value.second.ToString()); - } - std::unique_ptr range_del_iter( - new test::VectorIterator(keys, values)); - range_del_agg.AddTombstones(std::move(range_del_iter)); + AddTombstones(&range_del_agg, range_dels.tombstones, + range_dels.smallest, range_dels.largest); - auto tombstone = range_del_agg.GetTombstone(expected_point.begin, expected_point.seq); + auto key = InternalKey(expected_point.begin, kMaxSequenceNumber, kTypeValue); + auto tombstone = range_del_agg.GetTombstone(key.Encode(), expected_point.seq); VerifyPartialTombstonesEq(expected_tombstone, tombstone); } @@ -395,62 +386,99 @@ TEST_F(RangeDelAggregatorTest, MergingIteratorSeek) { } TEST_F(RangeDelAggregatorTest, ShouldDeleteRange) { + const InternalKey b8("b", 8, kTypeValue); + const InternalKey b9("b", 9, kTypeValue); + const InternalKey b10("b", 10, kTypeValue); + const InternalKey c9("c", 9, kTypeValue); + const InternalKey c10("c", 10, kTypeValue); + ASSERT_TRUE(ShouldDeleteRange( - {{"a", "c", 10}}, + {{{"a", "c", 10}}}, + {"a", "b", 9})); + ASSERT_TRUE(ShouldDeleteRange( + {{{"a", "c", 10}}, nullptr, &b9}, + {"a", "b", 9})); + ASSERT_FALSE(ShouldDeleteRange( + {{{"a", "c", 10}}, nullptr, &b10}, {"a", "b", 9})); ASSERT_TRUE(ShouldDeleteRange( - {{"a", "c", 10}}, + {{{"a", "c", 10}}}, {"a", "a", 9})); ASSERT_FALSE(ShouldDeleteRange( - {{"a", "c", 10}}, + {{{"a", "c", 10}}}, {"b", "a", 9})); ASSERT_FALSE(ShouldDeleteRange( - {{"a", "c", 10}}, + {{{"a", "c", 10}}}, {"a", "b", 10})); ASSERT_FALSE(ShouldDeleteRange( - {{"a", "c", 10}}, + {{{"a", "c", 10}}}, {"a", "c", 9})); ASSERT_FALSE(ShouldDeleteRange( - {{"b", "c", 10}}, + {{{"b", "c", 10}}}, {"a", "b", 9})); ASSERT_TRUE(ShouldDeleteRange( - {{"a", "b", 10}, {"b", "d", 20}}, + {{{"a", "b", 10}, {"b", "d", 20}}}, {"a", "c", 9})); + ASSERT_TRUE(ShouldDeleteRange( + {{{"a", "b", 10}, {"b", "d", 20}}, nullptr, &c9}, + {"a", "c", 9})); + ASSERT_FALSE(ShouldDeleteRange( + {{{"a", "b", 10}, {"b", "d", 20}}, nullptr, &c10}, + {"a", "c", 9})); + ASSERT_TRUE(ShouldDeleteRange( + {{{"a", "b", 10}, {"b", "d", 20}}, &b9, nullptr}, + {"b", "c", 9})); + ASSERT_FALSE(ShouldDeleteRange( + {{{"a", "b", 10}, {"b", "d", 20}}, &b8, nullptr}, + {"b", "c", 9})); ASSERT_FALSE(ShouldDeleteRange( - {{"a", "b", 10}, {"b", "d", 20}}, + {{{"a", "b", 10}, {"b", "d", 20}}}, {"a", "c", 15})); ASSERT_FALSE(ShouldDeleteRange( - {{"a", "b", 10}, {"c", "e", 20}}, + {{{"a", "b", 10}, {"c", "e", 20}}}, {"a", "d", 9})); ASSERT_TRUE(ShouldDeleteRange( - {{"a", "b", 10}, {"c", "e", 20}}, + {{{"a", "b", 10}, {"c", "e", 20}}}, {"c", "d", 15})); ASSERT_FALSE(ShouldDeleteRange( - {{"a", "b", 10}, {"c", "e", 20}}, + {{{"a", "b", 10}, {"c", "e", 20}}}, {"c", "d", 20})); } TEST_F(RangeDelAggregatorTest, GetTombstone) { - Slice a = "a", b = "b", c = "c", d = "d", e = "e", h = "h"; - VerifyGetTombstone({{"b", "d", 10}}, {"b", 9}, + const ParsedInternalKey a = {"a", kMaxSequenceNumber, kMaxValue}; + const ParsedInternalKey b = {"b", kMaxSequenceNumber, kMaxValue}; + const ParsedInternalKey b10 = {"b", 10, kMaxValue}; + const InternalKey ib10("b", 10, kTypeValue); + const ParsedInternalKey c = {"c", kMaxSequenceNumber, kMaxValue}; + const ParsedInternalKey c8 = {"c", 8, kMaxValue}; + const InternalKey ic9("c", 9, kTypeValue); + const ParsedInternalKey d = {"d", kMaxSequenceNumber, kMaxValue}; + const ParsedInternalKey e = {"e", kMaxSequenceNumber, kMaxValue}; + const ParsedInternalKey h = {"h", kMaxSequenceNumber, kMaxValue}; + VerifyGetTombstone({{{"b", "d", 10}}}, {"b", 9}, PartialRangeTombstone(&b, &d, 10)); - VerifyGetTombstone({{"b", "d", 10}}, {"b", 10}, + VerifyGetTombstone({{{"b", "d", 10}}, nullptr, &ic9}, {"b", 9}, + PartialRangeTombstone(&b, &c8, 10)); + VerifyGetTombstone({{{"a", "d", 10}}, &ib10, nullptr}, {"c", 9}, + PartialRangeTombstone(&b10, &d, 10)); + VerifyGetTombstone({{{"b", "d", 10}}}, {"b", 10}, PartialRangeTombstone(&b, &d, 0)); - VerifyGetTombstone({{"b", "d", 10}}, {"b", 20}, + VerifyGetTombstone({{{"b", "d", 10}}}, {"b", 20}, PartialRangeTombstone(&b, &d, 0)); - VerifyGetTombstone({{"b", "d", 10}}, {"a", 9}, + VerifyGetTombstone({{{"b", "d", 10}}}, {"a", 9}, PartialRangeTombstone(nullptr, &b, 0)); - VerifyGetTombstone({{"b", "d", 10}}, {"d", 9}, + VerifyGetTombstone({{{"b", "d", 10}}}, {"d", 9}, PartialRangeTombstone(&d, nullptr, 0)); - VerifyGetTombstone({{"a", "c", 10}, {"e", "h", 20}}, {"d", 9}, + VerifyGetTombstone({{{"a", "c", 10}, {"e", "h", 20}}}, {"d", 9}, PartialRangeTombstone(&c, &e, 0)); - VerifyGetTombstone({{"a", "c", 10}, {"e", "h", 20}}, {"b", 9}, + VerifyGetTombstone({{{"a", "c", 10}, {"e", "h", 20}}}, {"b", 9}, PartialRangeTombstone(&a, &c, 10)); - VerifyGetTombstone({{"a", "c", 10}, {"e", "h", 20}}, {"b", 10}, + VerifyGetTombstone({{{"a", "c", 10}, {"e", "h", 20}}}, {"b", 10}, PartialRangeTombstone(&a, &c, 0)); - VerifyGetTombstone({{"a", "c", 10}, {"e", "h", 20}}, {"e", 19}, + VerifyGetTombstone({{{"a", "c", 10}, {"e", "h", 20}}}, {"e", 19}, PartialRangeTombstone(&e, &h, 20)); - VerifyGetTombstone({{"a", "c", 10}, {"e", "h", 20}}, {"e", 20}, + VerifyGetTombstone({{{"a", "c", 10}, {"e", "h", 20}}}, {"e", 20}, PartialRangeTombstone(&e, &h, 0)); } @@ -458,9 +486,11 @@ TEST_F(RangeDelAggregatorTest, AddGetTombstoneInterleaved) { RangeDelAggregator range_del_agg(bytewise_icmp, {} /* snapshots */, true /* collapsed */); AddTombstones(&range_del_agg, {{"b", "c", 10}}); - auto tombstone = range_del_agg.GetTombstone("b", 5); + auto key = InternalKey("b", kMaxSequenceNumber, kTypeValue); + auto tombstone = range_del_agg.GetTombstone(key.Encode(), 5); AddTombstones(&range_del_agg, {{"a", "d", 20}}); - Slice b = "b", c = "c"; + ParsedInternalKey b = {"b", kMaxSequenceNumber, kMaxValue}; + ParsedInternalKey c {"c", kMaxSequenceNumber, kMaxValue}; VerifyPartialTombstonesEq(PartialRangeTombstone(&b, &c, 10), tombstone); } diff --git a/table/block_based_table_reader.cc b/table/block_based_table_reader.cc index 8e99ecca2fe..504e2e5aeb5 100644 --- a/table/block_based_table_reader.cc +++ b/table/block_based_table_reader.cc @@ -1787,7 +1787,7 @@ void BlockBasedTableIterator::Seek(const Slice& const_target) { } // Before we seek the iterator, find the next non-deleted key. - InitRangeTombstone(ExtractUserKey(target)); + InitRangeTombstone(target); std::string tmp_target; if (range_tombstone_.seq() > 0) { tmp_target = tombstone_internal_end_key(); @@ -1820,7 +1820,7 @@ void BlockBasedTableIterator::SeekForPrev(const Slice& const_target) { } // Before we seek the iterator, find the previous non-deleted key. - InitRangeTombstone(ExtractUserKey(target)); + InitRangeTombstone(target); std::string tmp_target; if (range_tombstone_.seq() > 0) { tmp_target = tombstone_internal_start_key(); @@ -1872,7 +1872,7 @@ void BlockBasedTableIterator::SeekToFirst() { InitDataBlock(); data_block_iter_.SeekToFirst(); if (Valid()) { - InitRangeTombstone(user_key()); + InitRangeTombstone(key()); } FindKeyForward(); } @@ -1887,7 +1887,7 @@ void BlockBasedTableIterator::SeekToLast() { InitDataBlock(); data_block_iter_.SeekToLast(); if (Valid()) { - InitRangeTombstone(user_key()); + InitRangeTombstone(key()); } FindKeyBackward(); } @@ -2006,14 +2006,18 @@ void BlockBasedTableIterator::FindKeyForward() { return; } - auto ukey = user_key(); - if (icomp_.user_comparator()->Compare(ukey, *range_tombstone_.end_key()) >= + ParsedInternalKey parsed; + if (!ParseInternalKey(key(), &parsed)) { + assert(false); + return; + } + if (icomp_.Compare(parsed, *range_tombstone_.end_key()) >= 0) { // The key is past the tombstone. Grab the tombstone covering the // current key. The new tombstone might cover the existing key, so loop // so that we can have the proper check for whether the tombstone covers // the key and is a deletion tombstone or not. - InitRangeTombstone(ukey); + InitRangeTombstone(key()); continue; } // The key is contained within the current tombstone. @@ -2032,7 +2036,7 @@ void BlockBasedTableIterator::FindKeyForward() { InitDataBlock(); data_block_iter_.Seek(tombstone_internal_end_key()); if (Valid()) { - InitRangeTombstone(user_key()); + InitRangeTombstone(key()); } } } @@ -2082,14 +2086,18 @@ void BlockBasedTableIterator::FindKeyBackward() { return; } - auto ukey = user_key(); - if (icomp_.user_comparator()->Compare(ukey, *range_tombstone_.start_key()) < + ParsedInternalKey parsed; + if (!ParseInternalKey(key(), &parsed)) { + assert(false); + return; + } + if (icomp_.Compare(parsed, *range_tombstone_.start_key()) < 0) { // The key is past the tombstone. Grab the tombstone covering the // current key. The new tombstone might cover the existing key, so loop // so that we can have the proper check for whether the tombstone covers // the key and is a deletion tombstone or not. - InitRangeTombstone(ukey); + InitRangeTombstone(key()); continue; } // The key is contained within the current tombstone. @@ -2112,7 +2120,7 @@ void BlockBasedTableIterator::FindKeyBackward() { InitDataBlock(); data_block_iter_.SeekForPrev(tombstone_internal_start_key()); if (Valid()) { - InitRangeTombstone(user_key()); + InitRangeTombstone(key()); } } } @@ -2127,18 +2135,22 @@ void BlockBasedTableIterator::InitRangeTombstone(const Slice& target) { // Clear the start key if it is less than the smallest key in the // sstable. This allows us to avoid comparisons during Prev() in the common // case. - if (range_tombstone_.start_key() != nullptr && - icomp_.user_comparator()->Compare(*range_tombstone_.start_key(), - file_meta_->smallest.user_key()) < 0) { - range_tombstone_.SetStartKey(nullptr); + if (range_tombstone_.start_key() != nullptr) { + ParsedInternalKey smallest; + if (!ParseInternalKey(file_meta_->smallest.Encode(), &smallest) || + (icomp_.Compare(*range_tombstone_.start_key(), smallest) < 0)) { + range_tombstone_.SetStartKey(nullptr); + } } // Clear the end key if it is larger than the largest key in the // sstable. This allows us to avoid comparisons during Next() in the common // case. - if (range_tombstone_.end_key() != nullptr && - icomp_.user_comparator()->Compare(*range_tombstone_.end_key(), - file_meta_->largest.user_key()) > 0) { - range_tombstone_.SetEndKey(nullptr); + if (range_tombstone_.end_key() != nullptr) { + ParsedInternalKey largest; + if (!ParseInternalKey(file_meta_->largest.Encode(), &largest) || + (icomp_.Compare(*range_tombstone_.end_key(), largest) > 0)) { + range_tombstone_.SetEndKey(nullptr); + } } } @@ -2148,8 +2160,8 @@ std::string BlockBasedTableIterator::tombstone_internal_start_key() const { AppendInternalKey(&internal_key, {file_meta_->smallest.user_key(), range_tombstone_.seq(), kTypeValue}); } else { - AppendInternalKey(&internal_key, {*range_tombstone_.start_key(), - range_tombstone_.seq(), kTypeValue}); + AppendInternalKey(&internal_key, { range_tombstone_.start_key()->user_key, + range_tombstone_.seq(), kTypeValue }); } return internal_key; } @@ -2165,8 +2177,8 @@ std::string BlockBasedTableIterator::tombstone_internal_end_key() const { AppendInternalKey(&internal_key, {file_meta_->largest.user_key(), kMaxSequenceNumber, kTypeValue}); } else { - AppendInternalKey(&internal_key, {*range_tombstone_.end_key(), - kMaxSequenceNumber, kTypeValue}); + AppendInternalKey(&internal_key, { range_tombstone_.end_key()->user_key, + kMaxSequenceNumber, kTypeValue }); } return internal_key; } diff --git a/tools/ldb_cmd.cc b/tools/ldb_cmd.cc index 203bedcd55f..59aefccd22d 100644 --- a/tools/ldb_cmd.cc +++ b/tools/ldb_cmd.cc @@ -3047,8 +3047,7 @@ IngestExternalSstFilesCommand::IngestExternalSstFilesCommand( snapshot_consistency_(true), allow_global_seqno_(true), allow_blocking_flush_(true), - ingest_behind_(false), - write_global_seqno_(true) { + ingest_behind_(false) { create_if_missing_ = IsFlagPresent(flags, ARG_CREATE_IF_MISSING) || ParseBooleanOption(options, ARG_CREATE_IF_MISSING, false); @@ -3106,7 +3105,6 @@ void IngestExternalSstFilesCommand::DoCommand() { ifo.allow_global_seqno = allow_global_seqno_; ifo.allow_blocking_flush = allow_blocking_flush_; ifo.ingest_behind = ingest_behind_; - ifo.write_global_seqno = write_global_seqno_; Status status = db_->IngestExternalFile(cfh, {input_sst_path_}, ifo); if (!status.ok()) { exec_state_ = LDBCommandExecuteResult::Failed(