Skip to content

Commit 4c2f71c

Browse files
committed
MB-54729: Add KVStore::scanAllVersions
Add a new scan method that scans the seqno index. For now this function is the same as ::scan, but will be updated to scan the retained history. Change-Id: I7a2c424b212962634120f2ba3f831f47e72c9820
1 parent 284c2e2 commit 4c2f71c

File tree

10 files changed

+86
-0
lines changed

10 files changed

+86
-0
lines changed

engines/ep/src/kvstore/couch-kvstore/couch-kvstore.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2376,6 +2376,11 @@ scan_error_t CouchKVStore::scan(BySeqnoScanContext& ctx) const {
23762376
return scan_success;
23772377
}
23782378

2379+
scan_error_t CouchKVStore::scanAllVersions(BySeqnoScanContext& sctx) const {
2380+
// StorageProperties reported this feature is not available
2381+
throw std::runtime_error("CouchKVStore::scanAllVersions was invoked");
2382+
}
2383+
23792384
scan_error_t CouchKVStore::scan(ByIdScanContext& ctx) const {
23802385
TRACE_EVENT_START2("CouchKVStore",
23812386
"scan by id",

engines/ep/src/kvstore/couch-kvstore/couch-kvstore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ class CouchKVStore : public KVStore
333333
ValueFilter valOptions) const override;
334334

335335
scan_error_t scan(BySeqnoScanContext& sctx) const override;
336+
scan_error_t scanAllVersions(BySeqnoScanContext& sctx) const override;
336337
scan_error_t scan(ByIdScanContext& sctx) const override;
337338

338339
std::unique_ptr<KVFileHandle> makeFileHandle(Vbid vbid) const override;

engines/ep/src/kvstore/kvstore_iface.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,20 @@ class KVStoreIface {
521521
*/
522522
virtual scan_error_t scan(BySeqnoScanContext& sctx) const = 0;
523523

524+
/**
525+
* Run a BySeqno scan that retrieves all versions of a document from the
526+
* configured "window of history".
527+
*
528+
* This function is only valid to call when the KVStore reports
529+
* StorageProperties::HistoryRetentionAvailable::Yes and that the scan
530+
* is with the range of retained history as reported by
531+
* ScanContext::historyStartSeqno
532+
*
533+
* @param sctx non-const reference to the context, internal callbacks may
534+
* write to the object as progress is made through the scan
535+
*/
536+
virtual scan_error_t scanAllVersions(BySeqnoScanContext& sctx) const = 0;
537+
524538
/**
525539
* Run a ById scan
526540
* @param sctx non-const reference to the context, internal callbacks may

engines/ep/src/kvstore/magma-kvstore/magma-kvstore.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,6 +1805,12 @@ std::unique_ptr<ByIdScanContext> MagmaKVStore::initByIdScanContext(
18051805
return sctx;
18061806
}
18071807

1808+
scan_error_t MagmaKVStore::scanAllVersions(BySeqnoScanContext& ctx) const {
1809+
// @todo use magma's mode
1810+
// return scan(ctx, magma::Magma::SeqIterator::Mode::History);
1811+
return scan(ctx);
1812+
}
1813+
18081814
scan_error_t MagmaKVStore::scan(BySeqnoScanContext& ctx) const {
18091815
if (ctx.lastReadSeqno == ctx.maxSeqno) {
18101816
logger->TRACE("MagmaKVStore::scan {} lastReadSeqno:{} == maxSeqno:{}",

engines/ep/src/kvstore/magma-kvstore/magma-kvstore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ class MagmaKVStore : public KVStore {
233233
ValueFilter valOptions) const override;
234234

235235
scan_error_t scan(BySeqnoScanContext& sctx) const override;
236+
scan_error_t scanAllVersions(BySeqnoScanContext& sctx) const override;
236237
scan_error_t scan(ByIdScanContext& ctx) const override;
237238

238239
std::unique_ptr<KVFileHandle> makeFileHandle(Vbid vbid) const override;

engines/ep/src/kvstore/nexus-kvstore/nexus-kvstore.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,6 +2789,10 @@ scan_error_t NexusKVStore::scan(BySeqnoScanContext& ctx) const {
27892789
return primaryScanResult;
27902790
}
27912791

2792+
scan_error_t NexusKVStore::scanAllVersions(BySeqnoScanContext& ctx) const {
2793+
throw std::runtime_error("NexusKVStore::scanAllVersions unimplemented");
2794+
}
2795+
27922796
scan_error_t NexusKVStore::scan(ByIdScanContext& ctx) const {
27932797
auto& nexusCtx = dynamic_cast<NexusKVStoreByIdScanContext&>(ctx);
27942798
auto& primaryCtx = *nexusCtx.primaryCtx;

engines/ep/src/kvstore/nexus-kvstore/nexus-kvstore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class NexusKVStore : public KVStoreIface {
103103
DocumentFilter options,
104104
ValueFilter valOptions) const override;
105105
scan_error_t scan(BySeqnoScanContext& sctx) const override;
106+
scan_error_t scanAllVersions(BySeqnoScanContext& sctx) const override;
106107
scan_error_t scan(ByIdScanContext& sctx) const override;
107108
std::unique_ptr<KVFileHandle> makeFileHandle(Vbid vbid) const override;
108109
std::pair<GetCollectionStatsStatus, Collections::VB::PersistedStats>

engines/ep/src/kvstore/rocksdb-kvstore/rocksdb-kvstore.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,11 @@ class RocksDBKVStore : public KVStore {
276276
}
277277

278278
scan_error_t scan(BySeqnoScanContext& sctx) const override;
279+
280+
scan_error_t scanAllVersions(BySeqnoScanContext& sctx) const override {
281+
throw std::runtime_error("RocksDB no support for scanAllVersions");
282+
}
283+
279284
scan_error_t scan(ByIdScanContext& sctx) const override {
280285
throw std::runtime_error("RocksDB no support for byID scan");
281286
}

engines/ep/tests/mock/mock_kvstore.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ class MockKVStore : public KVStore {
158158
scan,
159159
(BySeqnoScanContext & sctx),
160160
(const, override));
161+
MOCK_METHOD(scan_error_t,
162+
scanAllVersions,
163+
(BySeqnoScanContext & sctx),
164+
(const, override));
161165
MOCK_METHOD(scan_error_t,
162166
scan,
163167
(ByIdScanContext & sctx),

engines/ep/tests/module_tests/magma-kvstore_test.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ class MagmaKVStoreTest : public KVStoreTest {
5757
rollbackTest = true;
5858
}
5959

60+
queued_item doWrite(uint64_t seqno,
61+
bool expected,
62+
const std::string& key = "key") {
63+
auto ctx =
64+
kvstore->begin(vbid, std::make_unique<PersistenceCallback>());
65+
auto qi = makeCommittedItem(makeStoredDocKey(key),
66+
"value" + std::to_string(seqno));
67+
qi->setBySeqno(seqno);
68+
flush.proposedVBState.lastSnapStart = seqno;
69+
flush.proposedVBState.lastSnapEnd = seqno;
70+
kvstore->set(*ctx, qi);
71+
EXPECT_EQ(expected, kvstore->commit(std::move(ctx), flush));
72+
return qi;
73+
};
74+
6075
private:
6176
bool rollbackTest{false};
6277
};
@@ -697,4 +712,34 @@ TEST_F(MagmaKVStoreTest, makeFileHandleSyncFailed) {
697712
setupSyncStatus(magma::Status(magma::Status::Internal, "Internal"));
698713
fileHandle = kvstore->makeFileHandle(vbid);
699714
EXPECT_FALSE(fileHandle);
715+
}
716+
717+
// @todo: This is a basic test that will be expanded to cover scanning history
718+
// at the moment this test is equivalent to "scan"
719+
TEST_F(MagmaKVStoreTest, scanAllVersions) {
720+
initialize_kv_store(kvstore.get(), vbid);
721+
std::vector<queued_item> expectedItems;
722+
expectedItems.push_back(doWrite(1, true, "k1"));
723+
expectedItems.push_back(doWrite(2, true, "k2"));
724+
auto validate = [&expectedItems](GetValue gv) {
725+
ASSERT_TRUE(gv.item);
726+
ASSERT_GE(expectedItems.size(), size_t(gv.item->getBySeqno()));
727+
EXPECT_EQ(*expectedItems[gv.item->getBySeqno() - 1], *gv.item);
728+
};
729+
auto bySeq = kvstore->initBySeqnoScanContext(
730+
std::make_unique<CustomCallback<GetValue>>(validate),
731+
std::make_unique<CustomCallback<CacheLookup>>(),
732+
vbid,
733+
1,
734+
DocumentFilter::ALL_ITEMS,
735+
ValueFilter::VALUES_COMPRESSED,
736+
SnapshotSource::Head);
737+
ASSERT_TRUE(bySeq);
738+
// @todo: This must be the expected seqno where history begins
739+
EXPECT_EQ(0, bySeq->historyStartSeqno);
740+
EXPECT_EQ(scan_success, kvstore->scanAllVersions(*bySeq));
741+
742+
auto& cb =
743+
static_cast<CustomCallback<GetValue>&>(bySeq->getValueCallback());
744+
EXPECT_EQ(2, cb.getProcessedCount());
700745
}

0 commit comments

Comments
 (0)