summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2020-02-03 09:11:19 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-14 10:54:32 +0000
commitb6ef7212c4f1c263e9d997b606c9127601e023e3 (patch)
tree0516c4d3e89e5b4ee7788379804ba46b7340ac43 /src
parenta7a4c477283d6cdddb5d16de6b976b71a7afaffe (diff)
downloadmongo-b6ef7212c4f1c263e9d997b606c9127601e023e3.tar.gz
SERVER-45120 Move 'localSetTime' out of the RWConcernDefault IDL
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/SConscript2
-rw-r--r--src/mongo/db/auth/authorization_manager_global.cpp30
-rw-r--r--src/mongo/db/commands/read_write_concern_defaults_server_status.cpp7
-rw-r--r--src/mongo/db/commands/rwc_defaults_commands.cpp28
-rw-r--r--src/mongo/db/commands/rwc_defaults_commands.idl24
-rw-r--r--src/mongo/db/op_observer_impl.cpp1
-rw-r--r--src/mongo/db/op_observer_impl_test.cpp20
-rw-r--r--src/mongo/db/read_write_concern_defaults.cpp85
-rw-r--r--src/mongo/db/read_write_concern_defaults.h29
-rw-r--r--src/mongo/db/read_write_concern_defaults.idl (renamed from src/mongo/db/rw_concern_default.idl)22
-rw-r--r--src/mongo/db/read_write_concern_defaults_test.cpp182
-rw-r--r--src/mongo/db/repl/rs_rollback_test.cpp23
-rw-r--r--src/mongo/s/commands/cluster_rwc_defaults_commands.cpp24
-rw-r--r--src/mongo/s/commands/s_read_write_concern_defaults_server_status.cpp7
-rw-r--r--src/mongo/util/read_through_cache.h96
15 files changed, 339 insertions, 241 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 08e9800be1c..780a18011d4 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -374,7 +374,7 @@ env.Library(
target='read_write_concern_defaults',
source=[
'read_write_concern_defaults.cpp',
- env.Idlc('rw_concern_default.idl')[0],
+ env.Idlc('read_write_concern_defaults.idl')[0],
],
LIBDEPS=[
'repl/read_concern_args',
diff --git a/src/mongo/db/auth/authorization_manager_global.cpp b/src/mongo/db/auth/authorization_manager_global.cpp
index e549de2f404..af3342c1c5d 100644
--- a/src/mongo/db/auth/authorization_manager_global.cpp
+++ b/src/mongo/db/auth/authorization_manager_global.cpp
@@ -38,10 +38,23 @@
#include "mongo/util/assert_util.h"
namespace mongo {
+namespace {
-// This setting is unique in that it is read-only.
-// The IDL subststem doesn't actually allow for that,
-// so we'll pretend it's startup-settable, then override it here.
+ServiceContext::ConstructorActionRegisterer createAuthorizationManager(
+ "CreateAuthorizationManager",
+ {"OIDGeneration", "EndStartupOptionStorage"},
+ [](ServiceContext* service) {
+ auto authzManager = AuthorizationManager::create();
+ authzManager->setAuthEnabled(serverGlobalParams.authState ==
+ ServerGlobalParams::AuthState::kEnabled);
+ authzManager->setShouldValidateAuthSchemaOnStartup(gStartupAuthSchemaValidation);
+ AuthorizationManager::set(service, std::move(authzManager));
+ });
+
+} // namespace
+
+// This setting is unique in that it is read-only. The IDL subststem doesn't actually allow for
+// that, so we'll pretend it's startup-settable, then override it here.
AuthzVersionParameter::AuthzVersionParameter(StringData name, ServerParameterType)
: ServerParameter(ServerParameterSet::getGlobal(), name, false, false) {}
@@ -58,15 +71,4 @@ Status AuthzVersionParameter::setFromString(const std::string& newValueString) {
return {ErrorCodes::InternalError, "set called on unsettable server parameter"};
}
-ServiceContext::ConstructorActionRegisterer createAuthorizationManager(
- "CreateAuthorizationManager",
- {"OIDGeneration", "EndStartupOptionStorage"},
- [](ServiceContext* service) {
- auto authzManager = AuthorizationManager::create();
- authzManager->setAuthEnabled(serverGlobalParams.authState ==
- ServerGlobalParams::AuthState::kEnabled);
- authzManager->setShouldValidateAuthSchemaOnStartup(gStartupAuthSchemaValidation);
- AuthorizationManager::set(service, std::move(authzManager));
- });
-
} // namespace mongo
diff --git a/src/mongo/db/commands/read_write_concern_defaults_server_status.cpp b/src/mongo/db/commands/read_write_concern_defaults_server_status.cpp
index 6f2cfc6f8b5..16f3d6d0235 100644
--- a/src/mongo/db/commands/read_write_concern_defaults_server_status.cpp
+++ b/src/mongo/db/commands/read_write_concern_defaults_server_status.cpp
@@ -29,6 +29,7 @@
#include "mongo/platform/basic.h"
+#include "mongo/db/commands/rwc_defaults_commands_gen.h"
#include "mongo/db/commands/server_status.h"
#include "mongo/db/read_write_concern_defaults.h"
#include "mongo/db/repl/replication_coordinator.h"
@@ -51,7 +52,11 @@ public:
return {};
}
- return ReadWriteConcernDefaults::get(opCtx).getDefault(opCtx).toBSON();
+ auto rwcDefault = ReadWriteConcernDefaults::get(opCtx).getDefault(opCtx);
+ GetDefaultRWConcernResponse response;
+ response.setRWConcernDefault(rwcDefault);
+ response.setLocalUpdateWallClockTime(rwcDefault.localUpdateWallClockTime());
+ return response.toBSON();
}
} defaultRWConcernServerStatus;
diff --git a/src/mongo/db/commands/rwc_defaults_commands.cpp b/src/mongo/db/commands/rwc_defaults_commands.cpp
index 2352c1650d7..0cbf5636a09 100644
--- a/src/mongo/db/commands/rwc_defaults_commands.cpp
+++ b/src/mongo/db/commands/rwc_defaults_commands.cpp
@@ -40,7 +40,6 @@
#include "mongo/db/read_write_concern_defaults.h"
#include "mongo/db/repl/read_concern_args.h"
#include "mongo/db/repl/replication_coordinator.h"
-#include "mongo/db/rw_concern_default_gen.h"
#include "mongo/logv2/log.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/util/log.h"
@@ -82,6 +81,17 @@ void assertNotStandaloneOrShardServer(OperationContext* opCtx, StringData cmdNam
serverGlobalParams.clusterRole != ClusterRole::ShardServer);
}
+auto makeResponse(const ReadWriteConcernDefaults::RWConcernDefaultAndTime& rwcDefault,
+ bool inMemory) {
+ GetDefaultRWConcernResponse response;
+ response.setRWConcernDefault(rwcDefault);
+ response.setLocalUpdateWallClockTime(rwcDefault.localUpdateWallClockTime());
+ if (inMemory)
+ response.setInMemory(true);
+
+ return response;
+}
+
class SetDefaultRWConcernCommand : public TypedCommand<SetDefaultRWConcernCommand> {
public:
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
@@ -121,7 +131,7 @@ public:
// Refresh to populate the cache with the latest defaults.
rwcDefaults.refreshIfNecessary(opCtx);
- return rwcDefaults.getDefault(opCtx);
+ return makeResponse(rwcDefaults.getDefault(opCtx), false);
}
private:
@@ -166,15 +176,14 @@ public:
assertNotStandaloneOrShardServer(opCtx, GetDefaultRWConcern::kCommandName);
auto& rwcDefaults = ReadWriteConcernDefaults::get(opCtx->getServiceContext());
- if (request().getInMemory() && *request().getInMemory()) {
- auto rwc = rwcDefaults.getDefault(opCtx);
- rwc.setInMemory(true);
- return rwc;
+ const bool inMemory = request().getInMemory().value_or(false);
+ if (!inMemory) {
+ // If not asking for the in-memory values, force a refresh to find the most recent
+ // defaults
+ rwcDefaults.refreshIfNecessary(opCtx);
}
- // Force a refresh to find the most recent defaults, then return them.
- rwcDefaults.refreshIfNecessary(opCtx);
- return rwcDefaults.getDefault(opCtx);
+ return makeResponse(rwcDefaults.getDefault(opCtx), inMemory);
}
private:
@@ -195,5 +204,6 @@ public:
}
};
} getDefaultRWConcernCommand;
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/commands/rwc_defaults_commands.idl b/src/mongo/db/commands/rwc_defaults_commands.idl
index ad8efef676f..6d0f8d98c32 100644
--- a/src/mongo/db/commands/rwc_defaults_commands.idl
+++ b/src/mongo/db/commands/rwc_defaults_commands.idl
@@ -32,11 +32,31 @@ global:
imports:
- "mongo/idl/basic_types.idl"
- "mongo/db/repl/read_concern_args.idl"
+ - "mongo/db/read_write_concern_defaults.idl"
- "mongo/db/write_concern_options.idl"
+structs:
+ GetDefaultRWConcernResponse:
+ description: "Describes the response for the getDefaultRWConcern command"
+ strict: false
+ chained_structs:
+ RWConcernDefault: RWConcernDefault
+ fields:
+ inMemory:
+ description: "Whether the value came from the in-memory cache or it reflects the
+ defaults which were persisted as of the time of invocation."
+ optional: true
+ type: bool
+ localUpdateWallClockTime:
+ description: "The wallclock time of when the default read or write concern was
+ applied to the cache of the node, which returned the response. This
+ value is only informational and must not be used for any recency
+ comparisons."
+ type: date
+
commands:
setDefaultRWConcern:
- description: "set the current read/write concern defaults (cluster-wide)"
+ description: "Set the current read/write concern defaults (cluster-wide)"
namespace: ignored
fields:
defaultReadConcern:
@@ -49,7 +69,7 @@ commands:
optional: true
getDefaultRWConcern:
- description: "get the current read/write concern defaults being applied by this node"
+ description: "Get the current read/write concern defaults being applied by this node"
namespace: ignored
fields:
inMemory:
diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp
index 26de717a90a..22f880514e1 100644
--- a/src/mongo/db/op_observer_impl.cpp
+++ b/src/mongo/db/op_observer_impl.cpp
@@ -53,7 +53,6 @@
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/oplog_entry_gen.h"
#include "mongo/db/repl/replication_coordinator.h"
-#include "mongo/db/rw_concern_default_gen.h"
#include "mongo/db/s/collection_sharding_state.h"
#include "mongo/db/server_options.h"
#include "mongo/db/session_catalog_mongod.h"
diff --git a/src/mongo/db/op_observer_impl_test.cpp b/src/mongo/db/op_observer_impl_test.cpp
index 06b18144353..79270c9b5cd 100644
--- a/src/mongo/db/op_observer_impl_test.cpp
+++ b/src/mongo/db/op_observer_impl_test.cpp
@@ -2306,25 +2306,25 @@ TEST_F(OpObserverTest, OnRollbackInvalidatesDefaultRWConcernCache) {
// Put initial defaults in the cache.
{
RWConcernDefault origDefaults;
- origDefaults.setEpoch(Timestamp(10, 20));
- origDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ origDefaults.setUpdateOpTime(Timestamp(10, 20));
+ origDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(origDefaults));
}
auto origCachedDefaults = rwcDefaults.getDefault(opCtx.get());
- ASSERT_EQ(Timestamp(10, 20), *origCachedDefaults.getEpoch());
- ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *origCachedDefaults.getSetTime());
+ ASSERT_EQ(Timestamp(10, 20), *origCachedDefaults.getUpdateOpTime());
+ ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *origCachedDefaults.getUpdateWallClockTime());
// Change the mock's defaults, but don't invalidate the cache yet. The cache should still return
// the original defaults.
{
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(50, 20));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(5678));
+ newDefaults.setUpdateOpTime(Timestamp(50, 20));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto cachedDefaults = rwcDefaults.getDefault(opCtx.get());
- ASSERT_EQ(Timestamp(10, 20), *cachedDefaults.getEpoch());
- ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *cachedDefaults.getSetTime());
+ ASSERT_EQ(Timestamp(10, 20), *cachedDefaults.getUpdateOpTime());
+ ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *cachedDefaults.getUpdateWallClockTime());
}
// Rollback to a timestamp should invalidate the cache and getting the defaults should now
@@ -2335,8 +2335,8 @@ TEST_F(OpObserverTest, OnRollbackInvalidatesDefaultRWConcernCache) {
opObserver.onReplicationRollback(opCtx.get(), rbInfo);
}
auto newCachedDefaults = rwcDefaults.getDefault(opCtx.get());
- ASSERT_EQ(Timestamp(50, 20), *newCachedDefaults.getEpoch());
- ASSERT_EQ(Date_t::fromMillisSinceEpoch(5678), *newCachedDefaults.getSetTime());
+ ASSERT_EQ(Timestamp(50, 20), *newCachedDefaults.getUpdateOpTime());
+ ASSERT_EQ(Date_t::fromMillisSinceEpoch(5678), *newCachedDefaults.getUpdateWallClockTime());
}
} // namespace
diff --git a/src/mongo/db/read_write_concern_defaults.cpp b/src/mongo/db/read_write_concern_defaults.cpp
index 4f4113e1db8..020d094cd72 100644
--- a/src/mongo/db/read_write_concern_defaults.cpp
+++ b/src/mongo/db/read_write_concern_defaults.cpp
@@ -43,38 +43,6 @@ namespace {
static constexpr auto kReadConcernLevelsDisallowedAsDefault = {
repl::ReadConcernLevel::kSnapshotReadConcern, repl::ReadConcernLevel::kLinearizableReadConcern};
-/**
- * Used to invalidate the cache on updates to the persisted defaults document.
- */
-class OnUpdateCommitHandler final : public RecoveryUnit::Change {
-public:
- // rwcDefaults must outlive instantiations of this class.
- OnUpdateCommitHandler(ServiceContext* service,
- ReadWriteConcernDefaults* rwcDefaults,
- const boost::optional<BSONObj>& newDefaultsDoc)
- : _service(service), _rwcDefaults(rwcDefaults) {
- // Note this will throw if the document can't be parsed. In the case of a delete, there will
- // be no new defaults document and the RWConcern will be default constructed, which matches
- // the behavior when lookup discovers a non-existent defaults document.
- _rwc = newDefaultsDoc
- ? RWConcernDefault::parse(IDLParserErrorContext("RWDefaultsWriteObserver"),
- *newDefaultsDoc)
- : RWConcernDefault();
- }
-
- void commit(boost::optional<Timestamp> timestamp) final {
- _rwc.setLocalSetTime(_service->getFastClockSource()->now());
- _rwcDefaults->setDefault(std::move(_rwc));
- }
-
- void rollback() final {}
-
-private:
- ServiceContext* _service;
- ReadWriteConcernDefaults* _rwcDefaults;
- RWConcernDefault _rwc;
-};
-
const auto getReadWriteConcernDefaults =
ServiceContext::declareDecoration<std::unique_ptr<ReadWriteConcernDefaults>>();
@@ -134,10 +102,10 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewConcerns(
checkSuitabilityAsDefault(*wc);
rwc.setDefaultWriteConcern(wc);
}
- auto epoch = LogicalClock::get(opCtx->getServiceContext())->getClusterTime().asTimestamp();
- rwc.setEpoch(epoch);
- auto now = opCtx->getServiceContext()->getFastClockSource()->now();
- rwc.setSetTime(now);
+
+ auto* const serviceContext = opCtx->getServiceContext();
+ rwc.setUpdateOpTime(LogicalClock::get(serviceContext)->getClusterTime().asTimestamp());
+ rwc.setUpdateWallClockTime(serviceContext->getFastClockSource()->now());
auto current = _getDefault(opCtx);
if (!rc && current) {
@@ -158,16 +126,28 @@ void ReadWriteConcernDefaults::observeDirectWriteToConfigSettings(OperationConte
return;
}
- opCtx->recoveryUnit()->registerChange(
- std::make_unique<OnUpdateCommitHandler>(opCtx->getServiceContext(), this, newDoc));
+ // Note this will throw if the document can't be parsed. In the case of a delete, there will be
+ // no new defaults document and the RWConcern will be default constructed, which matches the
+ // behavior when lookup discovers a non-existent defaults document.
+ auto newDefaultsDoc = newDoc
+ ? RWConcernDefault::parse(IDLParserErrorContext("RWDefaultsWriteObserver"),
+ newDoc->getOwned())
+ : RWConcernDefault();
+
+ opCtx->recoveryUnit()->onCommit([this, opCtx, newDefaultsDoc = std::move(newDefaultsDoc)](
+ boost::optional<Timestamp> unusedCommitTime) mutable {
+ setDefault(opCtx, std::move(newDefaultsDoc));
+ });
}
void ReadWriteConcernDefaults::invalidate() {
_defaults.invalidate(Type::kReadWriteConcernEntry);
}
-void ReadWriteConcernDefaults::setDefault(RWConcernDefault&& rwc) {
- _defaults.insertOrAssignAndGet(Type::kReadWriteConcernEntry, std::move(rwc));
+void ReadWriteConcernDefaults::setDefault(OperationContext* opCtx, RWConcernDefault&& rwc) {
+ _defaults.insertOrAssignAndGet(Type::kReadWriteConcernEntry,
+ std::move(rwc),
+ opCtx->getServiceContext()->getFastClockSource()->now());
}
void ReadWriteConcernDefaults::refreshIfNecessary(OperationContext* opCtx) {
@@ -177,18 +157,19 @@ void ReadWriteConcernDefaults::refreshIfNecessary(OperationContext* opCtx) {
}
auto currentDefaultsHandle = _defaults.acquire(opCtx, Type::kReadWriteConcernEntry);
- if (!currentDefaultsHandle || !possibleNewDefaults->getEpoch() ||
- (possibleNewDefaults->getEpoch() > currentDefaultsHandle->getEpoch())) {
+ if (!currentDefaultsHandle || !possibleNewDefaults->getUpdateOpTime() ||
+ (possibleNewDefaults->getUpdateOpTime() > currentDefaultsHandle->getUpdateOpTime())) {
// Use the new defaults if they have a higher epoch, if there are no defaults in the cache,
// or if the found defaults have no epoch, meaning there are no defaults in config.settings.
LOGV2(20997,
- "refreshed RWC defaults to {possibleNewDefaults}",
- "possibleNewDefaults"_attr = possibleNewDefaults->toBSON());
- setDefault(std::move(*possibleNewDefaults));
+ "refreshed RWC defaults to {newDefaults}",
+ "newDefaults"_attr = possibleNewDefaults->toBSON());
+ setDefault(opCtx, std::move(*possibleNewDefaults));
}
}
-boost::optional<RWConcernDefault> ReadWriteConcernDefaults::_getDefault(OperationContext* opCtx) {
+boost::optional<ReadWriteConcernDefaults::RWConcernDefaultAndTime>
+ReadWriteConcernDefaults::_getDefault(OperationContext* opCtx) {
auto defaultsHandle = _defaults.acquire(opCtx, Type::kReadWriteConcernEntry);
if (defaultsHandle) {
// Since CWRWC is ok with continuing to use a value well after it has been invalidated
@@ -196,7 +177,7 @@ boost::optional<RWConcernDefault> ReadWriteConcernDefaults::_getDefault(Operatio
// defaultsValue.isValid() here, and we don't need to return the Handle, since callers don't
// need to check defaultsValue.isValid() later, either. Just dereference it to get the
// underlying contents.
- return *defaultsHandle;
+ return RWConcernDefaultAndTime(*defaultsHandle, defaultsHandle.updateWallClockTime());
}
return boost::none;
}
@@ -213,10 +194,6 @@ ReadWriteConcernDefaults::getDefaultWriteConcern(OperationContext* opCtx) {
return current.getDefaultWriteConcern();
}
-RWConcernDefault ReadWriteConcernDefaults::getDefault(OperationContext* opCtx) {
- return _getDefault(opCtx).value_or(RWConcernDefault());
-}
-
ReadWriteConcernDefaults& ReadWriteConcernDefaults::get(ServiceContext* service) {
return *getReadWriteConcernDefaults(service);
}
@@ -242,11 +219,7 @@ ReadWriteConcernDefaults::Cache::Cache(LookupFn lookupFn)
boost::optional<RWConcernDefault> ReadWriteConcernDefaults::Cache::lookup(
OperationContext* opCtx, const ReadWriteConcernDefaults::Type& key) {
invariant(key == Type::kReadWriteConcernEntry);
- auto newDefaults = _lookupFn(opCtx, key);
- if (newDefaults) {
- newDefaults->setLocalSetTime(opCtx->getServiceContext()->getFastClockSource()->now());
- }
- return newDefaults;
+ return _lookupFn(opCtx, key);
}
} // namespace mongo
diff --git a/src/mongo/db/read_write_concern_defaults.h b/src/mongo/db/read_write_concern_defaults.h
index 1f10af61999..d493fdf2cc3 100644
--- a/src/mongo/db/read_write_concern_defaults.h
+++ b/src/mongo/db/read_write_concern_defaults.h
@@ -32,8 +32,8 @@
#include <map>
#include "mongo/db/operation_context.h"
+#include "mongo/db/read_write_concern_defaults_gen.h"
#include "mongo/db/repl/read_concern_args.h"
-#include "mongo/db/rw_concern_default_gen.h"
#include "mongo/db/service_context.h"
#include "mongo/db/write_concern_options.h"
#include "mongo/platform/mutex.h"
@@ -75,7 +75,28 @@ public:
boost::optional<ReadConcern> getDefaultReadConcern(OperationContext* opCtx);
boost::optional<WriteConcern> getDefaultWriteConcern(OperationContext* opCtx);
- RWConcernDefault getDefault(OperationContext* opCtx);
+ class RWConcernDefaultAndTime : public RWConcernDefault {
+ public:
+ RWConcernDefaultAndTime() = default;
+ RWConcernDefaultAndTime(RWConcernDefault rwcd, Date_t localUpdateWallClockTime)
+ : RWConcernDefault(std::move(rwcd)),
+ _localUpdateWallClockTime(localUpdateWallClockTime) {}
+
+ Date_t localUpdateWallClockTime() const {
+ return _localUpdateWallClockTime;
+ }
+
+ private:
+ Date_t _localUpdateWallClockTime;
+ };
+
+ /**
+ * Returns the current set of read/write concern defaults along with the wallclock time when
+ * they were cached (for diagnostic purposes).
+ */
+ RWConcernDefaultAndTime getDefault(OperationContext* opCtx) {
+ return _getDefault(opCtx).value_or(RWConcernDefaultAndTime());
+ }
/**
* Returns true if the RC level is permissible to use as a default, and false if it cannot be a
@@ -128,12 +149,12 @@ public:
/**
* Sets the given read write concern as the defaults in the cache.
*/
- void setDefault(RWConcernDefault&& rwc);
+ void setDefault(OperationContext* opCtx, RWConcernDefault&& rwc);
private:
enum class Type { kReadWriteConcernEntry };
- boost::optional<RWConcernDefault> _getDefault(OperationContext* opCtx);
+ boost::optional<RWConcernDefaultAndTime> _getDefault(OperationContext* opCtx);
class Cache : public ReadThroughCache<Type, RWConcernDefault> {
Cache(const Cache&) = delete;
diff --git a/src/mongo/db/rw_concern_default.idl b/src/mongo/db/read_write_concern_defaults.idl
index 5ff0b997b2a..bdf67c6fca5 100644
--- a/src/mongo/db/rw_concern_default.idl
+++ b/src/mongo/db/read_write_concern_defaults.idl
@@ -28,13 +28,11 @@
global:
cpp_namespace: "mongo"
-
imports:
- "mongo/idl/basic_types.idl"
- "mongo/db/repl/read_concern_args.idl"
- "mongo/db/write_concern_options.idl"
-
structs:
RWConcernDefault:
description: "Represents a set of read/write concern defaults, and associated metadata"
@@ -48,19 +46,15 @@ structs:
description: "The default write concern"
type: WriteConcern
optional: true
- epoch:
- description: "The epoch (unique generation id) of when the default read or write concern was last set"
+ updateOpTime:
+ description: "The optime of when the default read or write concern was last set. On
+ replica sets it advances with the primary's optime and on clusters it
+ advances with the config server primary's optime."
type: timestamp
optional: true
- setTime:
- description: "The wallclock time when the default read or write concern was last set by an administrator"
+ updateWallClockTime:
+ description: "The wallclock time when the default read or write concern was last set
+ by an administrator. This value is only informational and must not be
+ used for any recency comparisons."
type: date
optional: true
- localSetTime:
- description: "The wallclock time when this node updated its understanding of the default read or write concern"
- type: date
- optional: true
- inMemory:
- description: "Whether these defaults were from the inMemory cache"
- type: bool
- optional: true
diff --git a/src/mongo/db/read_write_concern_defaults_test.cpp b/src/mongo/db/read_write_concern_defaults_test.cpp
index 5b726994d1f..69c37853665 100644
--- a/src/mongo/db/read_write_concern_defaults_test.cpp
+++ b/src/mongo/db/read_write_concern_defaults_test.cpp
@@ -64,9 +64,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithAbsentDefaults) {
auto defaults = _rwcd.getDefault(_opCtx);
ASSERT(!defaults.getDefaultReadConcern());
ASSERT(!defaults.getDefaultWriteConcern());
- ASSERT(!defaults.getEpoch());
- ASSERT(!defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT(!defaults.getUpdateOpTime());
+ ASSERT(!defaults.getUpdateWallClockTime());
+ ASSERT_EQ(Date_t(), defaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithDefaultsNeverSet) {
@@ -75,23 +75,23 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithDefaultsNeverSet) {
auto defaults = _rwcd.getDefault(_opCtx);
ASSERT(!defaults.getDefaultReadConcern());
ASSERT(!defaults.getDefaultWriteConcern());
- ASSERT(!defaults.getEpoch());
- ASSERT(!defaults.getSetTime());
- ASSERT(defaults.getLocalSetTime());
+ ASSERT(!defaults.getUpdateOpTime());
+ ASSERT(!defaults.getUpdateWallClockTime());
+ ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
}
TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithUnsetDefaults) {
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(1, 2));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ newDefaults.setUpdateOpTime(Timestamp(1, 2));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto defaults = _rwcd.getDefault(_opCtx);
ASSERT(!defaults.getDefaultReadConcern());
ASSERT(!defaults.getDefaultWriteConcern());
- ASSERT_EQ(Timestamp(1, 2), *defaults.getEpoch());
- ASSERT_EQ(1234, defaults.getSetTime()->toMillisSinceEpoch());
- ASSERT(defaults.getLocalSetTime());
+ ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
+ ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
}
TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetDefaults) {
@@ -101,17 +101,17 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetDefaults) {
WriteConcernOptions wc;
wc.wNumNodes = 4;
newDefaults.setDefaultWriteConcern(wc);
- newDefaults.setEpoch(Timestamp(1, 2));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ newDefaults.setUpdateOpTime(Timestamp(1, 2));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto defaults = _rwcd.getDefault(_opCtx);
ASSERT(defaults.getDefaultReadConcern()->getLevel() ==
repl::ReadConcernLevel::kLocalReadConcern);
ASSERT_EQ(4, defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT_EQ(Timestamp(1, 2), *defaults.getEpoch());
- ASSERT_EQ(1234, defaults.getSetTime()->toMillisSinceEpoch());
- ASSERT(defaults.getLocalSetTime());
+ ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
+ ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
}
TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultLookupFailure) {
@@ -121,16 +121,16 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultLookupFailure) {
TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithoutInvalidateDoesNotCallLookup) {
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(1, 2));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ newDefaults.setUpdateOpTime(Timestamp(1, 2));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto defaults = _rwcd.getDefault(_opCtx);
ASSERT(!defaults.getDefaultReadConcern());
ASSERT(!defaults.getDefaultWriteConcern());
- ASSERT_EQ(Timestamp(1, 2), *defaults.getEpoch());
- ASSERT_EQ(1234, defaults.getSetTime()->toMillisSinceEpoch());
- ASSERT(defaults.getLocalSetTime());
+ ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
+ ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
RWConcernDefault newDefaults2;
newDefaults2.setDefaultReadConcern(
@@ -138,30 +138,30 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithoutInvalidateDoesNotCallL
WriteConcernOptions wc;
wc.wNumNodes = 4;
newDefaults2.setDefaultWriteConcern(wc);
- newDefaults2.setEpoch(Timestamp(3, 4));
- newDefaults2.setSetTime(Date_t::fromMillisSinceEpoch(5678));
+ newDefaults2.setUpdateOpTime(Timestamp(3, 4));
+ newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults2));
auto defaults2 = _rwcd.getDefault(_opCtx);
ASSERT(!defaults2.getDefaultReadConcern());
ASSERT(!defaults2.getDefaultWriteConcern());
- ASSERT_EQ(Timestamp(1, 2), *defaults2.getEpoch());
- ASSERT_EQ(1234, defaults2.getSetTime()->toMillisSinceEpoch());
- ASSERT(defaults2.getLocalSetTime());
+ ASSERT_EQ(Timestamp(1, 2), *defaults2.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults2.getUpdateWallClockTime()->toMillisSinceEpoch());
+ ASSERT_GT(defaults2.localUpdateWallClockTime(), Date_t());
}
TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) {
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(1, 2));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ newDefaults.setUpdateOpTime(Timestamp(1, 2));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto defaults = _rwcd.getDefault(_opCtx);
ASSERT(!defaults.getDefaultReadConcern());
ASSERT(!defaults.getDefaultWriteConcern());
- ASSERT_EQ(Timestamp(1, 2), *defaults.getEpoch());
- ASSERT_EQ(1234, defaults.getSetTime()->toMillisSinceEpoch());
- ASSERT(defaults.getLocalSetTime());
+ ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
+ ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
RWConcernDefault newDefaults2;
newDefaults2.setDefaultReadConcern(
@@ -169,8 +169,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) {
WriteConcernOptions wc;
wc.wNumNodes = 4;
newDefaults2.setDefaultWriteConcern(wc);
- newDefaults2.setEpoch(Timestamp(3, 4));
- newDefaults2.setSetTime(Date_t::fromMillisSinceEpoch(5678));
+ newDefaults2.setUpdateOpTime(Timestamp(3, 4));
+ newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults2));
_rwcd.invalidate();
@@ -178,9 +178,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) {
ASSERT(defaults2.getDefaultReadConcern()->getLevel() ==
repl::ReadConcernLevel::kLocalReadConcern);
ASSERT_EQ(4, defaults2.getDefaultWriteConcern()->wNumNodes);
- ASSERT_EQ(Timestamp(3, 4), *defaults2.getEpoch());
- ASSERT_EQ(5678, defaults2.getSetTime()->toMillisSinceEpoch());
- ASSERT(defaults2.getLocalSetTime());
+ ASSERT_EQ(Timestamp(3, 4), *defaults2.getUpdateOpTime());
+ ASSERT_EQ(5678, defaults2.getUpdateWallClockTime()->toMillisSinceEpoch());
+ ASSERT_GT(defaults2.localUpdateWallClockTime(), Date_t());
}
TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithEmptyCacheAndAbsentDefaults) {
@@ -189,67 +189,67 @@ TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithEmptyCacheAndAbsentD
auto defaults = _rwcd.getDefault(_opCtx);
ASSERT(!defaults.getDefaultReadConcern());
ASSERT(!defaults.getDefaultWriteConcern());
- ASSERT(!defaults.getEpoch());
- ASSERT(!defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT(!defaults.getUpdateOpTime());
+ ASSERT(!defaults.getUpdateWallClockTime());
+ ASSERT_EQ(Date_t(), defaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithEmptyCacheAndSetDefaults) {
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(1, 2));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ newDefaults.setUpdateOpTime(Timestamp(1, 2));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
_rwcd.refreshIfNecessary(_opCtx);
auto defaults = _rwcd.getDefault(_opCtx);
- ASSERT_EQ(Timestamp(1, 2), *defaults.getEpoch());
- ASSERT_EQ(1234, defaults.getSetTime()->toMillisSinceEpoch());
- ASSERT(defaults.getLocalSetTime());
+ ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
+ ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
}
TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithHigherEpoch) {
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(1, 2));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ newDefaults.setUpdateOpTime(Timestamp(1, 2));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto defaults = _rwcd.getDefault(_opCtx);
- ASSERT_EQ(Timestamp(1, 2), *defaults.getEpoch());
- ASSERT_EQ(1234, defaults.getSetTime()->toMillisSinceEpoch());
+ ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
RWConcernDefault newDefaults2;
- newDefaults2.setEpoch(Timestamp(3, 4));
- newDefaults2.setSetTime(Date_t::fromMillisSinceEpoch(5678));
+ newDefaults2.setUpdateOpTime(Timestamp(3, 4));
+ newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults2));
_rwcd.refreshIfNecessary(_opCtx);
auto defaults2 = _rwcd.getDefault(_opCtx);
- ASSERT_EQ(Timestamp(3, 4), *defaults2.getEpoch());
- ASSERT_EQ(5678, defaults2.getSetTime()->toMillisSinceEpoch());
+ ASSERT_EQ(Timestamp(3, 4), *defaults2.getUpdateOpTime());
+ ASSERT_EQ(5678, defaults2.getUpdateWallClockTime()->toMillisSinceEpoch());
}
TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithLowerEpoch) {
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(10, 20));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ newDefaults.setUpdateOpTime(Timestamp(10, 20));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto defaults = _rwcd.getDefault(_opCtx);
- ASSERT(defaults.getEpoch());
- ASSERT(defaults.getSetTime());
+ ASSERT(defaults.getUpdateOpTime());
+ ASSERT(defaults.getUpdateWallClockTime());
RWConcernDefault newDefaults2;
- newDefaults2.setEpoch(Timestamp(5, 6));
- newDefaults2.setSetTime(Date_t::fromMillisSinceEpoch(5678));
+ newDefaults2.setUpdateOpTime(Timestamp(5, 6));
+ newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults2));
_rwcd.refreshIfNecessary(_opCtx);
auto defaults2 = _rwcd.getDefault(_opCtx);
- ASSERT_EQ(Timestamp(10, 20), *defaults2.getEpoch());
- ASSERT_EQ(1234, defaults2.getSetTime()->toMillisSinceEpoch());
+ ASSERT_EQ(Timestamp(10, 20), *defaults2.getUpdateOpTime());
+ ASSERT_EQ(1234, defaults2.getUpdateWallClockTime()->toMillisSinceEpoch());
}
/**
@@ -271,9 +271,8 @@ protected:
ASSERT(defaults.getDefaultReadConcern()->getLevel() ==
repl::ReadConcernLevel::kLocalReadConcern);
ASSERT_EQ(4, defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT(defaults.getEpoch());
- ASSERT(defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT(defaults.getUpdateOpTime());
+ ASSERT(defaults.getUpdateWallClockTime());
_lookupMock.setLookupCallReturnValue(std::move(defaults));
auto oldDefaults = _rwcd.getDefault(operationContext());
@@ -361,14 +360,13 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
ASSERT(defaults.getDefaultReadConcern()->getLevel() ==
repl::ReadConcernLevel::kMajorityReadConcern);
ASSERT_EQ(5, defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT_LT(*oldDefaults.getEpoch(), *defaults.getEpoch());
- ASSERT_LT(*oldDefaults.getSetTime(), *defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
+ ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
_lookupMock.setLookupCallReturnValue(std::move(defaults));
_rwcd.refreshIfNecessary(operationContext());
auto newDefaults = _rwcd.getDefault(operationContext());
- ASSERT_LT(*oldDefaults.getLocalSetTime(), *newDefaults.getLocalSetTime());
+ ASSERT_LT(oldDefaults.localUpdateWallClockTime(), newDefaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
@@ -382,14 +380,13 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
repl::ReadConcernLevel::kMajorityReadConcern);
ASSERT_EQ(oldDefaults.getDefaultWriteConcern()->wNumNodes,
defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT_LT(*oldDefaults.getEpoch(), *defaults.getEpoch());
- ASSERT_LT(*oldDefaults.getSetTime(), *defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
+ ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
_lookupMock.setLookupCallReturnValue(std::move(defaults));
_rwcd.refreshIfNecessary(operationContext());
auto newDefaults = _rwcd.getDefault(operationContext());
- ASSERT_LT(*oldDefaults.getLocalSetTime(), *newDefaults.getLocalSetTime());
+ ASSERT_LT(oldDefaults.localUpdateWallClockTime(), newDefaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
@@ -402,14 +399,13 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
ASSERT(oldDefaults.getDefaultReadConcern()->getLevel() ==
defaults.getDefaultReadConcern()->getLevel());
ASSERT_EQ(5, defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT_LT(*oldDefaults.getEpoch(), *defaults.getEpoch());
- ASSERT_LT(*oldDefaults.getSetTime(), *defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
+ ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
_lookupMock.setLookupCallReturnValue(std::move(defaults));
_rwcd.refreshIfNecessary(operationContext());
auto newDefaults = _rwcd.getDefault(operationContext());
- ASSERT_LT(*oldDefaults.getLocalSetTime(), *newDefaults.getLocalSetTime());
+ ASSERT_LT(oldDefaults.localUpdateWallClockTime(), newDefaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
@@ -419,14 +415,13 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
operationContext(), repl::ReadConcernArgs(), WriteConcernOptions());
ASSERT(!defaults.getDefaultReadConcern());
ASSERT(!defaults.getDefaultWriteConcern());
- ASSERT_LT(*oldDefaults.getEpoch(), *defaults.getEpoch());
- ASSERT_LT(*oldDefaults.getSetTime(), *defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
+ ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
_lookupMock.setLookupCallReturnValue(std::move(defaults));
_rwcd.refreshIfNecessary(operationContext());
auto newDefaults = _rwcd.getDefault(operationContext());
- ASSERT_LT(*oldDefaults.getLocalSetTime(), *newDefaults.getLocalSetTime());
+ ASSERT_LT(oldDefaults.localUpdateWallClockTime(), newDefaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
@@ -441,14 +436,13 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
ASSERT_EQ(1, defaults.getDefaultWriteConcern()->wNumNodes);
ASSERT_EQ(0, defaults.getDefaultWriteConcern()->wTimeout);
ASSERT(WriteConcernOptions::SyncMode::JOURNAL == defaults.getDefaultWriteConcern()->syncMode);
- ASSERT_LT(*oldDefaults.getEpoch(), *defaults.getEpoch());
- ASSERT_LT(*oldDefaults.getSetTime(), *defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
+ ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
_lookupMock.setLookupCallReturnValue(std::move(defaults));
_rwcd.refreshIfNecessary(operationContext());
auto newDefaults = _rwcd.getDefault(operationContext());
- ASSERT_LT(*oldDefaults.getLocalSetTime(), *newDefaults.getLocalSetTime());
+ ASSERT_LT(oldDefaults.localUpdateWallClockTime(), newDefaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
@@ -463,25 +457,24 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
ASSERT_EQ(1, defaults.getDefaultWriteConcern()->wNumNodes);
ASSERT_EQ(12345, defaults.getDefaultWriteConcern()->wTimeout);
ASSERT(WriteConcernOptions::SyncMode::UNSET == defaults.getDefaultWriteConcern()->syncMode);
- ASSERT_LT(*oldDefaults.getEpoch(), *defaults.getEpoch());
- ASSERT_LT(*oldDefaults.getSetTime(), *defaults.getSetTime());
- ASSERT(!defaults.getLocalSetTime());
+ ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
+ ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
_lookupMock.setLookupCallReturnValue(std::move(defaults));
_rwcd.refreshIfNecessary(operationContext());
auto newDefaults = _rwcd.getDefault(operationContext());
- ASSERT_LT(*oldDefaults.getLocalSetTime(), *newDefaults.getLocalSetTime());
+ ASSERT_LT(oldDefaults.localUpdateWallClockTime(), newDefaults.localUpdateWallClockTime());
}
TEST_F(ReadWriteConcernDefaultsTestWithClusterTime, TestRefreshDefaultsWithDeletedDefaults) {
RWConcernDefault origDefaults;
- origDefaults.setEpoch(Timestamp(10, 20));
- origDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ origDefaults.setUpdateOpTime(Timestamp(10, 20));
+ origDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(origDefaults));
auto origCachedDefaults = _rwcd.getDefault(operationContext());
- ASSERT_EQ(Timestamp(10, 20), *origCachedDefaults.getEpoch());
- ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *origCachedDefaults.getSetTime());
+ ASSERT_EQ(Timestamp(10, 20), *origCachedDefaults.getUpdateOpTime());
+ ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *origCachedDefaults.getUpdateWallClockTime());
getClock()->reserveTicks(1);
getMockClockSource()->advance(Milliseconds(1));
@@ -492,9 +485,10 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime, TestRefreshDefaultsWithDelet
// The cache should now contain default constructed defaults.
auto newCachedDefaults = _rwcd.getDefault(operationContext());
- ASSERT(!newCachedDefaults.getEpoch());
- ASSERT(!newCachedDefaults.getSetTime());
- ASSERT_LT(*origCachedDefaults.getLocalSetTime(), *newCachedDefaults.getLocalSetTime());
+ ASSERT(!newCachedDefaults.getUpdateOpTime());
+ ASSERT(!newCachedDefaults.getUpdateWallClockTime());
+ ASSERT_LT(origCachedDefaults.localUpdateWallClockTime(),
+ newCachedDefaults.localUpdateWallClockTime());
}
} // namespace
diff --git a/src/mongo/db/repl/rs_rollback_test.cpp b/src/mongo/db/repl/rs_rollback_test.cpp
index ac288a13df4..b9a78ef8ed3 100644
--- a/src/mongo/db/repl/rs_rollback_test.cpp
+++ b/src/mongo/db/repl/rs_rollback_test.cpp
@@ -63,9 +63,9 @@
#include "mongo/unittest/unittest.h"
#include "mongo/util/net/hostandport.h"
+namespace mongo {
namespace {
-using namespace mongo;
using namespace mongo::repl;
using namespace mongo::repl::rollback_internal;
@@ -2918,25 +2918,25 @@ TEST_F(RSRollbackTest, RollbackInvalidatesDefaultRWConcernCache) {
// Put initial defaults in the cache.
{
RWConcernDefault origDefaults;
- origDefaults.setEpoch(Timestamp(10, 20));
- origDefaults.setSetTime(Date_t::fromMillisSinceEpoch(1234));
+ origDefaults.setUpdateOpTime(Timestamp(10, 20));
+ origDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
_lookupMock.setLookupCallReturnValue(std::move(origDefaults));
}
auto origCachedDefaults = rwcDefaults.getDefault(_opCtx.get());
- ASSERT_EQ(Timestamp(10, 20), *origCachedDefaults.getEpoch());
- ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *origCachedDefaults.getSetTime());
+ ASSERT_EQ(Timestamp(10, 20), *origCachedDefaults.getUpdateOpTime());
+ ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *origCachedDefaults.getUpdateWallClockTime());
// Change the mock's defaults, but don't invalidate the cache yet. The cache should still return
// the original defaults.
{
RWConcernDefault newDefaults;
- newDefaults.setEpoch(Timestamp(50, 20));
- newDefaults.setSetTime(Date_t::fromMillisSinceEpoch(5678));
+ newDefaults.setUpdateOpTime(Timestamp(50, 20));
+ newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
_lookupMock.setLookupCallReturnValue(std::move(newDefaults));
auto cachedDefaults = rwcDefaults.getDefault(_opCtx.get());
- ASSERT_EQ(Timestamp(10, 20), *cachedDefaults.getEpoch());
- ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *cachedDefaults.getSetTime());
+ ASSERT_EQ(Timestamp(10, 20), *cachedDefaults.getUpdateOpTime());
+ ASSERT_EQ(Date_t::fromMillisSinceEpoch(1234), *cachedDefaults.getUpdateWallClockTime());
}
// Rollback via refetch should invalidate the cache and getting the defaults should now return
@@ -2949,8 +2949,9 @@ TEST_F(RSRollbackTest, RollbackInvalidatesDefaultRWConcernCache) {
_testRollbackDelete(_opCtx.get(), _coordinator, _replicationProcess.get(), coll->uuid(), doc);
auto newCachedDefaults = rwcDefaults.getDefault(_opCtx.get());
- ASSERT_EQ(Timestamp(50, 20), *newCachedDefaults.getEpoch());
- ASSERT_EQ(Date_t::fromMillisSinceEpoch(5678), *newCachedDefaults.getSetTime());
+ ASSERT_EQ(Timestamp(50, 20), *newCachedDefaults.getUpdateOpTime());
+ ASSERT_EQ(Date_t::fromMillisSinceEpoch(5678), *newCachedDefaults.getUpdateWallClockTime());
}
} // namespace
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp b/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp
index 3587c6cda59..44ff531a3a4 100644
--- a/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp
+++ b/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp
@@ -36,7 +36,6 @@
#include "mongo/db/commands/rwc_defaults_commands_gen.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/read_write_concern_defaults.h"
-#include "mongo/db/rw_concern_default_gen.h"
#include "mongo/s/cluster_commands_helpers.h"
#include "mongo/s/grid.h"
#include "mongo/util/log.h"
@@ -72,7 +71,7 @@ public:
// Quickly pick up the new defaults by setting them in the cache.
auto newDefaults = RWConcernDefault::parse(
IDLParserErrorContext("ClusterSetDefaultRWConcern"), cmdResponse.response);
- ReadWriteConcernDefaults::get(opCtx).setDefault(std::move(newDefaults));
+ ReadWriteConcernDefaults::get(opCtx).setDefault(opCtx, std::move(newDefaults));
CommandHelpers::filterCommandReplyForPassthrough(cmdResponse.response, &result);
return true;
@@ -113,20 +112,23 @@ class ClusterGetDefaultRWConcernCommand final
: public TypedCommand<ClusterGetDefaultRWConcernCommand> {
public:
using Request = GetDefaultRWConcern;
- using Response = RWConcernDefault;
class Invocation final : public InvocationBase {
public:
using InvocationBase::InvocationBase;
- Response typedRun(OperationContext* opCtx) {
- if (request().getInMemory() && *request().getInMemory()) {
- auto rwc =
- ReadWriteConcernDefaults::get(opCtx->getServiceContext()).getDefault(opCtx);
- rwc.setInMemory(true);
- return rwc;
+ GetDefaultRWConcernResponse typedRun(OperationContext* opCtx) {
+ auto& rwcDefaults = ReadWriteConcernDefaults::get(opCtx->getServiceContext());
+ if (request().getInMemory().value_or(false)) {
+ const auto rwcDefault = rwcDefaults.getDefault(opCtx);
+ GetDefaultRWConcernResponse response;
+ response.setRWConcernDefault(rwcDefault);
+ response.setLocalUpdateWallClockTime(rwcDefault.localUpdateWallClockTime());
+ response.setInMemory(true);
+ return response;
}
+ // If not asking for the in-memory defaults, fetch them from the config server
GetDefaultRWConcern configsvrRequest;
configsvrRequest.setDbName(request().getDbName());
@@ -140,8 +142,8 @@ public:
uassertStatusOK(cmdResponse.commandStatus);
- return Response::parse(IDLParserErrorContext("ClusterGetDefaultRWConcernResponse"),
- cmdResponse.response);
+ return GetDefaultRWConcernResponse::parse(
+ IDLParserErrorContext("ClusterGetDefaultRWConcernResponse"), cmdResponse.response);
}
private:
diff --git a/src/mongo/s/commands/s_read_write_concern_defaults_server_status.cpp b/src/mongo/s/commands/s_read_write_concern_defaults_server_status.cpp
index c7d9382bb43..4a012777bdc 100644
--- a/src/mongo/s/commands/s_read_write_concern_defaults_server_status.cpp
+++ b/src/mongo/s/commands/s_read_write_concern_defaults_server_status.cpp
@@ -29,6 +29,7 @@
#include "mongo/platform/basic.h"
+#include "mongo/db/commands/rwc_defaults_commands_gen.h"
#include "mongo/db/commands/server_status.h"
#include "mongo/db/read_write_concern_defaults.h"
@@ -45,7 +46,11 @@ public:
BSONObj generateSection(OperationContext* opCtx,
const BSONElement& configElement) const override {
- return ReadWriteConcernDefaults::get(opCtx).getDefault(opCtx).toBSON();
+ auto rwcDefault = ReadWriteConcernDefaults::get(opCtx).getDefault(opCtx);
+ GetDefaultRWConcernResponse response;
+ response.setRWConcernDefault(rwcDefault);
+ response.setLocalUpdateWallClockTime(rwcDefault.localUpdateWallClockTime());
+ return response.toBSON();
}
} defaultRWConcernServerStatus;
diff --git a/src/mongo/util/read_through_cache.h b/src/mongo/util/read_through_cache.h
index 83790bd9605..f13cd486e13 100644
--- a/src/mongo/util/read_through_cache.h
+++ b/src/mongo/util/read_through_cache.h
@@ -32,14 +32,13 @@
#include <boost/optional.hpp>
#include "mongo/bson/oid.h"
+#include "mongo/db/operation_context.h"
#include "mongo/platform/mutex.h"
#include "mongo/stdx/condition_variable.h"
#include "mongo/util/invalidating_lru_cache.h"
namespace mongo {
-class OperationContext;
-
/**
* Serves as a container of the non-templatised parts of the ReadThroughCache class below.
*/
@@ -214,12 +213,82 @@ protected:
*/
template <typename Key, typename Value>
class ReadThroughCache : public ReadThroughCacheBase {
+ /**
+ * Data structure wrapping and expanding on the values stored in the cache.
+ */
+ struct StoredValue {
+ Value value;
+
+ // Contains the wallclock time of when the value was fetched from the backing storage. This
+ // value is not precise and should only be used for diagnostics purposes (i.e., it cannot be
+ // relied on to perform any recency comparisons for example).
+ Date_t updateWallClockTime;
+ };
+ using Cache = InvalidatingLRUCache<Key, StoredValue>;
+
public:
- using Cache = InvalidatingLRUCache<Key, Value>;
- using ValueHandle = typename Cache::ValueHandle;
using LookupFn = std::function<boost::optional<Value>(OperationContext*, const Key&)>;
/**
+ * Common type for values returned from the cache.
+ */
+ class ValueHandle {
+ public:
+ // The two constructors below are present in order to offset the fact that the cache doesn't
+ // support pinning items. Their only usage must be in the authorization mananager for the
+ // internal authentication user.
+ ValueHandle(Value&& value) : _valueHandle({std::move(value), Date_t::min()}) {}
+ ValueHandle() = default;
+
+ operator bool() const {
+ return bool(_valueHandle);
+ }
+
+ bool isValid() const {
+ return _valueHandle.isValid();
+ }
+
+ Value* get() {
+ return &_valueHandle->value;
+ }
+
+ const Value* get() const {
+ return &_valueHandle->value;
+ }
+
+ Value& operator*() {
+ return *get();
+ }
+
+ const Value& operator*() const {
+ return *get();
+ }
+
+ Value* operator->() {
+ return get();
+ }
+
+ const Value* operator->() const {
+ return get();
+ }
+
+ /**
+ * See the comments for `StoredValue::updateWallClockTime` above.
+ */
+ Date_t updateWallClockTime() const {
+ return _valueHandle->updateWallClockTime;
+ }
+
+ private:
+ friend class ReadThroughCache;
+
+ ValueHandle(typename Cache::ValueHandle&& valueHandle)
+ : _valueHandle(std::move(valueHandle)) {}
+
+ typename Cache::ValueHandle _valueHandle;
+ };
+
+ /**
* If 'key' is found in the cache, returns a ValidHandle, otherwise invokes the blocking
* 'lookup' method below to fetch the 'key' from the backing store. If the key is not found in
* the backing store, returns a ValueHandle which defaults to not-set (it's bool operator is
@@ -233,7 +302,7 @@ public:
while (true) {
auto cachedValue = _cache.get(key);
if (cachedValue)
- return cachedValue;
+ return ValueHandle(std::move(cachedValue));
// Otherwise make sure we have the locks we need and check whether and wait on another
// thread is fetching into the cache
@@ -244,7 +313,7 @@ public:
}
if (cachedValue)
- return cachedValue;
+ return ValueHandle(std::move(cachedValue));
// If there's still no value in the cache, then we need to go and get it. Take the slow
// path.
@@ -252,14 +321,16 @@ public:
auto value = lookup(opCtx, key);
if (!value)
- return cachedValue;
+ return ValueHandle();
// All this does is re-acquire the _cacheWriteMutex if we don't hold it already - a
// caller may also call endFetchPhase() after this returns.
guard.endFetchPhase();
if (guard.isSameCacheGeneration())
- return _cache.insertOrAssignAndGet(key, std::move(*value));
+ return ValueHandle(_cache.insertOrAssignAndGet(
+ key,
+ {std::move(*value), opCtx->getServiceContext()->getFastClockSource()->now()}));
// If the cache generation changed while this thread was in fetch mode, the data
// associated with the value may now be invalid, so we will throw out the fetched value
@@ -270,10 +341,10 @@ public:
/**
* Invalidates the given 'key' and immediately replaces it with a new value.
*/
- ValueHandle insertOrAssignAndGet(const Key& key, Value&& newValue) {
+ ValueHandle insertOrAssignAndGet(const Key& key, Value&& newValue, Date_t updateWallClockTime) {
CacheGuard guard(this);
_updateCacheGeneration(guard);
- return _cache.insertOrAssignAndGet(key, std::move(newValue));
+ return _cache.insertOrAssignAndGet(key, {std::move(newValue), updateWallClockTime});
}
/**
@@ -290,8 +361,9 @@ public:
void invalidateIf(const Pred& predicate) {
CacheGuard guard(this);
_updateCacheGeneration(guard);
- _cache.invalidateIf(
- [&](const Key& key, const Value* value) { return predicate(key, value); });
+ _cache.invalidateIf([&](const Key& key, const StoredValue* storedValue) {
+ return predicate(key, &storedValue->value);
+ });
}
void invalidateAll() {