MB-21143: Don't store conflict resolution mode per document 55/67955/9
authorJim Walker <jim@couchbase.com>
Fri, 23 Sep 2016 13:45:40 +0000 (14:45 +0100)
committerDave Rigby <daver@couchbase.com>
Wed, 12 Oct 2016 07:42:09 +0000 (07:42 +0000)
Disk and memory have storage on a per document basis for the
conflict resolution mode.

LWW is now enabled globally so this meta data is wasted.

Change-Id: I7b54a96f453b4182e0976e6c18cb48ac964e5177
Reviewed-on: http://review.couchbase.org/67955
Reviewed-by: Dave Rigby <daver@couchbase.com>
Tested-by: buildbot <build@couchbase.com>
20 files changed:
src/couch-kvstore/couch-kvstore.cc
src/couch-kvstore/couch-kvstore.h
src/dcp/stream.cc
src/dcp/stream.h
src/ep.cc
src/ep.h
src/ep_engine.cc
src/ext_meta_parser.cc
src/ext_meta_parser.h
src/forest-kvstore/forest-kvstore.cc
src/forest-kvstore/forest-kvstore.h
src/item.h
src/stored-value.cc
src/stored-value.h
tests/ep_test_apis.cc
tests/ep_test_apis.h
tests/ep_testsuite.cc
tests/ep_testsuite_dcp.cc
tests/ep_testsuite_xdcr.cc
tests/module_tests/kvstore_test.cc

index 9b4d1cc..1883b46 100644 (file)
@@ -56,10 +56,17 @@ using namespace CouchbaseDirectoryUtilities;
 
 static const int MAX_OPEN_DB_RETRY = 10;
 
+/*
+ * MetaData warning
+ * Sherlock began storing an extra byte of data (taking meta_len to 19 bytes).
+ * Watson (4.6) removes this byte as it is never utilised.
+ *
+ * WARNING: any *new* meta-data we wish to store may cause upgrade trouble if it
+ * takes the length to 19 bytes.
+ */
 static const uint32_t DEFAULT_META_LEN = 16;
 static const uint32_t V1_META_LEN = 18;
