Merge remote-tracking branch 'couchbase/3.0.x' into sherlock 89/65189/2
authorDave Rigby <daver@couchbase.com>
Tue, 28 Jun 2016 15:13:14 +0000 (16:13 +0100)
committerDave Rigby <daver@couchbase.com>
Tue, 28 Jun 2016 15:14:34 +0000 (16:14 +0100)
* couchbase/3.0.x:
  MB-19343: Use cb_gmtime_r instead of gmtime_r
  [BP] MB-16366: Obtain vbstate readlock in numerous operations
  MB-19280: Fix data race in CouchKVStore stats access
  MB-19279: Fix race in use of gmtime()
  MB-19113: Suppress test_mb16357 when on thread sanitizer

Change-Id: Id289ae95e6fc5e03a64957cc41f53af9ee262a2a

1  2 
src/couch-kvstore/couch-kvstore.h
src/ep.cc
src/ep.h
tests/ep_testsuite.cc

@@@ -608,9 -636,15 +609,14 @@@ public
  
      void removeCompactFile(const std::string &filename);
  
 -    EPStats &epStats;
      Configuration &configuration;
      const std::string dbname;
-     std::vector<uint64_t>dbFileRevMap;
+     // Map of the fileRev for each vBucket. Using RelaxedAtomic so
+     // stats gathering (doDcpVbTakeoverStats) can get a snapshot
+     // without having to lock.
+     std::vector<Couchbase::RelaxedAtomic<uint64_t> > dbFileRevMap;
      uint16_t numDbFiles;
      std::vector<CouchRequest *> pendingReqsQ;
      bool intransaction;
diff --cc src/ep.cc
+++ b/src/ep.cc
@@@ -585,10 -534,12 +573,12 @@@ StoredValue *EventuallyPersistentStore:
              if (vb->getState() != vbucket_state_active) {
                  return wantDeleted ? v : NULL;
              }
-             if (queueExpired) {
+             ReaderLockHolder(vb->getStateLock());
+             // queueDirty only allowed on active VB
+             if (queueExpired && vb->getState() == vbucket_state_active) {
                  incExpirationStat(vb, false);
                  vb->ht.unlocked_softDelete(v, 0, eviction_policy);
 -                queueDirty(vb, v, NULL, false, true);
 +                queueDirty(vb, v, NULL, NULL, false, true);
              }
              return wantDeleted ? v : NULL;
          }
@@@ -925,15 -836,20 +939,22 @@@ ENGINE_ERROR_CODE EventuallyPersistentS
      }
  }
  
 -ENGINE_ERROR_CODE EventuallyPersistentStore::addTAPBackfillItem(const Item &itm,
 -                                                                uint8_t nru,
 -                                                                bool genBySeqno) {
 +ENGINE_ERROR_CODE EventuallyPersistentStore::addTAPBackfillItem(
 +                                                        const Item &itm,
 +                                                        uint8_t nru,
 +                                                        bool genBySeqno,
 +                                                        ExtendedMetaData *emd) {
  
      RCPtr<VBucket> vb = getVBucket(itm.getVBucketId());
-     if (!vb ||
-         vb->getState() == vbucket_state_dead ||
+     if (!vb) {
+         ++stats.numNotMyVBuckets;
+         return ENGINE_NOT_MY_VBUCKET;
+     }
+     // Obtain read-lock on VB state to ensure VB state changes are interlocked
+     // with this add-tapbackfill
+     ReaderLockHolder(vb->getStateLock());
+     if (vb->getState() == vbucket_state_dead ||
          vb->getState() == vbucket_state_active) {
          ++stats.numNotMyVBuckets;
          return ENGINE_NOT_MY_VBUCKET;
@@@ -2049,20 -1824,23 +2072,26 @@@ ENGINE_ERROR_CODE EventuallyPersistentS
      }
  }
  
 -ENGINE_ERROR_CODE EventuallyPersistentStore::setWithMeta(const Item &itm,
 -                                                         uint64_t cas,
 -                                                         const void *cookie,
 -                                                         bool force,
 -                                                         bool allowExisting,
 -                                                         uint8_t nru,
 -                                                         bool genBySeqno,
 -                                                         bool isReplication)
 +ENGINE_ERROR_CODE EventuallyPersistentStore::setWithMeta(
 +                                                     const Item &itm,
 +                                                     uint64_t cas,
 +                                                     uint64_t *seqno,
 +                                                     const void *cookie,
 +                                                     bool force,
 +                                                     bool allowExisting,
 +                                                     uint8_t nru,
 +                                                     bool genBySeqno,
 +                                                     ExtendedMetaData *emd,
 +                                                     bool isReplication)
  {
      RCPtr<VBucket> vb = getVBucket(itm.getVBucketId());
-     if (!vb || vb->getState() == vbucket_state_dead) {
+     if (!vb) {
+         ++stats.numNotMyVBuckets;
+         return ENGINE_NOT_MY_VBUCKET;
+     }
+     ReaderLockHolder(vb->getStateLock());
+     if (vb->getState() == vbucket_state_dead) {
          ++stats.numNotMyVBuckets;
          return ENGINE_NOT_MY_VBUCKET;
      } else if (vb->getState() == vbucket_state_replica && !force) {
@@@ -2230,9 -1967,12 +2259,12 @@@ GetValue EventuallyPersistentStore::get
                      ENGINE_SUCCESS, v->getBySeqno());
  
          if (exptime_mutated) {
-             // persist the item in the underlying storage for
-             // mutated exptime
-             queueDirty(vb, v, &lh, NULL);
+             ReaderLockHolder(vb->getStateLock());
+             if (vb->getState() == vbucket_state_active) {
+                 // persist the item in the underlying storage for
+                 // mutated exptime but only if VB is active.
 -                queueDirty(vb, v, &lh);
++                queueDirty(vb, v, &lh, NULL);
+             }
          }
          return rv;
      } else {
diff --cc src/ep.h
Simple merge
@@@ -15537,21 -12787,9 +15544,21 @@@ engine_test_t* get_tests(void) 
  
          TestCase("test failover log behavior", test_failover_log_behavior,
                   test_setup, teardown, NULL, prepare, cleanup),
 +
 +#if defined(HAVE_JEMALLOC)
 +        TestCase("test defragmenter", test_defragmenter,
 +                 test_setup, teardown,
 +                 "defragmenter_interval=9999"
 +                 ";defragmenter_age_threshold=0"
 +                 ";defragmenter_chunk_duration=99999",
 +                 prepare, cleanup),
 +#endif
 +
 +        TestCase("test hlc cas", test_hlc_cas, test_setup, teardown,
 +                 NULL, prepare, cleanup),
          TestCase("test get all vb seqnos", test_get_all_vb_seqnos, test_setup,
                   teardown, NULL, prepare, cleanup),
+ #if !defined(THREAD_SANITIZER)
          TestCase("test MB-16357", test_mb16357,
                   test_setup, teardown, "compaction_exp_mem_threshold=85",
                   prepare, cleanup),