@@ -511,11 +511,14 @@ class DurabilityWarmupTest : public DurabilityKVBucketTest {
511511protected:
512512 // Test that a pending SyncWrite/Delete not yet committed is correctly
513513 // warmed up when the bucket restarts.
514- void testPendingSyncWrite (vbucket_state_t vbState, DocumentState docState);
514+ void testPendingSyncWrite (vbucket_state_t vbState,
515+ const std::vector<std::string>& keys,
516+ DocumentState docState);
515517
516518 // Test that a pending SyncWrite/Delete which was committed is correctly
517519 // warmed up when the bucket restarts (as a Committed item).
518520 void testCommittedSyncWrite (vbucket_state_t vbState,
521+ const std::vector<std::string>& keys,
519522 DocumentState docState);
520523
521524 // Test that a committed mutation followed by a pending SyncWrite to the
@@ -579,7 +582,6 @@ DurabilityWarmupTest::PrePostStateChecker::~PrePostStateChecker() {
579582 EXPECT_EQ (preHCS, vb->getHighCompletedSeqno ())
580583 << " PrePostStateChecker: Found that post warmup the HCS does not "
581584 " match the pre-warmup value" ;
582- ;
583585}
584586
585587DurabilityWarmupTest::PrePostStateChecker
@@ -604,124 +606,156 @@ GetValue DurabilityWarmupTest::getItemFetchFromDiskIfNeeded(
604606 return gv;
605607}
606608
607- void DurabilityWarmupTest::testPendingSyncWrite (vbucket_state_t vbState,
608- DocumentState docState) {
609- // Store a pending SyncWrite/Delete (without committing) and then restart
610- auto key = makeStoredDocKey (" key" );
611- auto item = makePendingItem (key, " pending_value" );
612- if (docState == DocumentState::Deleted) {
613- item->setDeleted (DeleteSource::Explicit);
614- }
615- ASSERT_EQ (ENGINE_EWOULDBLOCK, store->set (*item, cookie));
616- flush_vbucket_to_disk (vbid);
609+ void DurabilityWarmupTest::testPendingSyncWrite (
610+ vbucket_state_t vbState,
611+ const std::vector<std::string>& keys,
612+ DocumentState docState) {
613+ // Store the given pending SyncWrites/Deletes (without committing) and then
614+ // restart
617615
618- if (vbState != vbucket_state_active) {
619- setVBucketStateAndRunPersistTask (vbid, vbState);
620- }
621- resetEngineAndWarmup ();
616+ auto vb = engine->getVBucket (vbid);
617+ auto numTracked = vb->getDurabilityMonitor ().getNumTracked ();
622618
623- // Check that attempts to read this key via frontend are blocked.
624- auto gv = store->get (key, vbid, cookie, {});
625- EXPECT_EQ (ENGINE_SYNC_WRITE_RECOMMIT_IN_PROGRESS, gv.getStatus ());
619+ for (const auto & k : keys) {
620+ // Previous runs could have left the VB into a non-active state - must
621+ // be active to perform set().
622+ if (vb->getState () != vbucket_state_active) {
623+ setVBucketToActiveWithValidTopology ();
624+ }
626625
627- // Check that the item is still pending with the correct CAS.
628- auto vb = engine->getVBucket (vbid);
629- auto handle = vb->lockCollections (item->getKey ());
630- auto prepared = vb->fetchPreparedValue (handle);
631- EXPECT_TRUE (prepared.storedValue );
632- EXPECT_TRUE (prepared.storedValue ->isPending ());
633- EXPECT_EQ (item->isDeleted (), prepared.storedValue ->isDeleted ());
634- EXPECT_EQ (item->getCas (), prepared.storedValue ->getCas ());
626+ const auto key = makeStoredDocKey (k);
627+ auto item = makePendingItem (key, " pending_value" );
628+ if (docState == DocumentState::Deleted) {
629+ item->setDeleted (DeleteSource::Explicit);
630+ }
631+ ASSERT_EQ (ENGINE_EWOULDBLOCK, store->set (*item, cookie));
632+ flush_vbucket_to_disk (vbid);
635633
636- // DurabilityMonitor be tracking the prepare.
637- EXPECT_EQ (1 , vb->getDurabilityMonitor ().getNumTracked ());
634+ // Set the state that we want to test
635+ if (vbState != vbucket_state_active) {
636+ setVBucketStateAndRunPersistTask (vbid, vbState);
637+ }
638+
639+ // About to destroy engine; reset vb shared_ptr.
640+ vb.reset ();
641+ resetEngineAndWarmup ();
642+ vb = engine->getVBucket (vbid);
643+
644+ // Check that attempts to read this key via frontend are blocked.
645+ auto gv = store->get (key, vbid, cookie, {});
646+ EXPECT_EQ (ENGINE_SYNC_WRITE_RECOMMIT_IN_PROGRESS, gv.getStatus ());
647+
648+ // Check that the item is still pending with the correct CAS.
649+ auto handle = vb->lockCollections (item->getKey ());
650+ auto prepared = vb->fetchPreparedValue (handle);
651+ EXPECT_TRUE (prepared.storedValue );
652+ EXPECT_TRUE (prepared.storedValue ->isPending ());
653+ EXPECT_EQ (item->isDeleted (), prepared.storedValue ->isDeleted ());
654+ EXPECT_EQ (item->getCas (), prepared.storedValue ->getCas ());
655+
656+ // DurabilityMonitor be tracking the prepare.
657+ EXPECT_EQ (++numTracked, vb->getDurabilityMonitor ().getNumTracked ());
658+ }
638659}
639660
640661TEST_P (DurabilityWarmupTest, ActivePendingSyncWrite) {
641- testPendingSyncWrite (vbucket_state_active, DocumentState::Alive);
662+ testPendingSyncWrite (vbucket_state_active,
663+ {" key1" , " key2" , " key3" },
664+ DocumentState::Alive);
642665}
643666
644667TEST_P (DurabilityWarmupTest, ActivePendingSyncDelete) {
645- testPendingSyncWrite (vbucket_state_active, DocumentState::Deleted);
668+ testPendingSyncWrite (vbucket_state_active,
669+ {" key1" , " key2" , " key3" },
670+ DocumentState::Deleted);
646671}
647672
648673TEST_P (DurabilityWarmupTest, ReplicaPendingSyncWrite) {
649- testPendingSyncWrite (vbucket_state_replica, DocumentState::Alive);
674+ testPendingSyncWrite (vbucket_state_replica,
675+ {" key1" , " key2" , " key3" },
676+ DocumentState::Alive);
650677}
651678
652679TEST_P (DurabilityWarmupTest, ReplicaPendingSyncDelete) {
653- testPendingSyncWrite (vbucket_state_replica, DocumentState::Deleted);
680+ testPendingSyncWrite (vbucket_state_replica,
681+ {" key1" , " key2" , " key3" },
682+ DocumentState::Deleted);
654683}
655- void DurabilityWarmupTest::testCommittedSyncWrite (vbucket_state_t vbState,
656- DocumentState docState) {
657- // prepare & commit a SyncWrite then restart.
658- auto key = makeStoredDocKey (" key" );
659- auto item = makePendingItem (key, " value" );
660- if (docState == DocumentState::Deleted) {
661- item->setDeleted (DeleteSource::Explicit);
662- }
663- ASSERT_EQ (ENGINE_EWOULDBLOCK, store->set (*item, cookie));
664- flush_vbucket_to_disk (vbid);
684+ void DurabilityWarmupTest::testCommittedSyncWrite (
685+ vbucket_state_t vbState,
686+ const std::vector<std::string>& keys,
687+ DocumentState docState) {
688+ // Prepare
689+ testPendingSyncWrite (vbState, keys, docState);
665690
666- { // scoping vb - is invalid once resetEngineAndWarmup() is called.
667- auto vb = engine->getVBucket (vbid);
668- EXPECT_EQ (ENGINE_SUCCESS,
669- vb->seqnoAcknowledged (
670- folly::SharedMutex::ReadHolder (vb->getStateLock ()),
671- " replica" ,
672- vb->getHighPreparedSeqno ()));
691+ auto vb = engine->getVBucket (vbid);
692+ auto numTracked = vb->getDurabilityMonitor ().getNumTracked ();
693+ ASSERT_EQ (keys.size (), numTracked);
694+
695+ auto prepareSeqno = 1 ;
696+ for (const auto & k : keys) {
697+ // Commit
698+ const auto key = makeStoredDocKey (k);
699+ if (vbState == vbucket_state_active) {
700+ // Commit on active is driven by the ADM so we need to drive our
701+ // commit via seqno ack
702+ EXPECT_EQ (ENGINE_SUCCESS,
703+ vb->seqnoAcknowledged (folly::SharedMutex::ReadHolder (
704+ vb->getStateLock ()),
705+ " replica" ,
706+ prepareSeqno++));
707+ } else {
708+ // Commit on non-active is driven by VBucket::commit
709+ vb->commit (key, prepareSeqno++, {}, vb->lockCollections (key));
710+ }
673711
674712 flush_vbucket_to_disk (vbid, 1 );
675- }
676713
677- if (vbState != vbucket_state_active) {
678- setVBucketStateAndRunPersistTask (vbid, vbState);
679- }
714+ if (vbState != vbucket_state_active) {
715+ setVBucketStateAndRunPersistTask (vbid, vbState);
716+ }
680717
681- const auto expectedItem = getItemFetchFromDiskIfNeeded (key, docState);
682- ASSERT_EQ (ENGINE_SUCCESS, expectedItem.getStatus ());
718+ const auto expectedItem = getItemFetchFromDiskIfNeeded (key, docState);
719+ ASSERT_EQ (ENGINE_SUCCESS, expectedItem.getStatus ());
683720
684- resetEngineAndWarmup ();
685-
686- // Check that the item is CommittedviaPrepare.
687- auto vb = engine->getVBucket (vbid);
688- // @TODO: RocksDB currently only has an estimated item count in
689- // full-eviction, so it fails this check. Skip if RocksDB && full_eviction.
690- if ((std::get<0 >(GetParam ()).find (" Rocksdb" ) == std::string::npos) ||
691- std::get<0 >(GetParam ()) == " value_only" ) {
692- const auto expectedNumItems = docState == DocumentState::Alive ? 1 : 0 ;
693- EXPECT_EQ (expectedNumItems, vb->getNumItems ());
694- }
721+ // About to destroy engine; reset vb shared_ptr.
722+ vb.reset ();
723+ resetEngineAndWarmup ();
724+ vb = engine->getVBucket (vbid);
695725
696- GetValue gv = getItemFetchFromDiskIfNeeded (item->getKey (), docState);
697- EXPECT_EQ (ENGINE_SUCCESS, gv.getStatus ());
698- EXPECT_EQ (CommittedState::CommittedViaPrepare, gv.item ->getCommitted ());
699- EXPECT_EQ (*expectedItem.item , *gv.item );
726+ // Check that the item is CommittedviaPrepare.
727+ GetValue gv = getItemFetchFromDiskIfNeeded (key, docState);
728+ EXPECT_EQ (ENGINE_SUCCESS, gv.getStatus ());
729+ EXPECT_EQ (CommittedState::CommittedViaPrepare, gv.item ->getCommitted ());
730+ EXPECT_EQ (*expectedItem.item , *gv.item );
700731
701- // DurabilityMonitor should be empty as no outstanding prepares.
702- EXPECT_EQ (0 , vb->getDurabilityMonitor ().getNumTracked ());
732+ // DurabilityMonitor should be empty as no outstanding prepares.
733+ EXPECT_EQ (--numTracked, vb->getDurabilityMonitor ().getNumTracked ());
734+ }
703735}
704736
705737TEST_P (DurabilityWarmupTest, ActiveCommittedSyncWrite) {
706- testCommittedSyncWrite (vbucket_state_active, DocumentState::Alive);
707- // Run the test again to verify that item counts are correct after we
708- // overwrite the original prepare and commit
709- testCommittedSyncWrite (vbucket_state_active, DocumentState::Alive);
738+ testCommittedSyncWrite (vbucket_state_active,
739+ {" key1" , " key2" , " key3" },
740+ DocumentState::Alive);
710741}
711742
712743TEST_P (DurabilityWarmupTest, ActiveCommittedSyncDelete) {
713- testCommittedSyncWrite (vbucket_state_active, DocumentState::Deleted);
714- // Run the test again to verify that item counts are correct after we
715- // overwrite the original prepare and commit
716- testCommittedSyncWrite (vbucket_state_active, DocumentState::Deleted);
744+ testCommittedSyncWrite (vbucket_state_active,
745+ {" key1" , " key2" , " key3" },
746+ DocumentState::Deleted);
717747}
718748
719749TEST_P (DurabilityWarmupTest, ReplicaCommittedSyncWrite) {
720- testCommittedSyncWrite (vbucket_state_replica, DocumentState::Alive);
750+ testCommittedSyncWrite (vbucket_state_replica,
751+ {" key1" , " key2" , " key3" },
752+ DocumentState::Alive);
721753}
722754
723755TEST_P (DurabilityWarmupTest, ReplicaCommittedSyncDelete) {
724- testCommittedSyncWrite (vbucket_state_replica, DocumentState::Deleted);
756+ testCommittedSyncWrite (vbucket_state_replica,
757+ {" key1" , " key2" , " key3" },
758+ DocumentState::Deleted);
725759}
726760
727761void DurabilityWarmupTest::testCommittedAndPendingSyncWrite (
0 commit comments