-static const uint32_t V2_META_LEN = 19;
-
+#define UNUSED_V2_LEN 19
 
 extern "C" {
     static int recordDbDumpC(Db *db, DocInfo *docinfo, void *ctx)
@@ -182,7 +189,6 @@ CouchRequest::CouchRequest(const Item &it, uint64_t rev,
     uint32_t flags = it.getFlags();
     uint32_t vlen = it.getNBytes();
     uint32_t exptime = it.getExptime();
-    uint8_t confresmode = static_cast<uint8_t>(it.getConflictResMode());
 
     // Datatype used to determine whether document requires compression or not
     uint8_t datatype;
@@ -222,8 +228,6 @@ CouchRequest::CouchRequest(const Item &it, uint64_t rev,
         memcpy(meta + DEFAULT_META_LEN + FLEX_DATA_OFFSET, it.getExtMeta(),
                it.getExtMetaLen());
     }
-    memcpy(meta + DEFAULT_META_LEN + FLEX_DATA_OFFSET + EXT_META_LEN,
-           &confresmode, CONFLICT_RES_META_LEN);
 
     dbDocInfo.db_seq = it.getBySeqno();
     dbDocInfo.rev_meta.buf = reinterpret_cast<char *>(meta);
@@ -615,9 +619,8 @@ static std::string getDBFileName(const std::string &dbname,
 
 static int edit_docinfo_hook(DocInfo **info, const sized_buf *item) {
     if ((*info)->rev_meta.size == DEFAULT_META_LEN) {
-        // Metadata doesn't have flex_meta_code, datatype and
-        // conflict_resolution_mode, provision space for
-        // these paramenters.
+        // Metadata doesn't have flex_meta_code and datatype so provision space
+        // for these paramenters.
         const unsigned char* data;
         bool ret;
         if (((*info)->content_meta | COUCH_DOC_IS_COMPRESSED) ==
@@ -664,9 +667,6 @@ static int edit_docinfo_hook(DocInfo **info, const sized_buf *item) {
                &flex_code, FLEX_DATA_OFFSET);
         memcpy(extra + (*info)->rev_meta.size + FLEX_DATA_OFFSET,
                &datatype, sizeof(uint8_t));
-        uint8_t conflict_resolution_mode = revision_seqno;
-        memcpy(extra + (*info)->rev_meta.size + FLEX_DATA_OFFSET + EXT_META_LEN,
-               &conflict_resolution_mode, sizeof(uint8_t));
         docinfo->rev_meta.buf = extra;
         docinfo->rev_meta.size = (*info)->rev_meta.size +
                                  FLEX_DATA_OFFSET + EXT_META_LEN +
@@ -682,44 +682,6 @@ static int edit_docinfo_hook(DocInfo **info, const sized_buf *item) {
         couchstore_free_docinfo(*info);
         *info = docinfo;
         return 1;
-    } else if ((*info)->rev_meta.size == V1_META_LEN) {
-        // Metadata doesn't have conflict_resolution_mode,
-        // provision space for this flag.
-        DocInfo *docinfo = (DocInfo *) cb_calloc(1,
-                                               sizeof(DocInfo) +
-                                               (*info)->id.size +
-                                               (*info)->rev_meta.size +
-                                               sizeof(uint8_t));
-        if (!docinfo) {
-            LOG(EXTENSION_LOG_WARNING, "Failed to allocate docInfo, "
-                    "while editing docinfo in the compaction's docinfo_hook");
-            return 0;
-        }
-
-        char *extra = (char *)docinfo + sizeof(DocInfo);
-        memcpy(extra, (*info)->id.buf, (*info)->id.size);
-        docinfo->id.buf = extra;
-        docinfo->id.size = (*info)->id.size;
-
-        extra += (*info)->id.size;
-        memcpy(extra, (*info)->rev_meta.buf, (*info)->rev_meta.size);
-        uint8_t conflict_resolution_mode = revision_seqno;
-        memcpy(extra + (*info)->rev_meta.size,
-               &conflict_resolution_mode, sizeof(uint8_t));
-        docinfo->rev_meta.buf = extra;
-        docinfo->rev_meta.size = (*info)->rev_meta.size +
-                                 sizeof(uint8_t);
-
-        docinfo->db_seq = (*info)->db_seq;
-        docinfo->rev_seq = (*info)->rev_seq;
-        docinfo->deleted = (*info)->deleted;
-        docinfo->content_meta = (*info)->content_meta;
-        docinfo->bp = (*info)->bp;
-        docinfo->size = (*info)->size;
-
-        couchstore_free_docinfo(*info);
-        *info = docinfo;
-        return 1;
     }
     return 0;
 }
@@ -1467,7 +1429,6 @@ couchstore_error_t CouchKVStore::fetchDoc(Db *db, DocInfo *docinfo,
     time_t exptime = 0;
     uint8_t ext_meta[EXT_META_LEN];
     uint8_t ext_len = 0;
-    uint8_t conf_res_mode = 0;
 
     if (metadata.size < DEFAULT_META_LEN) {
         throw std::invalid_argument("CouchKVStore::fetchDoc: "
@@ -1490,10 +1451,6 @@ couchstore_error_t CouchKVStore::fetchDoc(Db *db, DocInfo *docinfo,
         ext_len = EXT_META_LEN;
     }
 
-    if (metadata.size == V2_META_LEN) {
-        memcpy(&conf_res_mode, metadata.buf + V1_META_LEN, CONFLICT_RES_META_LEN);
-    }
-
     cas = ntohll(cas);
     exptime = ntohl(exptime);
 
@@ -1505,8 +1462,6 @@ couchstore_error_t CouchKVStore::fetchDoc(Db *db, DocInfo *docinfo,
             it->setDeleted();
         }
 
-        it->setConflictResMode(
-                static_cast<enum conflict_resolution_mode>(conf_res_mode));
         it->setRevSeqno(docinfo->rev_seq);
         docValue = GetValue(it);
         // update ep-engine IO stats
@@ -1551,9 +1506,6 @@ couchstore_error_t CouchKVStore::fetchDoc(Db *db, DocInfo *docinfo,
                                     ext_meta, ext_len, cas, docinfo->db_seq, vbId,
                                     docinfo->rev_seq);
 
-                it->setConflictResMode(
-                           static_cast<enum conflict_resolution_mode>(conf_res_mode));
-
                 docValue = GetValue(it);
 
                 // update ep-engine IO stats
@@ -1584,7 +1536,6 @@ int CouchKVStore::recordDbDump(Db *db, DocInfo *docinfo, void *ctx) {
     uint32_t exptime = 0;
     uint8_t ext_meta[EXT_META_LEN] = {0};
     uint8_t ext_len = 0;
-    uint8_t conf_res_mode = 0;
 
     if (key.size > UINT16_MAX) {
         throw std::invalid_argument("CouchKVStore::recordDbDump: "
@@ -1620,10 +1571,6 @@ int CouchKVStore::recordDbDump(Db *db, DocInfo *docinfo, void *ctx) {
         ext_len = EXT_META_LEN;
     }
 
-    if (metadata.size == V2_META_LEN) {
-        memcpy(&conf_res_mode, metadata.buf + V1_META_LEN, CONFLICT_RES_META_LEN);
-    }
-
     exptime = ntohl(exptime);
     cas = ntohll(cas);
 
@@ -1698,9 +1645,6 @@ int CouchKVStore::recordDbDump(Db *db, DocInfo *docinfo, void *ctx) {
         it->setDeleted();
     }
 
-    it->setConflictResMode(
-                 static_cast<enum conflict_resolution_mode>(conf_res_mode));
-
     bool onlyKeys = (sctx->valFilter == ValueFilter::KEYS_ONLY) ? true : false;
     GetValue rv(it, ENGINE_SUCCESS, -1, onlyKeys);
     cb->callback(rv);
index 5f4bb16..80ce49a 100644 (file)
@@ -136,10 +136,9 @@ public:
 
 class EventuallyPersistentEngine;
 
-// Additional 3 Bytes for flex meta, datatype and conflict resolution mode
+// Additional 2 Bytes for flex meta and datatype
 const size_t COUCHSTORE_METADATA_SIZE(2 * sizeof(uint32_t) + sizeof(uint64_t) +
-                                      FLEX_DATA_OFFSET + EXT_META_LEN +
-                                      CONFLICT_RES_META_LEN);
+                                      FLEX_DATA_OFFSET + EXT_META_LEN);
 
 /**
  * Class representing a document to be persisted in couchstore.
index 257e3c6..0d6b185 100644 (file)
@@ -349,8 +349,7 @@ bool ActiveStream::backfillReceived(Item* itm, backfill_source_t backfill_source
             bufferedBackfill.items++;
 
             pushToReadyQ(new MutationResponse(itm, opaque_,
-                              prepareExtendedMetaData(itm->getVBucketId(),
-                                                      itm->getConflictResMode())));
+                              prepareExtendedMetaData(itm->getVBucketId())));
 
             lastReadSeqno.store(itm->getBySeqno());
             lh.unlock();
@@ -798,8 +797,7 @@ void ActiveStream::processItems(std::vector<queued_item>& items) {
                 lastReadSeqnoUnSnapshotted = qi->getBySeqno();
 
                 mutations.push_back(new MutationResponse(qi, opaque_,
-                            prepareExtendedMetaData(qi->getVBucketId(),
-                                                    qi->getConflictResMode()),
+                            prepareExtendedMetaData(qi->getVBucketId()),
                             isSendMutationKeyOnlyEnabled() ? KEY_ONLY :
                                                              KEY_VALUE));
             } else if (qi->getOperation() == queue_op_checkpoint_start) {
@@ -1205,17 +1203,14 @@ uint64_t ActiveStream::getLastSentSeqno() {
     return lastSentSeqno.load();
 }
 
-ExtendedMetaData* ActiveStream::prepareExtendedMetaData(uint16_t vBucketId,
-                                                        uint8_t conflictResMode)
+ExtendedMetaData* ActiveStream::prepareExtendedMetaData(uint16_t vBucketId)
 {
     ExtendedMetaData *emd = NULL;
     if (producer->isExtMetaDataEnabled()) {
         RCPtr<VBucket> vb = engine->getVBucket(vBucketId);
         if (vb && vb->getTimeSyncConfig() == time_sync_t::ENABLED_WITH_DRIFT) {
             int64_t adjustedTime = gethrtime() + vb->getDriftCounter();
-            emd = new ExtendedMetaData(adjustedTime, conflictResMode);
-        } else {
-            emd = new ExtendedMetaData(conflictResMode);
+            emd = new ExtendedMetaData(adjustedTime);
         }
     }
     return emd;
index 2bdd843..ced44ed 100644 (file)
@@ -289,8 +289,7 @@ private:
 
     const char* getEndStreamStatusStr(end_stream_status_t status);
 
-    ExtendedMetaData* prepareExtendedMetaData(uint16_t vBucketId,
-                                              uint8_t conflictResMode);
+    ExtendedMetaData* prepareExtendedMetaData(uint16_t vBucketId);
 
     bool isCurrentSnapshotCompleted() const;
 
index 817e4d0..3fddd5b 100644 (file)
--- a/src/ep.cc
+++ b/src/ep.cc
@@ -1108,16 +1108,8 @@ ENGINE_ERROR_CODE EventuallyPersistentStore::addTAPBackfillItem(
     case NOT_FOUND:
         // FALLTHROUGH
     case WAS_CLEAN:
-        /* set the conflict resolution mode from the extended meta data *
-         * Given that the mode is already set, we don't need to set the *
-         * conflict resolution mode in queueDirty */
-        if (emd) {
-            v->setConflictResMode(
-                 static_cast<enum conflict_resolution_mode>(
-                                      emd->getConflictResMode()));
-        }
         vb->setMaxCas(v->getCas());
-        queueDirty(vb, v, &lh, NULL, true, genBySeqno, false);
+        queueDirty(vb, v, &lh, NULL, true, genBySeqno);
         break;
     case INVALID_VBUCKET:
         ret = ENGINE_NOT_MY_VBUCKET;
@@ -2254,7 +2246,6 @@ ENGINE_ERROR_CODE EventuallyPersistentStore::getMetaData(
             metadata.flags = v->getFlags();
             metadata.exptime = v->getExptime();
             metadata.revSeqno = v->getRevSeqno();
-            confResMode = v->getConflictResMode();
             return ENGINE_SUCCESS;
         }
     } else {
@@ -2374,16 +2365,8 @@ ENGINE_ERROR_CODE EventuallyPersistentStore::setWithMeta(
         break;
     case WAS_DIRTY:
     case WAS_CLEAN:
-        /* set the conflict resolution mode from the extended meta data *
-         * Given that the mode is already set, we don't need to set the *
-         * conflict resolution mode in queueDirty */
-        if (emd) {
-            v->setConflictResMode(
-                      static_cast<enum conflict_resolution_mode>(
-                                            emd->getConflictResMode()));
-        }
         vb->setMaxCas(v->getCas());
-        queueDirty(vb, v, &lh, seqno, false, genBySeqno, false);
+        queueDirty(vb, v, &lh, seqno, false, genBySeqno);
         break;
     case NOT_FOUND:
         ret = ENGINE_KEY_ENOENT;
@@ -3053,16 +3036,8 @@ ENGINE_ERROR_CODE EventuallyPersistentStore::deleteWithMeta(
             v->setBySeqno(bySeqno);
         }
 
-        /* set the conflict resolution mode from the extended meta data *
-         * Given that the mode is already set, we don't need to set the *
-         * conflict resolution mode in queueDirty */
-        if (emd) {
-            v->setConflictResMode(
-               static_cast<enum conflict_resolution_mode>(
-                                         emd->getConflictResMode()));
-        }
         vb->setMaxCas(v->getCas());
-        queueDirty(vb, v, &lh, seqno, tapBackfill, genBySeqno, false);
+        queueDirty(vb, v, &lh, seqno, tapBackfill, genBySeqno);
         break;
     case NEED_BG_FETCH:
         lh.unlock();
@@ -3551,23 +3526,8 @@ void EventuallyPersistentStore::queueDirty(RCPtr<VBucket> &vb,
                                            LockHolder *plh,
                                            uint64_t *seqno,
                                            bool tapBackfill,
-                                           bool genBySeqno,
-                                           bool setConflictMode) {
+                                           bool genBySeqno) {
     if (vb) {
-        if (setConflictMode && (v->getConflictResMode() != last_write_wins) &&
-                vb->isTimeSyncEnabled()) {
-            time_sync_t timeSyncConfig = vb->getTimeSyncConfig();
-
-            /* Enable conflict resolution mode to last write wins in
-             * case the setting is (i) enabled_without_drift and for
-             * (ii) enabled_with_drift and a valid drift value is set
-             */
-            if (timeSyncConfig == time_sync_t::ENABLED_WITHOUT_DRIFT ||
-                    vb->getDriftCounter() != INITIAL_DRIFT) {
-                v->setConflictResMode(last_write_wins);
-            }
-        }
-
         queued_item qi(v->toItem(false, vb->getId()));
 
         bool rv = tapBackfill ? vb->queueBackfillItem(qi, genBySeqno) :
index 11ce789..e514068 100644 (file)
--- a/src/ep.h
+++ b/src/ep.h
@@ -921,15 +921,13 @@ protected:
      * @param seqno sequence number of the mutation
      * @param tapBackfill if the item is from backfill replication
      * @param genBySeqno whether or not to generate sequence number
-     * @param setConflictMode set the conflict resolution mode
      */
     void queueDirty(RCPtr<VBucket> &vb,
                     StoredValue* v,
                     LockHolder *plh,
                     uint64_t *seqno,
                     bool tapBackfill = false,
-                    bool genBySeqno = true,
-                    bool setConflictMode = true);
+                    bool genBySeqno = true);
 
     /**
      * Retrieve a StoredValue and invoke a method on it.
index b7461ff..6a6e08b 100644 (file)
@@ -5481,12 +5481,6 @@ ENGINE_ERROR_CODE EventuallyPersistentEngine::setWithMeta(const void* cookie,
 
     itm->setRevSeqno(seqno);
 
-    if (emd) {
-        itm->setConflictResMode(
-                 static_cast<enum conflict_resolution_mode>(
-                                            emd->getConflictResMode()));
-    }
-
     bool allowExisting = (opcode == PROTOCOL_BINARY_CMD_SET_WITH_META ||
                           opcode == PROTOCOL_BINARY_CMD_SETQ_WITH_META);
 
index 32ec4bb..267102f 100644 (file)
@@ -23,31 +23,17 @@ ExtendedMetaData::ExtendedMetaData(const void *meta, uint16_t nmeta) {
     len = nmeta;
     data = static_cast<const char*>(meta);
     adjustedTime = 0;
-    conflictResMode = 0;
     ret = ENGINE_SUCCESS;
     memoryAllocated = false;
     decodeMeta();
 }
 
-ExtendedMetaData::ExtendedMetaData(int64_t adjusted_time, uint8_t conflict_res_mode) {
+ExtendedMetaData::ExtendedMetaData(int64_t adjusted_time) {
     len = 0;
     data = NULL;
     adjustedTime = adjusted_time;
-    conflictResMode = conflict_res_mode;
     ret = ENGINE_SUCCESS;
     memoryAllocated = false;
-    adjustedTimeSet = true;
-    encodeMeta();
-}
-
-ExtendedMetaData::ExtendedMetaData(uint8_t conflict_res_mode) {
-    len = 0;
-    data = NULL;
-    adjustedTime = 0;
-    conflictResMode = conflict_res_mode;
-    ret = ENGINE_SUCCESS;
-    memoryAllocated = false;
-    adjustedTimeSet = false;
     encodeMeta();
 }
 
@@ -96,7 +82,9 @@ void ExtendedMetaData::decodeMeta() {
                         adjustedTime = ntohll(adjustedTime);
                         break;
                     case CMD_META_CONFLICT_RES_MODE:
-                        memcpy(&conflictResMode, data + offset, length);
+                        // MB-21143: Now ignoring conflict_res_mode
+                        // 4.6 no longer sends, but older versions
+                        // may send it to us.
                         break;
                     default:
                         ret = ENGINE_EINVAL;
@@ -118,15 +106,8 @@ void ExtendedMetaData::encodeMeta() {
     uint8_t type;
     int64_t adjusted_time = htonll(adjustedTime);
     uint16_t length;
-    uint16_t nmeta = 0;
-
-    nmeta = sizeof(version) + sizeof(type) + sizeof(length) +
-                sizeof(conflictResMode);
-
-    if (adjustedTimeSet) {
-        nmeta += (sizeof(type) + sizeof(length) +
-                     sizeof(adjustedTime));
-    }
+    uint16_t nmeta = sizeof(version) + sizeof(type) + sizeof(length) +
+                sizeof(adjusted_time);
 
     char* meta = new char[nmeta];
     if (meta == NULL) {
@@ -138,23 +119,8 @@ void ExtendedMetaData::encodeMeta() {
         memcpy(meta, &version, sizeof(version));
         offset += sizeof(version);
 
-        if (adjustedTimeSet) {
-            type = CMD_META_ADJUSTED_TIME;
-            length = sizeof(adjusted_time);
-            length = htons(length);
-
-            memcpy(meta + offset, &type, sizeof(type));
-            offset += sizeof(type);
-
-            memcpy(meta + offset, &length, sizeof(length));
-            offset += sizeof(length);
-
-            memcpy(meta + offset, &adjusted_time, sizeof(adjusted_time));
-            offset += sizeof(adjusted_time);
-        }
-
-        type = CMD_META_CONFLICT_RES_MODE;
-        length = sizeof(conflictResMode);
+        type = CMD_META_ADJUSTED_TIME;
+        length = sizeof(adjusted_time);
         length = htons(length);
 
         memcpy(meta + offset, &type, sizeof(type));
@@ -163,7 +129,7 @@ void ExtendedMetaData::encodeMeta() {
         memcpy(meta + offset, &length, sizeof(length));
         offset += sizeof(length);
 
-        memcpy(meta + offset, &conflictResMode, sizeof(conflictResMode));
+        memcpy(meta + offset, &adjusted_time, sizeof(adjusted_time));
 
         data = (const char*)meta;
         len = nmeta;
index 83a942e..5d18517 100644 (file)
@@ -39,8 +39,10 @@ enum cmd_meta_extras_version {
  * commands and DCP mutation/expiration messages
  */
 enum cmd_meta_extras_type {
-    CMD_META_ADJUSTED_TIME     = 0x01, /* adjusted time */
-    CMD_META_CONFLICT_RES_MODE = 0x02  /* conflict resolution mode */
+    /* adjusted time */
+    CMD_META_ADJUSTED_TIME     = 0x01,
+    /* conflict resolution mode is no longer sent, but could be received on upgrade.*/
+    CMD_META_CONFLICT_RES_MODE = 0x02
 };
 
 /**
@@ -51,8 +53,7 @@ enum cmd_meta_extras_type {
 class ExtendedMetaData {
 public:
     ExtendedMetaData(const void *meta, uint16_t nmeta);
-    ExtendedMetaData(int64_t adjusted_time, uint8_t conflict_res_mode);
-    ExtendedMetaData(uint8_t conflict_res_mode);
+    ExtendedMetaData(int64_t adjusted_time);
     ~ExtendedMetaData();
 
     ENGINE_ERROR_CODE getStatus() {
@@ -63,10 +64,6 @@ public:
         return adjustedTime;
     }
 
-    uint8_t getConflictResMode() {
-        return conflictResMode;
-    }
-
     std::pair<const char*, uint16_t> getExtMeta() {
         return std::make_pair(data, len);
     }
@@ -80,8 +77,6 @@ private:
     ENGINE_ERROR_CODE ret;
     uint16_t len;
     bool memoryAllocated;
-    bool adjustedTimeSet;
-    uint8_t conflictResMode;
 };
 
 #endif  // SRC_EXT_META_PARSER_H_
index 19b68ca..a649d23 100644 (file)
@@ -591,7 +591,6 @@ GetValue ForestKVStore::docToItem(fdb_kvs_handle *kvsHandle, fdb_doc *rdoc,
     uint32_t itemFlags;
     uint8_t ext_meta[EXT_META_LEN];
     uint8_t ext_len;
-    uint8_t conf_res_mode = 0;
 
     //TODO: handle metadata upgrade?
     memcpy(&cas, metadata, 8);
@@ -600,7 +599,6 @@ GetValue ForestKVStore::docToItem(fdb_kvs_handle *kvsHandle, fdb_doc *rdoc,
     memcpy(&itemFlags, metadata + 16, 4);
     memcpy(&rev_seqno, metadata + 20, 8);
     memcpy(ext_meta, metadata + 29, EXT_META_LEN);
-    memcpy(&conf_res_mode, metadata + 30, CONFLICT_RES_META_LEN);
     ext_len = EXT_META_LEN;
 
     cas = ntohll(cas);
@@ -631,8 +629,6 @@ GetValue ForestKVStore::docToItem(fdb_kvs_handle *kvsHandle, fdb_doc *rdoc,
                       cas, (uint64_t)rdoc->seqnum, vbId);
     }
 
-    it->setConflictResMode(
-                   static_cast<enum conflict_resolution_mode>(conf_res_mode));
     it->setRevSeqno(rev_seqno);
     return GetValue(it);
 }
@@ -810,7 +806,6 @@ static void populateMetaData(const Item &itm, uint8_t *meta, bool deletion) {
     uint32_t flags = itm.getFlags();
     uint32_t exptime = itm.getExptime();
     uint32_t texptime = 0;
-    uint8_t confresmode = static_cast<uint8_t>(itm.getConflictResMode());
 
     if (deletion) {
         texptime = ep_real_time();
@@ -832,8 +827,6 @@ static void populateMetaData(const Item &itm, uint8_t *meta, bool deletion) {
     } else {
         memcpy(meta + 29, itm.getExtMeta(), itm.getExtMetaLen());
     }
-
-    memcpy(meta + 30, &confresmode, CONFLICT_RES_META_LEN);
 }
 
 void ForestKVStore::set(const Item &itm, Callback<mutation_result> &cb) {
@@ -1274,7 +1267,6 @@ scan_error_t ForestKVStore::scan(ScanContext *ctx) {
          uint64_t rev_seqno;
          uint8_t ext_meta[EXT_META_LEN] = {0};
          uint8_t ext_len;
-         uint8_t conf_res_mode = 0;
 
          memcpy(&cas, metadata, 8);
          memcpy(&exptime, metadata + 8, 4);
@@ -1282,7 +1274,6 @@ scan_error_t ForestKVStore::scan(ScanContext *ctx) {
          memcpy(&itemflags, metadata + 16, 4);
          memcpy(&rev_seqno, metadata + 20, 8);
          memcpy(ext_meta, metadata + 29, EXT_META_LEN);
-         memcpy(&conf_res_mode, metadata + 30, CONFLICT_RES_META_LEN);
          ext_len = EXT_META_LEN;
 
          cas = ntohll(cas);
@@ -1305,9 +1296,6 @@ scan_error_t ForestKVStore::scan(ScanContext *ctx) {
              it->setDeleted();
          }
 
-         it->setConflictResMode(
-                      static_cast<enum conflict_resolution_mode>(conf_res_mode));
-
          bool onlyKeys = (ctx->valFilter == ValueFilter::KEYS_ONLY) ? true : false;
          GetValue rv(it, ENGINE_SUCCESS, -1, onlyKeys);
          cb->callback(rv);
index 91540c5..996e8cf 100644 (file)
 //Maximum length of a key
 const size_t MAX_KEY_LENGTH = 250;
 
-// Additional 3 Bytes for flex meta, datatype and conflict resolution mode
+// Additional 2 Bytes for flex meta and datatype.
 const size_t FORESTDB_METADATA_SIZE  ((3 * sizeof(uint32_t) + 2 * sizeof(uint64_t)) +
-                                      FLEX_DATA_OFFSET + EXT_META_LEN +
-                                      CONFLICT_RES_META_LEN);
+                                      FLEX_DATA_OFFSET + EXT_META_LEN);
 
 enum class handleType {
     READER,
index 23a83f5..2f33211 100644 (file)
@@ -306,14 +306,6 @@ public:
 };
 
 /**
- * Conflict Resolution Modes
- */
-enum conflict_resolution_mode {
-    revision_seqno = 0,
-    last_write_wins
-};
-
-/**
  * The Item structure we use to pass information between the memcached
  * core and the backend. Please note that the kvstore don't store these
  * objects, so we do have an extra layer of memory copying :(
@@ -327,8 +319,8 @@ public:
      */
     Item(const std::string &k, const uint32_t fl, const time_t exp,
          const value_t &val, uint64_t theCas = 0,  int64_t i = -1,
-         uint16_t vbid = 0, uint64_t sno = 1, uint8_t nru_value = INITIAL_NRU_VALUE,
-         uint8_t conflict_res_value = revision_seqno) :
+         uint16_t vbid = 0, uint64_t sno = 1,
+         uint8_t nru_value = INITIAL_NRU_VALUE) :
         metaData(theCas, sno, fl, exp),
         value(val),
         key(k),
@@ -336,8 +328,7 @@ public:
         queuedTime(ep_current_time()),
         vbucketId(vbid),
         op(queue_op_set),
-        nru(nru_value),
-        conflictResMode(conflict_res_value)
+        nru(nru_value)
     {
         if (bySeqno == 0) {
             throw std::invalid_argument("Item(): bySeqno must be non-zero");
@@ -359,16 +350,15 @@ public:
     Item(const void *k, uint16_t nk, const uint32_t fl, const time_t exp,
          const void *dta, const size_t nb, uint8_t* ext_meta = NULL,
          uint8_t ext_len = 0, uint64_t theCas = 0, int64_t i = -1,
-         uint16_t vbid = 0, uint64_t sno = 1, uint8_t nru_value = INITIAL_NRU_VALUE,
-         uint8_t conflict_res_value = revision_seqno) :
+         uint16_t vbid = 0, uint64_t sno = 1,
+         uint8_t nru_value = INITIAL_NRU_VALUE) :
         metaData(theCas, sno, fl, exp),
         key(static_cast<const char*>(k), nk),
         bySeqno(i),
         queuedTime(ep_current_time()),
         vbucketId(vbid),
         op(queue_op_set),
-        nru(nru_value),
-        conflictResMode(conflict_res_value)
+        nru(nru_value)
     {
         if (bySeqno == 0) {
             throw std::invalid_argument("Item(): bySeqno must be non-zero");
@@ -379,16 +369,14 @@ public:
 
     Item(const std::string &k, const uint16_t vb,
          enum queue_operation o, const uint64_t revSeq,
-         const int64_t bySeq, uint8_t nru_value = INITIAL_NRU_VALUE,
-         uint8_t conflict_res_value = revision_seqno) :
+         const int64_t bySeq, uint8_t nru_value = INITIAL_NRU_VALUE) :
         metaData(),
         key(k),
         bySeqno(bySeq),
         queuedTime(ep_current_time()),
         vbucketId(vb),
         op(static_cast<uint16_t>(o)),
-        nru(nru_value),
-        conflictResMode(conflict_res_value)
+        nru(nru_value)
     {
        if (bySeqno < 0) {
            throw std::invalid_argument("Item(): bySeqno must be non-negative");
@@ -405,8 +393,7 @@ public:
         queuedTime(other.queuedTime),
         vbucketId(other.vbucketId),
         op(other.op),
-        nru(other.nru),
-        conflictResMode(other.conflictResMode)
+        nru(other.nru)
     {
         if (copyKeyOnly) {
             setData(nullptr, 0, nullptr, 0);
@@ -682,15 +669,6 @@ public:
         return true;
     }
 
-
-    void setConflictResMode(enum conflict_resolution_mode conf_res_value) {
-        conflictResMode = static_cast<uint8_t>(conf_res_value);
-    }
-
-    enum conflict_resolution_mode getConflictResMode(void) const {
-        return static_cast<enum conflict_resolution_mode>(conflictResMode);
-    }
-
 private:
     /**
      * Set the item's data. This is only used by constructors, so we
@@ -715,7 +693,6 @@ private:
     uint16_t vbucketId;
     uint8_t op;
     uint8_t nru  : 2;
-    uint8_t conflictResMode : 2;
 
     static AtomicValue<uint64_t> casCounter;
     static const uint32_t metaDataSize;
index 85682f8..f22cef4 100644 (file)
@@ -99,7 +99,6 @@ bool StoredValue::unlocked_restoreValue(Item *itm, HashTable &ht) {
         nru = INITIAL_NRU_VALUE;
     }
     deleted = false;
-    conflictResMode = itm->getConflictResMode();
     value = itm->getValue();
     increaseCacheSize(ht, value->length());
     return true;
@@ -131,7 +130,6 @@ bool StoredValue::unlocked_restoreMeta(Item *itm, ENGINE_ERROR_CODE status,
         if (nru == MAX_NRU_VALUE) {
             nru = INITIAL_NRU_VALUE;
         }
-        conflictResMode = itm->getConflictResMode();
         return true;
     case ENGINE_KEY_ENOENT:
         setNonExistent();
@@ -758,9 +756,6 @@ Item* StoredValue::toItem(bool lck, uint16_t vbucket) const {
         itm->setDeleted();
     }
 
-    itm->setConflictResMode(
-          static_cast<enum conflict_resolution_mode>(conflictResMode));
-
     return itm;
 }
 
index 87b8e09..acf8b0f 100644 (file)
@@ -91,15 +91,6 @@ public:
         return !isDirty();
     }
 
-    void setConflictResMode(enum conflict_resolution_mode conflict_res_mode) {
-        conflictResMode = static_cast<uint8_t>(conflict_res_mode);
-    }
-
-
-    enum conflict_resolution_mode getConflictResMode(void) {
-        return static_cast<enum conflict_resolution_mode>(conflictResMode);
-    }
-
     bool eligibleForEviction(item_eviction_policy_t policy) {
         if (policy == VALUE_ONLY) {
             return isResident() && isClean() && !isDeleted();
@@ -214,8 +205,6 @@ public:
             itm.setRevSeqno(revSeqno);
         }
 
-        conflictResMode = itm.getConflictResMode();
-
         markDirty();
 
         if (isTempItem()) {
@@ -531,7 +520,6 @@ private:
         lock_expiry = 0;
         keylen = itm.getNKey();
         revSeqno = itm.getRevSeqno();
-        conflictResMode = itm.getConflictResMode();
 
         if (setDirty) {
             markDirty();
@@ -563,7 +551,6 @@ private:
     bool               _isDirty  :  1; // 1 bit
     bool               deleted   :  1;
     bool               newCacheItem : 1;
-    uint8_t            conflictResMode : 2;
     uint8_t            nru       :  2; //!< True if referenced since last sweep
     uint8_t            keylen;
     char               keybytes[1];    //!< The key itself.
index 5ff26d5..ce8d3a7 100644 (file)
@@ -468,7 +468,7 @@ void del_with_meta(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *key,
         blen = 26;
         ext = new char[blen];
         encodeWithMetaExt(ext, itemMeta);
-        emd = new ExtendedMetaData(adjustedTime, 0/*conflict_mode to be deleted*/);
+        emd = new ExtendedMetaData(adjustedTime);
         // nmeta added to ext below
     }
 
@@ -812,7 +812,7 @@ void set_with_meta(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *key,
         blen = 26;
         ext = new char[blen];
         encodeWithMetaExt(ext, itemMeta);
-        emd = new ExtendedMetaData(adjustedTime, 0/*conflict_mode to be deleted*/);
+        emd = new ExtendedMetaData(adjustedTime);
         // nmeta added to ext below
     }
 
index 1c8f1f5..f42314d 100644 (file)
@@ -57,7 +57,6 @@ ENGINE_ERROR_CODE vb_map_response(const void *cookie, const void *map,
 const uint8_t dcp_stream_end_resp_base_msg_bytes = 28;
 const uint8_t dcp_snapshot_marker_base_msg_bytes = 44;
 const uint8_t dcp_mutation_base_msg_bytes = 55;
-const uint8_t dcp_meta_size_none = 5;
 
 extern AtomicValue<protocol_binary_response_status> last_status;
 extern std::string last_key;
index 358eb35..83590d0 100644 (file)
@@ -1897,7 +1897,7 @@ static enum test_result test_io_stats(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
           "Expected storing one value to not change the read counter");
 
     check(get_int_stat(h, h1, "rw_0:io_num_write", "kvstore") == 1 &&
-          get_int_stat(h, h1, "rw_0:io_write_bytes", "kvstore") == 23,
+          get_int_stat(h, h1, "rw_0:io_write_bytes", "kvstore") == 22,
           "Expected storing the key to update the write counter");
     evict_key(h, h1, "a", 0, "Ejected.");
 
@@ -1907,7 +1907,7 @@ static enum test_result test_io_stats(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
           get_int_stat(h, h1, "ro_0:io_read_bytes", "kvstore") == 4,
           "Expected reading the value back in to update the read counter");
     check(get_int_stat(h, h1, "rw_0:io_num_write", "kvstore") == 1 &&
-          get_int_stat(h, h1, "rw_0:io_write_bytes", "kvstore") == 23,
+          get_int_stat(h, h1, "rw_0:io_write_bytes", "kvstore") == 22,
           "Expected reading the value back in to not update the write counter");
 
     return SUCCESS;
index 14e8468..52551a7 100644 (file)
@@ -238,7 +238,6 @@ void TestDcpConsumer::run(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
     std::unique_ptr<dcp_message_producers> producers(get_dcp_producers(h, h1));
 
     bool done = false;
-    ExtendedMetaData *emd = NULL;
     bool exp_all_items_streamed = true;
     size_t num_stream_ends_received = 0;
     uint32_t bytes_read = 0;
@@ -295,17 +294,8 @@ void TestDcpConsumer::run(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
                     if (stats.time_sync_enabled) {
                         checkeq(static_cast<size_t>(16), dcp_last_meta.size(),
                                 "Expected extended meta in mutation packet");
-                    } else {
-                        checkeq(static_cast<size_t>(5), dcp_last_meta.size(),
-                                "Expected no extended metadata");
                     }
 
-                    emd = new ExtendedMetaData(dcp_last_meta.c_str(),
-                                               dcp_last_meta.size());
-                    checkeq(stats.exp_conflict_res,
-                            emd->getConflictResMode(),
-                            "Unexpected conflict resolution mode");
-                    delete emd;
                     break;
                 case PROTOCOL_BINARY_CMD_DCP_DELETION:
                     cb_assert(vbid != static_cast<uint16_t>(-1));
@@ -326,18 +316,8 @@ void TestDcpConsumer::run(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
                         checkeq(static_cast<size_t>(16),
                                 dcp_last_meta.size(),
                                 "Expected adjusted time in mutation packet");
-                    } else {
-                        checkeq(static_cast<size_t>(5),
-                                dcp_last_meta.size(),
-                                "Expected no extended metadata");
                     }
 
-                    emd = new ExtendedMetaData(dcp_last_meta.c_str(),
-                                               dcp_last_meta.size());
-                    checkeq(stats.exp_conflict_res,
-                            emd->getConflictResMode(),
-                            "Unexpected conflict resolution mode");
-                    delete emd;
                     break;
                 case PROTOCOL_BINARY_CMD_DCP_STREAM_END:
                     cb_assert(vbid != static_cast<uint16_t>(-1));
@@ -2558,8 +2538,7 @@ static enum test_result test_dcp_producer_stream_backfill_no_value(
     total_bytes = tdc1.getTotalBytes();
 
     /* basebytes mutation + nmeta (when no ext_meta is expected) */
-    const int packet_fixed_size = dcp_mutation_base_msg_bytes +
-                                  dcp_meta_size_none;
+    const int packet_fixed_size = dcp_mutation_base_msg_bytes;
     est_bytes += (num_items * packet_fixed_size);
     /* Add DCP_SNAPSHOT_MARKER bytes and DCP_STREAM_END bytes */
     est_bytes += (dcp_snapshot_marker_base_msg_bytes +
@@ -2627,8 +2606,7 @@ static enum test_result test_dcp_producer_stream_mem_no_value(
     total_bytes = tdc1.getTotalBytes();
 
     /* basebytes mutation + nmeta (when no ext_meta is expected) */
-    const int packet_fixed_size = dcp_mutation_base_msg_bytes +
-                                  dcp_meta_size_none;
+    const int packet_fixed_size = dcp_mutation_base_msg_bytes;
     est_bytes += ((end-start) * packet_fixed_size);
     /* Add DCP_SNAPSHOT_MARKER bytes and DCP_STREAM_END bytes */
     est_bytes += (dcp_snapshot_marker_base_msg_bytes +
@@ -4155,7 +4133,7 @@ static enum test_result test_dcp_consumer_mutate_with_time_sync(
 
     // Consume a DCP mutation with extended meta
     int64_t adjusted_time1 = gethrtime() * 2;
-    ExtendedMetaData *emd = new ExtendedMetaData(adjusted_time1, false);
+    ExtendedMetaData *emd = new ExtendedMetaData(adjusted_time1);
     cb_assert(emd && emd->getStatus() == ENGINE_SUCCESS);
     std::pair<const char*, uint16_t> meta = emd->getExtMeta();
     checkeq(ENGINE_SUCCESS,
@@ -4314,7 +4292,7 @@ static enum test_result test_dcp_consumer_delete_with_time_sync(
 
     // Consume an DCP deletion
     int64_t adjusted_time1 = gethrtime() * 2;
-    ExtendedMetaData *emd = new ExtendedMetaData(adjusted_time1, false);
+    ExtendedMetaData *emd = new ExtendedMetaData(adjusted_time1);
     cb_assert(emd && emd->getStatus() == ENGINE_SUCCESS);
     std::pair<const char*, uint16_t> meta = emd->getExtMeta();
     checkeq(ENGINE_SUCCESS,
index 4ba8d23..24ebdad 100644 (file)
 
 // Helper functions ///////////////////////////////////////////////////////////
 
-static void verifyLastMetaData(ItemMetaData imd, uint8_t conflict_res_mode) {
+static void verifyLastMetaData(ItemMetaData imd) {
     checkeq(imd.revSeqno, last_meta.revSeqno, "Seqno didn't match");
     checkeq(imd.cas, last_meta.cas, "Cas didn't match");
     checkeq(imd.exptime, last_meta.exptime, "Expiration time didn't match");
     checkeq(imd.flags, last_meta.flags, "Flags didn't match");
-    checkeq(conflict_res_mode, last_conflict_resolution_mode.load(),
-            "Conflict resolution mode didn't match");
 }
 
 // Testcases //////////////////////////////////////////////////////////////////
@@ -58,7 +56,7 @@ static enum test_result test_get_meta(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1)
     checkeq(PROTOCOL_BINARY_RESPONSE_SUCCESS, last_status.load(), "Expected success");
     ItemMetaData metadata(it->getCas(), it->getRevSeqno(),
                           it->getFlags(), it->getExptime());
-    verifyLastMetaData(metadata, static_cast<uint8_t>(-1));
+    verifyLastMetaData(metadata);
 
     // check the stat again
     temp = get_int_stat(h, h1, "ep_num_ops_get_meta");
@@ -88,7 +86,7 @@ static enum test_result test_get_meta_with_extras(ENGINE_HANDLE *h,
     checkeq(PROTOCOL_BINARY_RESPONSE_SUCCESS, last_status.load(), "Expected success");
     ItemMetaData metadata1(it1->getCas(), it1->getRevSeqno(),
                            it1->getFlags(), it1->getExptime());
-    verifyLastMetaData(metadata1, static_cast<uint8_t>(last_write_wins));
+    verifyLastMetaData(metadata1);
     // check the stat again
     temp = get_int_stat(h, h1, "ep_num_ops_get_meta");
     check(temp == 1, "Expect one getMeta op");
@@ -103,7 +101,7 @@ static enum test_result test_get_meta_with_extras(ENGINE_HANDLE *h,
 
     check(get_meta(h, h1, key1, true), "Expected to get meta");
     check(last_status == PROTOCOL_BINARY_RESPONSE_SUCCESS, "Expected success");
-    verifyLastMetaData(metadata1, static_cast<uint8_t>(last_write_wins));
+    verifyLastMetaData(metadata1);
 
     return SUCCESS;
 }
@@ -971,7 +969,7 @@ static enum test_result test_set_with_meta_deleted(ENGINE_HANDLE *h, ENGINE_HAND
     check(get_meta(h, h1, key), "Expected to get meta");
     checkeq(PROTOCOL_BINARY_RESPONSE_SUCCESS, last_status.load(), "Expected success");
     ItemMetaData metadata(0xdeadbeef, 10, 0xdeadbeef, 1735689600);
-    verifyLastMetaData(metadata, static_cast<uint8_t>(-1));
+    verifyLastMetaData(metadata);
     checkeq(1, get_int_stat(h, h1, "curr_items"), "Expected single curr_items");
     checkeq(0, get_int_stat(h, h1, "curr_temp_items"), "Expected zero temp_items");
 
@@ -1024,7 +1022,7 @@ static enum test_result test_set_with_meta_nonexistent(ENGINE_HANDLE *h, ENGINE_
     check(get_meta(h, h1, key), "Expected to get meta");
     checkeq(PROTOCOL_BINARY_RESPONSE_SUCCESS, last_status.load(), "Expected success");
     ItemMetaData metadata(0xdeadbeef, 10, 0xdeadbeef, 1735689600);
-    verifyLastMetaData(metadata, static_cast<uint8_t>(-1));
+    verifyLastMetaData(metadata);
     checkeq(0, get_int_stat(h, h1, "curr_temp_items"), "Expected zero temp_items");
     checkeq(1, get_int_stat(h, h1, "curr_items"), "Expected single curr_items");
 
@@ -1584,7 +1582,7 @@ static enum test_result test_getMeta_with_item_eviction(ENGINE_HANDLE *h,
     checkeq(PROTOCOL_BINARY_RESPONSE_SUCCESS, last_status.load(), "Expected success");
     ItemMetaData metadata(it->getCas(), it->getRevSeqno(),
                           it->getFlags(), it->getExptime());
-    verifyLastMetaData(metadata, static_cast<uint8_t>(-1));
+    verifyLastMetaData(metadata);
 
     h1->release(h, NULL, i);
     return SUCCESS;
index 8518f7c..4a907db 100644 (file)
@@ -365,7 +365,7 @@ public:
               flags(0),
               ext1(0),
               ext2(0),
-              conflictResMode(0) {
+              legacyDeleted(0) {
         }
 
         uint64_t cas;
@@ -373,7 +373,7 @@ public:
         uint32_t flags;
         uint8_t ext1;
         uint8_t ext2;
-        uint8_t conflictResMode;
+        uint8_t legacyDeleted; // allow testing via 19byte meta document
 
         static const size_t sizeofV0 = 16;
         static const size_t sizeofV1 = 18;
@@ -476,11 +476,6 @@ protected:
     uint16_t vbid;
 };
 
-
-MATCHER(IsValidConflictMode, "") {
-    return (arg == last_write_wins || arg == revision_seqno);
-}
-
 template<class T>
 class MockedGetCallback : public Callback<T> {
     public:
@@ -498,7 +493,6 @@ class MockedGetCallback : public Callback<T> {
                 expTime(value.getValue()->getExptime());
                 flags(value.getValue()->getFlags());
                 datatype(protocol_binary_datatypes(value.getValue()->getDataType()));
-                conflictResMode(value.getValue()->getConflictResMode());
                 this->value(std::string(value.getValue()->getData(),
                                         value.getValue()->getNBytes()));
                 savedValue = value;
@@ -519,7 +513,6 @@ class MockedGetCallback : public Callback<T> {
         MOCK_METHOD1_T(expTime, void(uint32_t));
         MOCK_METHOD1_T(flags, void(uint32_t));
         MOCK_METHOD1_T(datatype, void(protocol_binary_datatypes));
-        MOCK_METHOD1_T(conflictResMode, void(conflict_resolution_mode));
         MOCK_METHOD1_T(value, void(std::string));
     private:
         GetValue savedValue;
@@ -611,7 +604,6 @@ TEST_F(CouchstoreTest, testV0MetaThings) {
     EXPECT_CALL(gc, expTime(0xaa00bb11));
     EXPECT_CALL(gc, flags(0x01020304));
     EXPECT_CALL(gc, datatype(PROTOCOL_BINARY_RAW_BYTES));
-    EXPECT_CALL(gc, conflictResMode(revision_seqno));
     kvstore->get("key", 0, gc);
 }
 
@@ -638,35 +630,6 @@ TEST_F(CouchstoreTest, testV1MetaThings) {
     EXPECT_CALL(gc, expTime(0xaa00bb11));
     EXPECT_CALL(gc, flags(0x01020304));
     EXPECT_CALL(gc, datatype(PROTOCOL_BINARY_DATATYPE_JSON));
-    EXPECT_CALL(gc, conflictResMode(revision_seqno));
-    kvstore->get("key", 0, gc);
-}
-
-TEST_F(CouchstoreTest, testV2MetaThings) {
-    // Baseline test, just writes meta things and reads them
-    // via standard interfaces
-    // Ensure CAS, exptime and flags are set to something.
-    uint8_t datatype = PROTOCOL_BINARY_DATATYPE_JSON; //lies, but non-zero
-    Item item("key", 3,
-              0x01020304/*flags*/, 0xaa00bb11,/*expiry*/
-              "value", 5,
-              &datatype, 1, /*ext_meta is v1 extension*/
-              0xf00fcafe11225566ull, 1, vbid, 1, INITIAL_NRU_VALUE,
-              last_write_wins /*non zero conflict mode*/);
-    EXPECT_NE(0, last_write_wins);
-    WriteCallback wc;
-    kvstore->begin();
-    kvstore->set(item, wc);
-    StatsCallback sc;
-    kvstore->commit(&sc);
-
-    MockedGetCallback<GetValue> gc;
-    EXPECT_CALL(gc, status(ENGINE_SUCCESS));
-    EXPECT_CALL(gc, cas(0xf00fcafe11225566ull));
-    EXPECT_CALL(gc, expTime(0xaa00bb11));
-    EXPECT_CALL(gc, flags(0x01020304));
-    EXPECT_CALL(gc, datatype(PROTOCOL_BINARY_DATATYPE_JSON));
-    EXPECT_CALL(gc, conflictResMode(last_write_wins));
     kvstore->get("key", 0, gc);
 }
 
@@ -692,7 +655,6 @@ TEST_F(CouchstoreTest, fuzzV0) {
     EXPECT_CALL(gc, expTime(htonl(0xaa00bb11)));
     EXPECT_CALL(gc, flags(0x01020304));
     EXPECT_CALL(gc, datatype(PROTOCOL_BINARY_RAW_BYTES));
-    EXPECT_CALL(gc, conflictResMode(revision_seqno));
     kvstore->get("key", 0, gc);
 }
 
@@ -719,39 +681,62 @@ TEST_F(CouchstoreTest, fuzzV1) {
     EXPECT_CALL(gc, expTime(htonl(0xaa00bb11)));
     EXPECT_CALL(gc, flags(0x01020304));
     EXPECT_CALL(gc, datatype(protocol_binary_datatypes(expectedDataType)));
-    EXPECT_CALL(gc, conflictResMode(revision_seqno));
     kvstore->get("key", 0, gc);
 }
 
-TEST_F(CouchstoreTest, fuzzV2) {
-    Item item("key", 3, 0, 0, "value", 5);
-    WriteCallback wc;
-    kvstore->begin();
-    auto request = kvstore->setAndReturnRequest(item, wc);
+TEST_F(CouchstoreTest, testV0WriteReadWriteRead) {
+    // Ensure CAS, exptime and flags are set to something.
+    uint8_t datatype = PROTOCOL_BINARY_DATATYPE_JSON; //lies, but non-zero
+    Item item("key", 3,
+              0x01020304/*flags*/, 0xaa00bb11,/*expiry*/
+              "value", 5,
+              &datatype, 1, /*ext_meta is v1 extension*/
+              0xf00fcafe11225566ull);
 
-    // Now directly mess with the metadata of the value which will be written
+    EXPECT_NE(0, datatype); // make sure we writing non-zero values
+
+    // Write an item with forced (valid) V0 meta
     MockCouchRequest::MetaData meta;
     meta.cas = 0xf00fcafe11225566ull;
     meta.expiry = 0xaa00bb11;
     meta.flags = 0x01020304;
-    meta.ext1 = 2;
-    meta.ext2 = 33;
-    meta.conflictResMode = 99;
-    request->writeMetaData(meta, MockCouchRequest::MetaData::sizeofV2);
+
+    WriteCallback wc;
+    kvstore->begin();
+    auto request = kvstore->setAndReturnRequest(item, wc);
+
+    // Force the meta to be V0
+    request->writeMetaData(meta, MockCouchRequest::MetaData::sizeofV0);
+
+    // Commit it
     StatsCallback sc;
     kvstore->commit(&sc);
 
+    // Read back, are V1 fields sane?
     MockedGetCallback<GetValue> gc;
     EXPECT_CALL(gc, status(ENGINE_SUCCESS));
     EXPECT_CALL(gc, cas(htonll(0xf00fcafe11225566ull)));
     EXPECT_CALL(gc, expTime(htonl(0xaa00bb11)));
     EXPECT_CALL(gc, flags(0x01020304));
     EXPECT_CALL(gc, datatype(protocol_binary_datatypes(meta.ext2)));
-    EXPECT_CALL(gc, conflictResMode(conflict_resolution_mode(3)));
     kvstore->get("key", 0, gc);
+
+    // Write back the item we read (this will write out V1 meta)
+    kvstore->begin();
+    kvstore->set(*gc.getValue(), wc);
+    kvstore->commit(&sc);
+
+    // Read back, is conf_res_mode sane?
+    MockedGetCallback<GetValue> gc2;
+    EXPECT_CALL(gc2, status(ENGINE_SUCCESS));
+    EXPECT_CALL(gc2, cas(htonll(0xf00fcafe11225566ull)));
+    EXPECT_CALL(gc2, expTime(htonl(0xaa00bb11)));
+    EXPECT_CALL(gc2, flags(0x01020304));
+    EXPECT_CALL(gc2, datatype(protocol_binary_datatypes(meta.ext2)));
+    kvstore->get("key", 0, gc2);
 }
 
-TEST_F(CouchstoreTest, testV1WriteReadWriteRead) {
+TEST_F(CouchstoreTest, testV2WriteRead) {
     // Ensure CAS, exptime and flags are set to something.
     uint8_t datatype = PROTOCOL_BINARY_DATATYPE_JSON; //lies, but non-zero
     Item item("key", 3,
@@ -762,49 +747,36 @@ TEST_F(CouchstoreTest, testV1WriteReadWriteRead) {
 
     EXPECT_NE(0, datatype); // make sure we writing non-zero values
 
-    // Write an item with forced (valid) V1 meta
+    // Write an item with forced (valid) V2 meta
+    // In 4.6 we removed the extra conflict resolution byte, so be sure we
+    // operate correctly if a document has V2 meta.
     MockCouchRequest::MetaData meta;
     meta.cas = 0xf00fcafe11225566ull;
     meta.expiry = 0xaa00bb11;
     meta.flags = 0x01020304;
     meta.ext1 = FLEX_META_CODE;
     meta.ext1 = datatype;
+    meta.legacyDeleted = 0x01;
 
     WriteCallback wc;
     kvstore->begin();
     auto request = kvstore->setAndReturnRequest(item, wc);
 
-    // Force the meta to be V1
-    request->writeMetaData(meta, MockCouchRequest::MetaData::sizeofV1);
+    // Force the meta to be V2 (19 bytes)
+    request->writeMetaData(meta, MockCouchRequest::MetaData::sizeofV2);
 
     // Commit it
     StatsCallback sc;
     kvstore->commit(&sc);
 
-    // Read back, is conf_res_mode sane?
+    // Read back successful, the extra byte will of been dropped.
     MockedGetCallback<GetValue> gc;
     EXPECT_CALL(gc, status(ENGINE_SUCCESS));
     EXPECT_CALL(gc, cas(htonll(0xf00fcafe11225566ull)));
     EXPECT_CALL(gc, expTime(htonl(0xaa00bb11)));
     EXPECT_CALL(gc, flags(0x01020304));
     EXPECT_CALL(gc, datatype(protocol_binary_datatypes(meta.ext2)));
-    EXPECT_CALL(gc, conflictResMode(IsValidConflictMode()));
     kvstore->get("key", 0, gc);
-
-    // Write back the item we read (this will write out V2 meta)
-    kvstore->begin();
-    kvstore->set(*gc.getValue(), wc);
-    kvstore->commit(&sc);
-
-    // Read back, is conf_res_mode sane?
-    MockedGetCallback<GetValue> gc2;
-    EXPECT_CALL(gc2, status(ENGINE_SUCCESS));
-    EXPECT_CALL(gc2, cas(htonll(0xf00fcafe11225566ull)));
-    EXPECT_CALL(gc2, expTime(htonl(0xaa00bb11)));
-    EXPECT_CALL(gc2, flags(0x01020304));
-    EXPECT_CALL(gc2, datatype(protocol_binary_datatypes(meta.ext2)));
-    EXPECT_CALL(gc2, conflictResMode(IsValidConflictMode()));
-    kvstore->get("key", 0, gc2);
 }
 
 // Test cases which run on both Couchstore and ForestDB