Skip to content

Commit 32119d4

Browse files
jimwwalkerdaverigby
authored andcommitted
MB-35326: Reset cached vbucket_state on VBucket creation
The cached vbucket_state is unconditionally populated with the state of all vbuckets found on disk during bucket creation. However not all vbuckets found will become VBucket objects (dead state vbuckets aren't created), so we may later create new VBucket objects in their default state (e.g. snapshot range of 0,0). Resetting the cached vbucket_state on creation means that the cached state will be consistent with the new VBucket. Change-Id: I122c21f34f1eca129a2ff4bc29f42f96645bb8d2 Reviewed-on: http://review.couchbase.org/112789 Reviewed-by: Dave Rigby <[email protected]> Tested-by: Build Bot <[email protected]>
1 parent 59c4b41 commit 32119d4

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

engines/ep/src/kv_bucket.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,10 @@ ENGINE_ERROR_CODE KVBucket::setVBucketState_UNLOCKED(
10121012
// Before adding the VB to the map increment the revision
10131013
getRWUnderlying(vbid)->incrementRevision(vbid);
10141014

1015+
// Wipe out any cached vbucket state
1016+
getRWUnderlying(vbid)->resetCachedVBState(vbid);
1017+
getROUnderlying(vbid)->resetCachedVBState(vbid);
1018+
10151019
// If active, update the VB from the bucket's collection state.
10161020
// Note: Must be done /before/ adding the new VBucket to vbMap so that
10171021
// it has the correct collections state when it is exposed to operations

engines/ep/src/kvstore.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,15 @@ uint64_t KVStore::getLastPersistedSeqno(Vbid vbid) {
491491

492492
uint64_t KVStore::prepareToDelete(Vbid vbid) {
493493
// MB-34380: We must clear the cached state
494+
resetCachedVBState(vbid);
495+
return prepareToDeleteImpl(vbid);
496+
}
497+
498+
void KVStore::resetCachedVBState(Vbid vbid) {
494499
vbucket_state* state = getVBucketState(vbid);
495500
if (state) {
496501
state->reset();
497502
}
498-
return prepareToDeleteImpl(vbid);
499503
}
500504

501505
void KVStore::setSystemEvent(const Item& item, SetCallback cb) {

engines/ep/src/kvstore.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,13 @@ class KVStore {
909909
*/
910910
uint64_t prepareToDelete(Vbid vbid);
911911

912+
/**
913+
* Call reset on the cached vbucket_state for the given vbucket (if any is
914+
* cached)
915+
* @param vbid ID of the vbucket to reset
916+
*/
917+
void resetCachedVBState(Vbid vbid);
918+
912919
/**
913920
* Set a system event into the KVStore.
914921
* Collection system events will be used to maintain extra meta-data before

engines/ep/tests/module_tests/evp_store_warmup_test.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,37 @@ TEST_P(MB_34718_WarmupTest, getTest) {
12431243
EXPECT_EQ(0, vb->getNumItems());
12441244
}
12451245

1246+
// Perform the sequence of operations which lead to MB-35326, a snapshot range
1247+
// exception. When the issue is fixed this test will pass
1248+
TEST_F(WarmupTest, MB_35326) {
1249+
// 1) Write an item to an active vbucket and flush it.
1250+
// vb state on disk will have a range of {1,1}
1251+
setVBucketStateAndRunPersistTask(vbid, vbucket_state_active);
1252+
auto key = makeStoredDocKey("key");
1253+
store_item(vbid, key, "value");
1254+
flush_vbucket_to_disk(vbid);
1255+
1256+
// 2) Mark the vbucket as dead and persist the state
1257+
setVBucketStateAndRunPersistTask(vbid, vbucket_state_dead);
1258+
1259+
// 3) Warmup - the dead vbucket will be skipped by warmup but KVStore has
1260+
// loaded the state into cachedVBStates
1261+
resetEngineAndWarmup();
1262+
1263+
EXPECT_FALSE(engine->getVBucket(vbid)) << "Dead vbuckets shouldn't warmup";
1264+
1265+
// 4) Now active creation, this results in a new VBucket object with default
1266+
// state, for this issue the snapshot range of {0,0}
1267+
setVBucketStateAndRunPersistTask(vbid, vbucket_state_active);
1268+
1269+
// 5) Store an item and flush, this would crash because we combine the in
1270+
// memory range {0,0} with the on disk range {1,1}, the crash occurs
1271+
// as the new range is {1, 0} and start:1 cannot be greater than end:0.
1272+
store_item(vbid, key, "value");
1273+
1274+
flush_vbucket_to_disk(vbid);
1275+
}
1276+
12461277
INSTANTIATE_TEST_CASE_P(FullOrValue,
12471278
MB_34718_WarmupTest,
12481279
STParameterizedBucketTest::persistentConfigValues(),

0 commit comments

Comments
 (0)