summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@mongodb.com>2017-02-14 17:59:57 -0500
committerSpencer T Brody <spencer@mongodb.com>2017-03-02 11:00:50 -0500
commit92d9fb1162f40e1feeb21c534f9e6b278e050d64 (patch)
tree2cc08a1a409c2615096f9a20fc2da50af53253a5
parent633a7101f5c0c21ef895b92c695dee9f012bbefc (diff)
downloadmongo-92d9fb1162f40e1feeb21c534f9e6b278e050d64.tar.gz
SERVER-28013 Ensure that last op for client only moves forward
(cherry picked from commit 34c00f16a8890775c71c63c860e2086c6bb603aa)
-rw-r--r--src/mongo/db/repl/oplog.cpp8
-rw-r--r--src/mongo/db/repl/repl_client_info.cpp5
-rw-r--r--src/mongo/db/repl/repl_client_info.h10
-rw-r--r--src/mongo/dbtests/repltests.cpp6
4 files changed, 22 insertions, 7 deletions
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 833da2a2e86..24700262de6 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -375,10 +375,10 @@ void _logOpsInner(OperationContext* txn,
checkOplogInsert(oplogCollection->insertDocumentsForOplog(txn, writers, nWriters));
// Set replCoord last optime only after we're sure the WUOW didn't abort and roll back.
- txn->recoveryUnit()->onCommit(
- [replCoord, finalOpTime] { replCoord->setMyLastAppliedOpTimeForward(finalOpTime); });
-
- ReplClientInfo::forClient(txn->getClient()).setLastOp(finalOpTime);
+ txn->recoveryUnit()->onCommit([txn, replCoord, finalOpTime] {
+ replCoord->setMyLastAppliedOpTimeForward(finalOpTime);
+ ReplClientInfo::forClient(txn->getClient()).setLastOp(finalOpTime);
+ });
}
void logOp(OperationContext* txn,
diff --git a/src/mongo/db/repl/repl_client_info.cpp b/src/mongo/db/repl/repl_client_info.cpp
index 678938f2755..3e98a0cb9d3 100644
--- a/src/mongo/db/repl/repl_client_info.cpp
+++ b/src/mongo/db/repl/repl_client_info.cpp
@@ -43,6 +43,11 @@ namespace repl {
const Client::Decoration<ReplClientInfo> ReplClientInfo::forClient =
Client::declareDecoration<ReplClientInfo>();
+void ReplClientInfo::setLastOp(const OpTime& ot) {
+ invariant(ot >= _lastOp);
+ _lastOp = ot;
+}
+
void ReplClientInfo::setLastOpToSystemLastOpTime(OperationContext* txn) {
ReplicationCoordinator* replCoord = repl::ReplicationCoordinator::get(txn->getServiceContext());
if (replCoord->isReplEnabled() && txn->writesAreReplicated()) {
diff --git a/src/mongo/db/repl/repl_client_info.h b/src/mongo/db/repl/repl_client_info.h
index 4c01119b794..3c81953d65f 100644
--- a/src/mongo/db/repl/repl_client_info.h
+++ b/src/mongo/db/repl/repl_client_info.h
@@ -45,13 +45,17 @@ class ReplClientInfo {
public:
static const Client::Decoration<ReplClientInfo> forClient;
- void setLastOp(const OpTime& op) {
- _lastOp = op;
- }
+ void setLastOp(const OpTime& op);
+
OpTime getLastOp() const {
return _lastOp;
}
+ // Resets the last op on this client; should only be used in testing.
+ void clearLastOp_forTest() {
+ _lastOp = OpTime();
+ }
+
void setLastSnapshot(SnapshotName name) {
_lastSnapshot = name;
}
diff --git a/src/mongo/dbtests/repltests.cpp b/src/mongo/dbtests/repltests.cpp
index e547f4aa8a6..e10f536c21f 100644
--- a/src/mongo/dbtests/repltests.cpp
+++ b/src/mongo/dbtests/repltests.cpp
@@ -45,6 +45,7 @@
#include "mongo/db/ops/update.h"
#include "mongo/db/repl/master_slave.h"
#include "mongo/db/repl/oplog.h"
+#include "mongo/db/repl/repl_client_info.h"
#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/db/repl/replication_coordinator_mock.h"
#include "mongo/db/repl/sync_tail.h"
@@ -78,6 +79,11 @@ public:
replSettings.setMaster(true);
setGlobalReplicationCoordinator(new repl::ReplicationCoordinatorMock(replSettings));
+ // Since the Client object persists across tests, even though the global
+ // ReplicationCoordinator does not, we need to clear the last op associated with the client
+ // to avoid the invariant in ReplClientInfo::setLastOp that the optime only goes forward.
+ repl::ReplClientInfo::forClient(_txn.getClient()).clearLastOp_forTest();
+
getGlobalServiceContext()->setOpObserver(stdx::make_unique<OpObserverImpl>());
setOplogCollectionName();