5252#include " tests/test_fileops.h"
5353#include " vbucket_state.h"
5454#include " vbucket_bgfetch_item.h"
55+ #include " warmup.h"
5556
5657#include " ../couchstore/src/internal.h"
5758
@@ -4903,6 +4904,119 @@ void STParamPersistentBucketTest::testAbortDoesNotIncrementOpsDelete(
49034904 EXPECT_EQ (0 , vb.opsDelete );
49044905}
49054906
4907+
4908+ void STParamPersistentBucketTest::testFailoverTableEntryPersistedAtWarmup (std::function<void ()> testFunction) {
4909+ // 1) Store something so we can expire it later
4910+ engine->getKVBucket ()->setVBucketState (vbid, vbucket_state_active);
4911+ auto vb = engine->getKVBucket ()->getVBucket (vbid);
4912+
4913+ // Grab initialUuid for testing
4914+ auto initialUuid = vb->failovers ->getLatestUUID ();
4915+
4916+ auto key = makeStoredDocKey (" key" );
4917+ store_item (vbid, key, " value" , 1 /* expiryTime*/ );
4918+ flushVBucketToDiskIfPersistent (vbid, 1 );
4919+ EXPECT_EQ (1 , vb->getHighSeqno ());
4920+
4921+ // 2) Restart as though we had an unclean shutdown (creating a new failover
4922+ // table entry) and run the warmup up to the point of completion.
4923+ vb.reset ();
4924+ resetEngineAndEnableWarmup ();
4925+
4926+ auto & readerQueue = *task_executor->getLpTaskQ ()[READER_TASK_IDX];
4927+ auto * warmup = engine->getKVBucket ()->getWarmup ();
4928+ ASSERT_TRUE (warmup);
4929+
4930+ // Warmup - load everything but don't run the complete phase which schedules
4931+ // persistence of the vBucket state (new failover entry)
4932+ while (warmup->getWarmupState () != WarmupState::State::Done) {
4933+ runNextTask (readerQueue);
4934+ }
4935+
4936+ // 3) Test
4937+ testFunction ();
4938+
4939+ // New high seqno
4940+ vb = engine->getKVBucket ()->getVBucket (vbid);
4941+ EXPECT_EQ (2 , vb->getHighSeqno ());
4942+
4943+ // Flush the expiry
4944+ flushVBucketToDiskIfPersistent (vbid, 1 );
4945+
4946+ // Verify that the item has been expired
4947+ auto options = static_cast <get_options_t >(
4948+ QUEUE_BG_FETCH | HONOR_STATES | TRACK_REFERENCE | DELETE_TEMP |
4949+ HIDE_LOCKED_CAS | TRACK_STATISTICS);
4950+ auto gv = store->get (key, vbid, cookie, options);
4951+
4952+ if (gv.getStatus () == ENGINE_EWOULDBLOCK) {
4953+ runBGFetcherTask ();
4954+ gv = store->get (key, vbid, cookie, options);
4955+ }
4956+
4957+ EXPECT_EQ (ENGINE_KEY_ENOENT, gv.getStatus ());
4958+
4959+ // Get our new uuid now
4960+ auto secondUuid = vb->failovers ->getLatestUUID ();
4961+ ASSERT_NE (initialUuid, secondUuid);
4962+
4963+ // "Complete" the warmup or the test will get stuck shutting down, we won't
4964+ // actually flush the new vb state though so we're still testing as though
4965+ // this didn't happen
4966+ runNextTask (readerQueue);
4967+
4968+ // 4) Restart again
4969+ vb.reset ();
4970+ resetEngineAndWarmup ();
4971+
4972+ // 5) The test - uuid should have both of the previous entries
4973+ vb = engine->getKVBucket ()->getVBucket (vbid);
4974+
4975+ auto failovers = vb->failovers ->getFailoverLog ();
4976+ auto itr = std::find_if (failovers.begin (), failovers.end (), [&initialUuid](const auto & failoverEntry) {
4977+ return failoverEntry.uuid == initialUuid;
4978+ });
4979+ EXPECT_NE (itr, failovers.end ());
4980+
4981+ itr = std::find_if (failovers.begin (), failovers.end (), [&secondUuid](const auto & failoverEntry) {
4982+ return failoverEntry.uuid == secondUuid;
4983+ });
4984+ EXPECT_NE (itr, failovers.end ());
4985+
4986+ EXPECT_EQ (2 , vb->getHighSeqno ());
4987+ gv = store->get (key, vbid, cookie, options);
4988+
4989+ if (gv.getStatus () == ENGINE_EWOULDBLOCK) {
4990+ runBGFetcherTask ();
4991+ gv = store->get (key, vbid, cookie, options);
4992+ }
4993+ }
4994+
4995+ TEST_P (STParamPersistentBucketTest, TestExpiryDueToCompactionPersistsFailoverTableEntryDuringWarmup) {
4996+ testFailoverTableEntryPersistedAtWarmup ([this ]() {
4997+ CompactionConfig config;
4998+ engine->compactDB (vbid, config, cookie);
4999+ std::string taskDescription =
5000+ " Compact DB file " + std::to_string (vbid.get ());
5001+ runNextTask (*task_executor->getLpTaskQ ()[WRITER_TASK_IDX], taskDescription);
5002+ });
5003+ }
5004+
5005+ TEST_P (STParamPersistentBucketTest, TestExpiryDueToGetPersistsFailoverTableEntryDuringWarmup) {
5006+ testFailoverTableEntryPersistedAtWarmup ([this ]() {
5007+ auto options = static_cast <get_options_t >(
5008+ QUEUE_BG_FETCH | HONOR_STATES | TRACK_REFERENCE | DELETE_TEMP |
5009+ HIDE_LOCKED_CAS | TRACK_STATISTICS);
5010+ auto key = makeStoredDocKey (" key" );
5011+ auto gv = store->get (key, vbid, cookie, options);
5012+
5013+ if (gv.getStatus () == ENGINE_EWOULDBLOCK) {
5014+ runBGFetcherTask ();
5015+ gv = store->get (key, vbid, cookie, options);
5016+ }
5017+ });
5018+ }
5019+
49065020TEST_P (STParamPersistentBucketTest, AbortDoesNotIncrementOpsDelete) {
49075021 testAbortDoesNotIncrementOpsDelete (true /* flusherDedup*/ );
49085022}
@@ -4992,4 +5106,4 @@ TEST_P(STParamPersistentBucketTest, ExpiryFindsPrepareWithSameCas) {
49925106INSTANTIATE_TEST_CASE_P (Persistent,
49935107 STParamPersistentBucketTest,
49945108 STParameterizedBucketTest::persistentConfigValues (),
4995- STParameterizedBucketTest::PrintToStringParamName);
5109+ STParameterizedBucketTest::PrintToStringParamName);
0 commit comments