summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Hernandez <scotthernandez@gmail.com>2016-01-05 13:27:39 -0500
committerScott Hernandez <scotthernandez@gmail.com>2016-01-05 13:31:44 -0500
commita14d55980c2cdc565d4704a7e3ad37e4e535c1b2 (patch)
treef2e502c9fe36a6dfcbec669f32e56a9ce13ab3c4
parent0d3d4aacc239c507f660bb4295217df92d9cfe79 (diff)
downloadmongo-r3.2.1-rc3.tar.gz
SERVER-21867: Throw WCE when next isn't next for WTRecordStore or WTIndex during forward iterationr3.2.1-rc3r3.2.1
(cherry picked from commit 490baef98fde3131a5a328c1f809ab02cecd5c62)
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp34
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp19
2 files changed, 50 insertions, 3 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp
index 9c51f2cc2a8..bd522ebf4bc 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp
@@ -51,6 +51,7 @@
#include "mongo/db/storage/storage_options.h"
#include "mongo/stdx/memory.h"
#include "mongo/util/assert_util.h"
+#include "mongo/util/hex.h"
#include "mongo/util/fail_point.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
@@ -72,6 +73,8 @@
namespace mongo {
namespace {
+MONGO_FP_DECLARE(WTEmulateOutOfOrderNextIndexKey);
+
using std::string;
using std::vector;
@@ -617,7 +620,7 @@ public:
if (!_lastMoveWasRestore)
advanceWTCursor();
- updatePosition();
+ updatePosition(true);
return curr(parts);
}
@@ -807,7 +810,7 @@ protected:
* be called after a restore that did not restore to original state since that does not
* logically move the cursor until the following call to next().
*/
- void updatePosition() {
+ void updatePosition(bool inNext = false) {
_lastMoveWasRestore = false;
if (_cursorAtEof) {
_eof = true;
@@ -820,6 +823,33 @@ protected:
WT_CURSOR* c = _cursor->get();
WT_ITEM item;
invariantWTOK(c->get_key(c, &item));
+
+ const auto isForwardNextCall = _forward && inNext && !_key.isEmpty();
+ if (isForwardNextCall) {
+ // Due to a bug in wired tiger (SERVER-21867) sometimes calling next
+ // returns something prev.
+ const int cmp =
+ std::memcmp(_key.getBuffer(), item.data, std::min(_key.getSize(), item.size));
+ bool nextNotIncreasing = cmp > 0 || (cmp == 0 && _key.getSize() > item.size);
+
+ if (MONGO_FAIL_POINT(WTEmulateOutOfOrderNextIndexKey)) {
+ log() << "WTIndex::updatePosition simulating next key not increasing.";
+ nextNotIncreasing = true;
+ }
+
+ if (nextNotIncreasing) {
+ // Our new key is less than the old key which means the next call moved to !next.
+ log() << "WTIndex::updatePosition -- the new key ( " << toHex(item.data, item.size)
+ << ") is less than the previous key (" << _key.toString()
+ << "), which is a bug.";
+
+ // Force a retry of the operation from our last known position by acting as-if
+ // we received a WT_ROLLBACK error.
+ throw WriteConflictException();
+ }
+ }
+
+ // Store (a copy of) the new item data as the current key for this cursor.
_key.resetFromBuffer(item.data, item.size);
if (atOrPastEndPointAfterSeeking()) {
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
index 030b2dd7647..a38a6fd517b 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -91,6 +91,7 @@ bool shouldUseOplogHack(OperationContext* opCtx, const std::string& uri) {
} // namespace
MONGO_FP_DECLARE(WTWriteConflictException);
+MONGO_FP_DECLARE(WTEmulateOutOfOrderNextRecordId);
const std::string kWiredTigerEngineName = "wiredTiger";
@@ -483,7 +484,23 @@ public:
_skipNextAdvance = false;
int64_t key;
invariantWTOK(c->get_key(c, &key));
- const RecordId id = _fromKey(key);
+ RecordId id = _fromKey(key);
+
+ if (_forward && MONGO_FAIL_POINT(WTEmulateOutOfOrderNextRecordId)) {
+ log() << "WTEmulateOutOfOrderNextRecordId fail point has triggerd so RecordId is now "
+ "RecordId(1) instead of " << id;
+ // Replace the found RecordId with a (small) fake one.
+ id = RecordId{1};
+ }
+
+ if (_forward && _lastReturnedId >= id) {
+ log() << "WTCursor::next -- c->next_key ( " << id
+ << ") was not greater than _lastReturnedId (" << _lastReturnedId
+ << ") which is a bug.";
+ // Force a retry of the operation from our last known position by acting as-if
+ // we received a WT_ROLLBACK error.
+ throw WriteConflictException();
+ }
if (!isVisible(id)) {
_eof = true;