@@ -1493,10 +1493,9 @@ ENGINE_ERROR_CODE VBucket::set(
14931493 bool cas_op = (itm.getCas () != 0 );
14941494
14951495 { // HashBucketLock scope
1496- auto htRes = itm.isPending () ? ht.findForSyncWrite (itm.getKey ())
1497- : ht.findForWrite (itm.getKey ());
1498- auto * v = htRes.storedValue ;
1499- auto & hbl = htRes.lock ;
1496+ auto htRes = ht.findForCommit (itm.getKey ());
1497+ auto * v = htRes.selectSVToModify (itm);
1498+ auto & hbl = htRes.getHBL ();
15001499
15011500 cb::StoreIfStatus storeIfStatus = cb::StoreIfStatus::Continue;
15021501 if (predicate && (storeIfStatus = callPredicate (predicate, v)) ==
@@ -1533,7 +1532,7 @@ ENGINE_ERROR_CODE VBucket::set(
15331532 queueItmCtx.preLinkDocumentContext = &preLinkDocumentContext;
15341533 MutationStatus status;
15351534 boost::optional<VBNotifyCtx> notifyCtx;
1536- std::tie (status, notifyCtx) = processSet (hbl ,
1535+ std::tie (status, notifyCtx) = processSet (htRes ,
15371536 v,
15381537 itm,
15391538 itm.getCas (),
@@ -1608,10 +1607,13 @@ ENGINE_ERROR_CODE VBucket::replace(
16081607 }
16091608
16101609 { // HashBucketLock scope
1611- auto htRes = itm.isPending () ? ht.findForSyncReplace (itm.getKey ())
1612- : ht.findForWrite (itm.getKey ());
1613- auto * v = htRes.storedValue ;
1614- auto & hbl = htRes.lock ;
1610+ auto htRes = ht.findForCommit (itm.getKey ());
1611+ auto * v = htRes.selectSVToModify (itm);
1612+ auto & hbl = htRes.getHBL ();
1613+
1614+ if (v && v->isCompleted ()) {
1615+ v = nullptr ;
1616+ }
16151617
16161618 cb::StoreIfStatus storeIfStatus = cb::StoreIfStatus::Continue;
16171619 if (predicate && (storeIfStatus = callPredicate (predicate, v)) ==
@@ -1638,7 +1640,7 @@ ENGINE_ERROR_CODE VBucket::replace(
16381640 queueItmCtx.durability =
16391641 DurabilityItemCtx{itm.getDurabilityReqs (), cookie};
16401642 }
1641- std::tie (mtype, notifyCtx) = processSet (hbl ,
1643+ std::tie (mtype, notifyCtx) = processSet (htRes ,
16421644 v,
16431645 itm,
16441646 0 ,
@@ -1706,9 +1708,9 @@ ENGINE_ERROR_CODE VBucket::replace(
17061708ENGINE_ERROR_CODE VBucket::addBackfillItem (
17071709 Item& itm,
17081710 const Collections::VB::Manifest::CachingReadHandle& cHandle) {
1709- auto htRes = ht.findForWrite (itm.getKey ());
1710- auto * v = htRes.storedValue ;
1711- auto & hbl = htRes.lock ;
1711+ auto htRes = ht.findForCommit (itm.getKey ());
1712+ auto * v = htRes.selectSVToModify (itm) ;
1713+ auto & hbl = htRes.getHBL () ;
17121714
17131715 // Note that this function is only called on replica or pending vbuckets.
17141716 if (v && v->isLocked (ep_current_time ())) {
@@ -1725,7 +1727,7 @@ ENGINE_ERROR_CODE VBucket::addBackfillItem(
17251727 nullptr /* No pre link should happen */ };
17261728 MutationStatus status;
17271729 boost::optional<VBNotifyCtx> notifyCtx;
1728- std::tie (status, notifyCtx) = processSet (hbl ,
1730+ std::tie (status, notifyCtx) = processSet (htRes ,
17291731 v,
17301732 itm,
17311733 0 ,
@@ -1798,9 +1800,9 @@ ENGINE_ERROR_CODE VBucket::prepare(
17981800 GenerateBySeqno genBySeqno,
17991801 GenerateCas genCas,
18001802 const Collections::VB::Manifest::CachingReadHandle& cHandle) {
1801- auto htRes = ht.findOnlyPrepared (itm.getKey ());
1802- auto * v = htRes.storedValue ;
1803- auto & hbl = htRes.lock ;
1803+ auto htRes = ht.findForCommit (itm.getKey ());
1804+ auto * v = htRes.pending . getSV () ;
1805+ auto & hbl = htRes.getHBL () ;
18041806 bool maybeKeyExists = true ;
18051807 MutationStatus status;
18061808 boost::optional<VBNotifyCtx> notifyCtx;
@@ -1853,7 +1855,7 @@ ENGINE_ERROR_CODE VBucket::prepare(
18531855 } else {
18541856 // Not a valid duplicate prepare, call processSet and hit the SyncWrite
18551857 // checks.
1856- std::tie (status, notifyCtx) = processSet (hbl ,
1858+ std::tie (status, notifyCtx) = processSet (htRes ,
18571859 v,
18581860 itm,
18591861 cas,
@@ -1924,10 +1926,9 @@ ENGINE_ERROR_CODE VBucket::setWithMeta(
19241926 GenerateBySeqno genBySeqno,
19251927 GenerateCas genCas,
19261928 const Collections::VB::Manifest::CachingReadHandle& cHandle) {
1927- auto htRes = itm.isPending () ? ht.findForSyncWrite (itm.getKey ())
1928- : ht.findForWrite (itm.getKey ());
1929- auto * v = htRes.storedValue ;
1930- auto & hbl = htRes.lock ;
1929+ auto htRes = ht.findForCommit (itm.getKey ());
1930+ auto * v = htRes.selectSVToModify (itm);
1931+ auto & hbl = htRes.getHBL ();
19311932 bool maybeKeyExists = true ;
19321933
19331934 // Effectively ignore logically deleted keys, they cannot stop the op
@@ -1994,7 +1995,7 @@ ENGINE_ERROR_CODE VBucket::setWithMeta(
19941995
19951996 MutationStatus status;
19961997 boost::optional<VBNotifyCtx> notifyCtx;
1997- std::tie (status, notifyCtx) = processSet (hbl ,
1998+ std::tie (status, notifyCtx) = processSet (htRes ,
19981999 v,
19992000 itm,
20002001 cas,
@@ -3124,7 +3125,7 @@ void VBucket::decrDirtyQueuePendingWrites(size_t decrementBy)
31243125}
31253126
31263127std::pair<MutationStatus, boost::optional<VBNotifyCtx>> VBucket::processSet (
3127- const HashTable::HashBucketLock& hbl ,
3128+ HashTable::FindCommitResult& htRes ,
31283129 StoredValue*& v,
31293130 Item& itm,
31303131 uint64_t cas,
@@ -3151,6 +3152,12 @@ std::pair<MutationStatus, boost::optional<VBNotifyCtx>> VBucket::processSet(
31513152 Expects (itm.isCommitted ());
31523153 getPassiveDM ().completeSyncWrite (
31533154 itm.getKey (), PassiveDurabilityMonitor::Resolution::Commit);
3155+
3156+ // @TODO we must remove the prepare and overwrite the mutation if we
3157+ // are replacing a prepare with a mutation
3158+ // Release the pending SV from the SVP that is holding it to prevent
3159+ // a double stat update that would cause a stat underflow exception.
3160+ htRes.pending .release ();
31543161 }
31553162
31563163 // This is a new SyncWrite, we just want to add a new prepare unless we
@@ -3161,12 +3168,12 @@ std::pair<MutationStatus, boost::optional<VBNotifyCtx>> VBucket::processSet(
31613168 // We have to modify the StoredValue pointer passed in or we do not
31623169 // return the correct cas to the client.
31633170 std::tie (v, notifyCtx) = addNewStoredValue (
3164- hbl , itm, queueItmCtx, GenerateRevSeqno::No);
3171+ htRes. getHBL () , itm, queueItmCtx, GenerateRevSeqno::No);
31653172 return {MutationStatus::WasClean, notifyCtx};
31663173 }
31673174 }
31683175
3169- return processSetInner (hbl ,
3176+ return processSetInner (htRes. getHBL () ,
31703177 v,
31713178 itm,
31723179 cas,
0 commit comments