MB-17889: DCP producer can leave an operation behind 96/60196/3
authorJim Walker <jim@couchbase.com>
Thu, 18 Feb 2016 15:14:28 +0000 (15:14 +0000)
committerChiyoung Seo <chiyoung@couchbase.com>
Thu, 18 Feb 2016 19:05:56 +0000 (19:05 +0000)
commit61ab9520e4c6a7a9de7ff4ef0c80c6ec7e7c8973
tree2c0c7954b3df08a99f946ff4c43787e2e4c2b30a
parent37d53b1a7339c08dc860003b35bd438e45b3a32f
MB-17889: DCP producer can leave an operation behind

In low-traffic setups there's a case in DcpProducer::getNextItem
where the function exits and pauses the task, yet an item was
waiting to be sent.

getNextItem() looked like

  1. setpaused=false;
  2. while(ready.pop(vbucket)) {
  3.   process(vbucket);
  4. }
  5. setpaused=true;
  6. return NULL;

The notifier

  a. if(ready.pushUnique(vbucket))
  b.   wakeupIfPaused;

If a and b execute between 4 and 5, then the producer will sleep
and not process the vbucket until the next wakeup (which maybe never).

This is not good, the first operation will have a long latency before
it can be seen on DCP. As long as it takes for the second operation.

If a and b occur between 5 and 6, that's fine, wakupIfPaused will re-wake
the producer.

a,b,5,6 is bad
5,a,6,b is ok
5,6,a,b is ok
5,a,b,6 is ok
5,6,a,b is ok
...

The fix.

getNextItem()

  0. do {
  1.   setpaused=false;
  2.   while(ready.pop(vbucket)) {
  3.     process(vbucket);
  4.   }
  5.   setpaused=true;
  6.  } while(!ready.empty());
  7. return NULL;

Now if ab occurs after 4, but before 5, it's ok as 6 will now consume
the vbucket.

5,a,b,6 is ok, as 6 will loop and consume
5,a,6,b is ok, "    "    "    "    "
6,a,b,7 is ok, paused is true (5), b will wake the task

Change-Id: Ib412a85ee10de0e2a2ca4116d0cc85bbad538da2
Reviewed-on: http://review.couchbase.org/60196
Well-Formed: buildbot <build@couchbase.com>
Reviewed-by: Chiyoung Seo <chiyoung@couchbase.com>
Reviewed-by: abhinav dangeti <abhinav@couchbase.com>
Tested-by: buildbot <build@couchbase.com>
src/dcp-producer.cc
src/dcp-producer.h