summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp')
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp34
1 files changed, 32 insertions, 2 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()) {