return ENGINE_EINVAL;
}
return acquireEngine(handle)->itemDelete(
- cookie, key, *cas, vbucket, nullptr, nullptr, mut_info);
+ cookie, key, *cas, vbucket, nullptr, mut_info);
}
static void EvpItemRelease(ENGINE_HANDLE* handle,
uint64_t* cas,
ENGINE_STORE_OPERATION operation,
DocumentState document_state) {
- ENGINE_ERROR_CODE err_code = ENGINE_SUCCESS;
auto engine = acquireEngine(handle);
- switch (document_state) {
- case DocumentState::Alive: {
- err_code = engine->store(cookie, itm, cas, operation);
- break;
- }
- case DocumentState::Deleted: {
- Item* item = static_cast<Item*>(itm);
- ItemMetaData itm_meta;
- mutation_descr_t mut_info;
-
- if (!cas) {
- LOG(EXTENSION_LOG_WARNING,
- "EvpStore(): cas ptr passed is null for vb: %" PRIu16,
- item->getVBucketId());
- return ENGINE_EINVAL;
- }
- /* Set the item as deleted */
+ if (document_state == DocumentState::Deleted) {
+ Item* item = static_cast<Item*>(itm);
item->setDeleted();
- *cas = item->getCas();
- err_code = engine->itemDelete(cookie,
- item->getKey(),
- *cas,
- item->getVBucketId(),
- item,
- &itm_meta,
- &mut_info);
- if (err_code == ENGINE_SUCCESS) {
- item->setBySeqno(mut_info.seqno);
- item->setCas(itm_meta.cas);
- item->setFlags(itm_meta.flags);
- item->setExpTime(itm_meta.exptime);
- }
- break;
}
- default:
- return ENGINE_ENOTSUP;
- }
- return err_code;
+
+ return engine->store(cookie, itm, cas, operation);
}
static ENGINE_ERROR_CODE EvpFlush(ENGINE_HANDLE* handle,
ItemMetaData itm_meta;
DocKey key(keyPtr, keylen, docNamespace);
ret = kvBucket->deleteItem(
- key, cas, vbucket, cookie, nullptr, &itm_meta, nullptr);
+ key, cas, vbucket, cookie, &itm_meta, nullptr);
if (ret == ENGINE_SUCCESS) {
++stats.numOpsDelRetMeta;
}
* @param cas CAS value of the mutation that needs to be returned
* back to the client
* @param vbucket vbucket id to which the deleted key corresponds to
- * @param itm item pointer that contains a value that needs to be
- * stored along with a delete. A NULL pointer indicates
- * that no value needs to be stored with the delete.
* @param item_meta pointer to item meta data that needs to be
* as a result the delete. A NULL pointer indicates
* that no meta data needs to be returned.
const DocKey& key,
uint64_t& cas,
uint16_t vbucket,
- Item* itm,
ItemMetaData* item_meta,
mutation_descr_t* mut_info) {
ENGINE_ERROR_CODE ret = kvBucket->deleteItem(key,
cas,
vbucket,
cookie,
- itm,
item_meta,
mut_info);
uint64_t& cas,
uint16_t vbucket,
const void* cookie,
- Item* itm,
ItemMetaData* itemMeta,
mutation_descr_t* mutInfo) {
VBucketPtr vb = getVBucket(vbucket);
cookie,
engine,
bgFetchDelay,
- itm,
itemMeta,
mutInfo);
}
uint64_t& cas,
uint16_t vbucket,
const void* cookie,
- Item* itm,
ItemMetaData* itemMeta,
mutation_descr_t* mutInfo);
* @param[in, out] cas the CAS ID for a CASed delete (0 to override)
* @param vbucket the vbucket for the key
* @param cookie the cookie representing the client
- * @param itm item holding a deleted value. A NULL value is passed
- if an empty body is to be used for deletion.
* @param[out] itemMeta the pointer to the metadata memory.
* @param[out] mutInfo mutation information
*
uint64_t& cas,
uint16_t vbucket,
const void* cookie,
- Item* itm,
ItemMetaData* itemMeta,
mutation_descr_t* mutInfo) = 0;
const void* cookie,
EventuallyPersistentEngine& engine,
const int bgFetchDelay,
- Item* itm,
ItemMetaData* itemMeta,
mutation_descr_t* mutInfo) {
auto hbl = ht.getLockedBucket(key);
StoredValue* v = ht.unlocked_find(
key, hbl.getBucketNum(), WantsDeleted::Yes, TrackReference::No);
- if (!itm) {
- if (!v || v->isDeleted() || v->isTempItem()) {
- if (eviction == VALUE_ONLY) {
- return ENGINE_KEY_ENOENT;
- } else { // Full eviction.
- if (!v) { // Item might be evicted from cache.
- if (maybeKeyExistsInFilter(key)) {
- return addTempItemAndBGFetch(
- hbl, key, cookie, engine, bgFetchDelay, true);
- } else {
- // As bloomfilter predicted that item surely doesn't
- // exist on disk, return ENOENT for deleteItem().
- return ENGINE_KEY_ENOENT;
- }
- } else if (v->isTempInitialItem()) {
- hbl.getHTLock().unlock();
- bgFetch(key, cookie, engine, bgFetchDelay, true);
- return ENGINE_EWOULDBLOCK;
- } else { // Non-existent or deleted key.
- if (v->isTempNonExistentItem() || v->isTempDeletedItem()) {
- // Delete a temp non-existent item to ensure that
- // if a delete were issued over an item that doesn't
- // exist, then we don't preserve a temp item.
- deleteStoredValue(hbl, *v);
- }
+ if (!v || v->isDeleted() || v->isTempItem()) {
+ if (eviction == VALUE_ONLY) {
+ return ENGINE_KEY_ENOENT;
+ } else { // Full eviction.
+ if (!v) { // Item might be evicted from cache.
+ if (maybeKeyExistsInFilter(key)) {
+ return addTempItemAndBGFetch(
+ hbl, key, cookie, engine, bgFetchDelay, true);
+ } else {
+ // As bloomfilter predicted that item surely doesn't
+ // exist on disk, return ENOENT for deleteItem().
return ENGINE_KEY_ENOENT;
}
- }
- }
- } else {
- /* if an item containing a deleted value is present, set the value
- * as part of the stored value so that a value is set as part of the
- * delete.
- */
- if (v) {
- if (cas != 0 && cas != v->getCas()) {
- return ENGINE_KEY_EEXISTS;
- }
- itm->setRevSeqno(v->getRevSeqno());
- v->setValue(*itm, ht);
- } else {
- /* retrieve the item, if it is present in disk, for CAS comparison */
- if (maybeKeyExistsInFilter(key)) {
- return addTempItemAndBGFetch(
- hbl, key, cookie, engine, bgFetchDelay, true);
- } else {
- AddStatus rv = addTempStoredValue(hbl, key);
- if (rv == AddStatus::NoMem) {
- return ENGINE_ENOMEM;
+ } else if (v->isTempInitialItem()) {
+ hbl.getHTLock().unlock();
+ bgFetch(key, cookie, engine, bgFetchDelay, true);
+ return ENGINE_EWOULDBLOCK;
+ } else { // Non-existent or deleted key.
+ if (v->isTempNonExistentItem() || v->isTempDeletedItem()) {
+ // Delete a temp non-existent item to ensure that
+ // if a delete were issued over an item that doesn't
+ // exist, then we don't preserve a temp item.
+ deleteStoredValue(hbl, *v);
}
- v = ht.unlocked_find(key,
- hbl.getBucketNum(),
- WantsDeleted::Yes,
- TrackReference::No);
- v->setValue(*itm, ht);
- /* Due to the above setValue() v is no longer a temp stored value*/
+ return ENGINE_KEY_ENOENT;
}
}
}
/* allow operation*/
v->unlock();
} else if (cas && cas != v->getCas()) {
- if (v->isTempDeletedItem() || v->isTempNonExistentItem() ||
- v->isDeleted()) {
+ if (v->isTempNonExistentItem()) {
+ // This is a temporary item which marks a key as non-existent;
+ // therefore specifying a non-matching CAS should be exposed
+ // as item not existing.
+ return {MutationStatus::NotFound, VBNotifyCtx()};
+ }
+ if ((v->isTempDeletedItem() || v->isDeleted()) && !itm.isDeleted()) {
+ // Existing item is deleted, and we are not replacing it with
+ // a (different) deleted value - return not existing.
return {MutationStatus::NotFound, VBNotifyCtx()};
}
+ // None of the above special cases; the existing item cannot be
+ // modified with the specified CAS.
return {MutationStatus::InvalidCas, VBNotifyCtx()};
}
if (!hasMetaData) {
* @param cookie the cookie representing the client to store the item
* @param engine Reference to ep engine
* @param bgFetchDelay
- * @param itm item pointer that contains a value that needs to be
- * stored along with a delete. A NULL pointer indicates
- * that no value needs to be stored with the delete.
* @param[out] itemMeta pointer to item meta data that needs to be returned
* as a result the delete. A NULL pointer indicates
* that no meta data needs to be returned.
const void* cookie,
EventuallyPersistentEngine& engine,
int bgFetchDelay,
- Item* itm,
ItemMetaData* itemMeta,
mutation_descr_t* mutInfo);
cas,
vbid,
/*cookie*/ nullptr,
- /*Item*/ nullptr,
/*itemMeta*/ nullptr,
/*mutation_descr_t*/ nullptr));
if (flush_before_rollback) {
cas,
vbid,
cookie,
- /*Item*/ nullptr,
/*itemMeta*/ nullptr,
/*mutation_descr_t*/ nullptr));
}
cas,
vbid,
cookie,
- /*Item*/ nullptr,
/*itemMeta*/ nullptr,
/*mutation_descr_t*/ nullptr));
cas,
vbid,
cookie,
- /*Item*/ nullptr,
&itemMeta2,
/*mutation_descr_t*/ nullptr));
0,
cookie,
nullptr,
- nullptr,
nullptr);
vals = get_stat(nullptr);
EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_json,xattr"]));
auto prev_revseqno = v->getRevSeqno();
deleted_item.setRevSeqno(prev_revseqno);
- // Set a new deleted value
- v->setValue(deleted_item, this->vbucket->ht);
-
EXPECT_EQ(MutationStatus::WasDirty,
- this->public_processSoftDelete(v->getKey(), v, 0));
+ this->public_processSet(deleted_item, 0));
verifyValue(key, "deletedvalue", TrackReference::Yes, WantsDeleted::Yes);
EXPECT_EQ(prev_revseqno + 1, v->getRevSeqno());
}
auto prev_revseqno = v->getRevSeqno();
deleted_item.setRevSeqno(prev_revseqno);
- // Set a new deleted value
- v->setValue(deleted_item, this->vbucket->ht);
-
EXPECT_EQ(MutationStatus::WasDirty,
- this->public_processSoftDelete(v->getKey(), v, 0));
+ this->public_processSet(deleted_item, 0));
verifyValue(
key,
"deletedvalue",
prev_revseqno = v->getRevSeqno();
update_deleted_item.setRevSeqno(prev_revseqno);
- // Set a new deleted value
- v->setValue(update_deleted_item, this->vbucket->ht);
-
EXPECT_EQ(MutationStatus::WasDirty,
- this->public_processSoftDelete(v->getKey(), v, 0));
+ this->public_processSet(update_deleted_item, 0));
verifyValue(
key, "updatedeletedvalue", TrackReference::Yes, WantsDeleted::Yes);
EXPECT_EQ(prev_revseqno + 1, v->getRevSeqno());