Skip to content

Commit b1c2721

Browse files
BenHuddlestondaverigby
authored andcommitted
MB-34946: Use HashTable::FindCommitResult in processSoftDelete
In a following change, we need to make use of the FindCommitResult in VBucket::processSoftDelete as it contains both the pending and committed StoredValues. To keep a single processSoftDelete interface, update all callers to pass a FindCommitResult instead of a single StoredValue&. Also, add a processSoftDeleteInner function as we will need to modify which StoredValue& v is deleted but assignment is not allowed. Change-Id: I3b7060a111c760a2194b8f5abac6344f5148b656 Reviewed-on: http://review.couchbase.org/111858 Reviewed-by: Dave Rigby <[email protected]> Tested-by: Build Bot <[email protected]>
1 parent 8c4e237 commit b1c2721

File tree

4 files changed

+62
-24
lines changed

4 files changed

+62
-24
lines changed

engines/ep/src/vbucket.cc

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,10 +2077,9 @@ ENGINE_ERROR_CODE VBucket::deleteItem(
20772077
ENGINE_ERROR_CODE ret = durability ? ENGINE_EWOULDBLOCK : ENGINE_SUCCESS;
20782078

20792079
{ // HashBucketLock scope
2080-
auto htRes = durability ? ht.findForSyncWrite(cHandle.getKey())
2081-
: ht.findForWrite(cHandle.getKey());
2082-
auto* v = htRes.storedValue;
2083-
auto& hbl = htRes.lock;
2080+
auto htRes = ht.findForCommit(cHandle.getKey());
2081+
auto* v = htRes.selectSVToModify(durability.is_initialized());
2082+
auto& hbl = htRes.getHBL();
20842083

20852084
if (!v || v->isDeleted() || v->isTempItem() ||
20862085
cHandle.isLogicallyDeleted(v->getBySeqno())) {
@@ -2135,7 +2134,7 @@ ENGINE_ERROR_CODE VBucket::deleteItem(
21352134
queueItmCtx.durability = DurabilityItemCtx{*durability, cookie};
21362135
}
21372136
std::tie(delrv, v, notifyCtx) =
2138-
processSoftDelete(hbl,
2137+
processSoftDelete(htRes,
21392138
*v,
21402139
cas,
21412140
metadata,
@@ -2215,9 +2214,9 @@ ENGINE_ERROR_CODE VBucket::deleteWithMeta(
22152214
const Collections::VB::Manifest::CachingReadHandle& cHandle,
22162215
DeleteSource deleteSource) {
22172216
const auto& key = cHandle.getKey();
2218-
auto htRes = ht.findForWrite(key);
2219-
auto* v = htRes.storedValue;
2220-
auto& hbl = htRes.lock;
2217+
auto htRes = ht.findForCommit(key);
2218+
auto* v = htRes.pending ? htRes.pending.getSV() : htRes.committed;
2219+
auto& hbl = htRes.pending.getHBL();
22212220

22222221
if (v && cHandle.isLogicallyDeleted(v->getBySeqno())) {
22232222
return ENGINE_KEY_ENOENT;
@@ -2317,7 +2316,7 @@ ENGINE_ERROR_CODE VBucket::deleteWithMeta(
23172316
// this is a replication call (i.e. not to an active vbucket),
23182317
// the active has done this and we must just store what we're
23192318
// given.
2320-
std::tie(delrv, v, notifyCtx) = processSoftDelete(hbl,
2319+
std::tie(delrv, v, notifyCtx) = processSoftDelete(htRes,
23212320
*v,
23222321
cas,
23232322
itemMeta,
@@ -3376,15 +3375,14 @@ std::pair<AddStatus, boost::optional<VBNotifyCtx>> VBucket::processAdd(
33763375
}
33773376

33783377
std::tuple<MutationStatus, StoredValue*, boost::optional<VBNotifyCtx>>
3379-
VBucket::processSoftDelete(const HashTable::HashBucketLock& hbl,
3378+
VBucket::processSoftDelete(HashTable::FindCommitResult& htRes,
33803379
StoredValue& v,
33813380
uint64_t cas,
33823381
const ItemMetaData& metadata,
33833382
const VBQueueItemCtx& queueItmCtx,
33843383
bool use_meta,
33853384
uint64_t bySeqno,
33863385
DeleteSource deleteSource) {
3387-
boost::optional<VBNotifyCtx> empty;
33883386
if (v.isPending()) {
33893387
// It is not valid for an active vBucket to attempt to overwrite an
33903388
// in flight SyncWrite. If this vBucket is not active, we are
@@ -3395,14 +3393,40 @@ VBucket::processSoftDelete(const HashTable::HashBucketLock& hbl,
33953393
// missing a prepare. This code allows this mutation to be accepted
33963394
// and overwrites the existing prepare.
33973395
if (getState() == vbucket_state_active || !isReceivingDiskSnapshot()) {
3398-
return {MutationStatus::IsPendingSyncWrite, &v, empty};
3396+
return {MutationStatus::IsPendingSyncWrite, &v, boost::none};
33993397
}
34003398

34013399
getPassiveDM().completeSyncWrite(
34023400
StoredDocKey(v.getKey()),
34033401
PassiveDurabilityMonitor::Resolution::Commit);
3402+
3403+
// @TODO we must remove the prepare and overwrite the mutation if we
3404+
// are replacing a prepare with a mutation
3405+
// Release the pending SV from the SVP that is holding it to prevent
3406+
// a double stat update that would cause a stat underflow exception.
3407+
htRes.pending.release();
34043408
}
34053409

3410+
return processSoftDeleteInner(htRes.getHBL(),
3411+
v,
3412+
cas,
3413+
metadata,
3414+
queueItmCtx,
3415+
use_meta,
3416+
bySeqno,
3417+
deleteSource);
3418+
}
3419+
3420+
std::tuple<MutationStatus, StoredValue*, boost::optional<VBNotifyCtx>>
3421+
VBucket::processSoftDeleteInner(const HashTable::HashBucketLock& hbl,
3422+
StoredValue& v,
3423+
uint64_t cas,
3424+
const ItemMetaData& metadata,
3425+
const VBQueueItemCtx& queueItmCtx,
3426+
bool use_meta,
3427+
uint64_t bySeqno,
3428+
DeleteSource deleteSource) {
3429+
boost::optional<VBNotifyCtx> empty;
34063430
if (v.isTempInitialItem() && eviction == EvictionPolicy::Full) {
34073431
return std::make_tuple(MutationStatus::NeedBgFetch, &v, empty);
34083432
}

engines/ep/src/vbucket.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,8 +1838,8 @@ class VBucket : public std::enable_shared_from_this<VBucket> {
18381838
* in-memory structure like HT, and checkpoint mgr.
18391839
* Assumes that HT bucket lock is grabbed.
18401840
*
1841-
* @param hbl Hash table bucket lock that must be held
1842-
* @param v Reference to the StoredValue to be soft deleted
1841+
* @param htRes Committed and Pending StoredValues
1842+
* @param v Reference to the StoredValue to delete (in the general case)
18431843
* @param cas the expected CAS of the item (or 0 to override)
18441844
* @param metadata ref to item meta data
18451845
* @param queueItmCtx holds info needed to queue an item in chkpt or vb
@@ -1855,15 +1855,27 @@ class VBucket : public std::enable_shared_from_this<VBucket> {
18551855
* notification info, if status was successful.
18561856
*/
18571857
std::tuple<MutationStatus, StoredValue*, boost::optional<VBNotifyCtx>>
1858-
processSoftDelete(const HashTable::HashBucketLock& hbl,
1858+
processSoftDelete(HashTable::FindCommitResult& htRes,
18591859
StoredValue& v,
18601860
uint64_t cas,
18611861
const ItemMetaData& metadata,
18621862
const VBQueueItemCtx& queueItmCtx,
18631863
bool use_meta,
18641864
uint64_t bySeqno,
18651865
DeleteSource deleteSource);
1866-
1866+
/**
1867+
* Inner function for processSoftDelete. Allows overwriting of in-flight
1868+
* prepares.
1869+
*/
1870+
std::tuple<MutationStatus, StoredValue*, boost::optional<VBNotifyCtx>>
1871+
processSoftDeleteInner(const HashTable::HashBucketLock& hbl,
1872+
StoredValue& v,
1873+
uint64_t cas,
1874+
const ItemMetaData& metadata,
1875+
const VBQueueItemCtx& queueItmCtx,
1876+
bool use_meta,
1877+
uint64_t bySeqno,
1878+
DeleteSource deleteSource);
18671879
/**
18681880
* Delete a key (associated StoredValue) from ALL in-memory data structures
18691881
* like HT.

engines/ep/tests/module_tests/vbucket_test.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,27 +228,27 @@ VBucketTestBase::public_processSoftDelete(const DocKey& key,
228228
VBQueueItemCtx ctx) {
229229
// Need to take the collections read handle before the hbl
230230
auto cHandle = vbucket->lockCollections(key);
231-
auto res = ctx.durability ? vbucket->ht.findForSyncWrite(key)
232-
: vbucket->ht.findForWrite(key);
233-
if (!res.storedValue) {
231+
auto htRes = vbucket->ht.findForCommit(key);
232+
auto* v = htRes.selectSVToModify(ctx.durability.is_initialized());
233+
if (!v) {
234234
return {MutationStatus::NotFound, nullptr};
235235
}
236-
if (res.storedValue->isDeleted() && !res.storedValue->isPending()) {
236+
if (v->isDeleted() && !v->isPending()) {
237237
return {MutationStatus::NotFound, nullptr};
238238
}
239-
return public_processSoftDelete(res.lock, *res.storedValue, ctx);
239+
return public_processSoftDelete(htRes, *v, ctx);
240240
}
241241

242242
std::pair<MutationStatus, StoredValue*>
243-
VBucketTestBase::public_processSoftDelete(const HashTable::HashBucketLock& hbl,
243+
VBucketTestBase::public_processSoftDelete(HashTable::FindCommitResult& htRes,
244244
StoredValue& v,
245245
VBQueueItemCtx ctx) {
246246
ItemMetaData metadata;
247247
metadata.revSeqno = v.getRevSeqno() + 1;
248248
MutationStatus status;
249249
StoredValue* deletedSV;
250250
std::tie(status, deletedSV, std::ignore) =
251-
vbucket->processSoftDelete(hbl,
251+
vbucket->processSoftDelete(htRes,
252252
v,
253253
/*cas*/ 0,
254254
metadata,

engines/ep/tests/module_tests/vbucket_test.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ class VBucketTestBase {
112112
std::pair<MutationStatus, StoredValue*> public_processSoftDelete(
113113
const DocKey& key, VBQueueItemCtx ctx = {});
114114
std::pair<MutationStatus, StoredValue*> public_processSoftDelete(
115-
const HashTable::HashBucketLock& hbl, StoredValue& v, VBQueueItemCtx ctx = {});
115+
HashTable::FindCommitResult& htRes,
116+
StoredValue& v,
117+
VBQueueItemCtx ctx = {});
116118

117119
bool public_deleteStoredValue(const DocKey& key);
118120

0 commit comments

Comments
 (0)