MB-19636: Initialise failovers correctly from 2.5.x vbstate 56/64156/6
authorJim Walker <jim@couchbase.com>
Tue, 17 May 2016 16:41:10 +0000 (17:41 +0100)
committerDave Rigby <daver@couchbase.com>
Thu, 19 May 2016 10:31:48 +0000 (10:31 +0000)
(Note: backport of MB-19635 to 3.0.x branch).

When loading a vb file, don't force the failover table data
to be ("[{\"id\":0,\"seq\":0}]"); if the file doesn't contain
any data.

Change-Id: I41673bf848fcbab9b616edec5c7fd2ab9a3ddd6b
Reviewed-on: http://review.couchbase.org/64156
Well-Formed: buildbot <build@couchbase.com>
Tested-by: buildbot <build@couchbase.com>
Reviewed-by: Dave Rigby <daver@couchbase.com>
CMakeLists.txt
src/couch-kvstore/couch-kvstore.cc
tests/ep_test_apis.h
tests/ep_testsuite.cc

index 82c4504..c90b5d6 100644 (file)
@@ -265,7 +265,8 @@ ADD_LIBRARY(ep_testsuite SHARED
    tests/mock/mock_dcp.cc
    tests/ep_test_apis.cc ${OBJECTREGISTRY_SOURCE} ${CONFIG_SOURCE})
 SET_TARGET_PROPERTIES(ep_testsuite PROPERTIES PREFIX "")
-TARGET_LINK_LIBRARIES(ep_testsuite JSON_checker dirutils platform ${LIBEVENT_LIBRARIES} ${SNAPPY_LIBRARIES})
+TARGET_LINK_LIBRARIES(ep_testsuite couchstore dirutils JSON_checker platform
+                      ${LIBEVENT_LIBRARIES} ${SNAPPY_LIBRARIES})
 
 
 #ADD_CUSTOM_COMMAND(OUTPUT
index c90b150..533acba 100644 (file)
@@ -1879,7 +1879,7 @@ void CouchKVStore::readVBState(Db *db, uint16_t vbId) {
     uint64_t checkpointId = 0;
     uint64_t maxDeletedSeqno = 0;
     int64_t highSeqno = 0;
-    std::string failovers("[{\"id\":0,\"seq\":0}]");
+    std::string failovers;
     uint64_t purgeSeqno = 0;
     uint64_t lastSnapStart = 0;
     uint64_t lastSnapEnd = 0;
index 056b74d..f2c1e65 100644 (file)
@@ -40,7 +40,17 @@ static void checkeqfn(T exp, T got, const char *msg, const char *file, const int
     }
 }
 
+template <typename T>
+static void checknefn(T exp, T got, const char *msg, const char *file, const int linenum) {
+    if (exp == got) {
+        std::stringstream ss;
+        ss << "Expected `" << exp << "' to not equal `" << got << "' - " << msg;
+        abort_msg(ss.str().c_str(), file, linenum);
+    }
+}
+
 #define checkeq(a, b, c) checkeqfn(a, b, c, __FILE__, __LINE__)
+#define checkne(a, b, c) checknefn(a, b, c, __FILE__, __LINE__)
 
 #ifdef __cplusplus
 extern "C" {
index d689079..29e052d 100644 (file)
@@ -46,6 +46,7 @@
 #include "ep_test_apis.h"
 #include "ep_testsuite.h"
 #include "locks.h"
+#include <libcouchstore/couch_db.h>
 #include "mock/mock_dcp.h"
 #include "mutex.h"
 
@@ -84,6 +85,13 @@ extern "C" {
 #define MULTI_DISPATCHER_CONFIG \
     "ht_size=129;ht_locks=3;chk_remover_stime=1;chk_period=60"
 
+// Exists in platform.h upstream, local copy here to enable test backports
+#ifdef WIN32
+#define DIRECTORY_SEPARATOR_CHARACTER '\\'
+#else
+#define DIRECTORY_SEPARATOR_CHARACTER '/'
+#endif
+
 struct test_harness testHarness;
 
 class ThreadData {
@@ -11851,6 +11859,56 @@ static enum test_result test_mb19153(ENGINE_HANDLE *h,
     return SUCCESS;
 }
 
+static void force_vbstate_to_25x(std::string dbname, int vbucket) {
+    std::stringstream ss;
+    ss << dbname << DIRECTORY_SEPARATOR_CHARACTER << vbucket << ".couch.1";
+    std::string filename = ss.str();
+    Db* handle;
+    couchstore_error_t err = couchstore_open_db(filename.c_str(),
+                                                COUCHSTORE_OPEN_FLAG_CREATE,
+                                                &handle);
+
+    checkeq(COUCHSTORE_SUCCESS, err, "Failed to open new database");
+
+    // Create 2.5 _local/vbstate
+    std::string vbstate2_5_x ="{\"state\": \"active\","
+                              " \"checkpoint_id\": \"1\","
+                              " \"max_deleted_seqno\": \"0\"}";
+    LocalDoc vbstate;
+    vbstate.id.buf = (char *)"_local/vbstate";
+    vbstate.id.size = sizeof("_local/vbstate") - 1;
+    vbstate.json.buf = (char *)vbstate2_5_x.c_str();
+    vbstate.json.size = vbstate2_5_x.size();
+    vbstate.deleted = 0;
+
+    err = couchstore_save_local_document(handle, &vbstate);
+    checkeq(COUCHSTORE_SUCCESS, err, "Failed to write local document");
+    couchstore_commit(handle);
+    couchstore_close_db(handle);
+}
+
+// Regression test for MB-19635
+// Check that warming up from a 2.x couchfile doesn't end up with a UUID of 0
+// we warmup 2 vbuckets and ensure they get unique IDs.
+static enum test_result test_mb19635_upgrade_from_25x(ENGINE_HANDLE *h,
+                                                      ENGINE_HANDLE_V1 *h1) {
+    std::string dbname = dbname_env;
+
+    force_vbstate_to_25x(dbname, 0);
+    force_vbstate_to_25x(dbname, 1);
+
+    // Now shutdown engine force and restart to warmup from the 2.5.x data.
+    testHarness.reload_engine(&h, &h1,
+                              testHarness.engine_path,
+                              testHarness.get_current_testcase()->cfg,
+                              true, false);
+    wait_for_warmup_complete(h, h1);
+    uint64_t vb_uuid0 = get_ull_stat(h, h1, "vb_0:uuid", "vbucket-details");
+    uint64_t vb_uuid1 = get_ull_stat(h, h1, "vb_1:uuid", "vbucket-details");
+    checkne(vb_uuid0, vb_uuid1, "UUID is not unique");
+    return SUCCESS;
+}
+
 static enum test_result prepare(engine_test_t *test) {
 #ifdef __sun
         // Some of the tests doesn't work on Solaris.. Don't know why yet..
@@ -12797,6 +12855,11 @@ engine_test_t* get_tests(void) {
 
         TestCase("test dcp early termination", test_dcp_early_termination,
                  test_setup, teardown, NULL, prepare, cleanup),
+
+        TestCase("test_mb19635_upgrade_from_25x",
+                 test_mb19635_upgrade_from_25x, test_setup, teardown, NULL,
+                 prepare, cleanup),
+
         TestCase(NULL, NULL, NULL, NULL, NULL, prepare, cleanup)
     };