diff --git a/fdbclient/DatabaseContext.h b/fdbclient/DatabaseContext.h index 16f32c5aa5..56d4275701 100644 --- a/fdbclient/DatabaseContext.h +++ b/fdbclient/DatabaseContext.h @@ -54,11 +54,17 @@ public: // For internal (fdbserver) use only static Database create( Reference>> clusterInterface, Reference connFile, LocalityData const& clientLocality ); - static Database create( Reference> clientInfo, Future clientInfoMonitor, LocalityData clientLocality, bool enableLocalityLoadBalance, int taskID=TaskDefaultEndpoint, bool lockAware=false, int apiVersion=Database::API_VERSION_LATEST ); + static Database create(Reference> clientInfo, Future clientInfoMonitor, + LocalityData clientLocality, bool enableLocalityLoadBalance, + int taskID = TaskDefaultEndpoint, bool lockAware = false, + int apiVersion = Database::API_VERSION_LATEST, bool switchable = false); ~DatabaseContext(); - Database clone() const { return Database(new DatabaseContext( cluster, clientInfo, clientInfoMonitor, dbId, taskID, clientLocality, enableLocalityLoadBalance, lockAware, apiVersion )); } + Database clone() const { + return Database(new DatabaseContext(cluster, clientInfo, clientInfoMonitor, dbId, taskID, clientLocality, + enableLocalityLoadBalance, lockAware, apiVersion, switchable)); + } std::pair> getCachedLocation( const KeyRef&, bool isBackward = false ); bool getCachedLocations( const KeyRangeRef&, vector>>&, int limit, bool reverse ); @@ -104,11 +110,13 @@ public: // new cluster. Future switchConnectionFile(Reference standby); Future recreateWatches(); + bool switchable = false; // private: - explicit DatabaseContext( Reference cluster, Reference> clientDBInfo, - Future clientInfoMonitor, Standalone dbId, int taskID, LocalityData const& clientLocality, - bool enableLocalityLoadBalance, bool lockAware, int apiVersion = Database::API_VERSION_LATEST ); + explicit DatabaseContext(Reference cluster, Reference> clientDBInfo, + Future clientInfoMonitor, Standalone dbId, int taskID, + LocalityData const& clientLocality, bool enableLocalityLoadBalance, bool lockAware, + int apiVersion = Database::API_VERSION_LATEST, bool switchable = false); explicit DatabaseContext( const Error &err ); diff --git a/fdbclient/NativeAPI.actor.cpp b/fdbclient/NativeAPI.actor.cpp index 2c9da7abbe..24ce7ea746 100644 --- a/fdbclient/NativeAPI.actor.cpp +++ b/fdbclient/NativeAPI.actor.cpp @@ -174,13 +174,13 @@ std::string unprintable( std::string const& val ) { } void DatabaseContext::validateVersion(Version version) { - // Version could be 0 if the INITIALIZE_NEW_DATABASE option is set. In that case, it is illegal to perform any reads. - // We throw client_invalid_operation because the caller didn't directly set the version, so the version_invalid error - // might be confusing. - if(version == 0) { + // Version could be 0 if the INITIALIZE_NEW_DATABASE option is set. In that case, it is illegal to perform any + // reads. We throw client_invalid_operation because the caller didn't directly set the version, so the + // version_invalid error might be confusing. + if (version == 0) { throw client_invalid_operation(); } - if (version < minAcceptableReadVersion) { + if (switchable && version < minAcceptableReadVersion) { TEST(true); // Attempted to read a version lower than any this client has seen from the current cluster throw transaction_too_old(); } @@ -511,17 +511,20 @@ Future DatabaseContext::getHealthMetrics(bool detailed = false) { return getHealthMetricsActor(this, detailed); } -DatabaseContext::DatabaseContext( - Reference cluster, Reference> clientInfo, Future clientInfoMonitor, Standalone dbId, - int taskID, LocalityData const& clientLocality, bool enableLocalityLoadBalance, bool lockAware, int apiVersion ) - : cluster(cluster), clientInfo(clientInfo), clientInfoMonitor(clientInfoMonitor), dbId(dbId), taskID(taskID), clientLocality(clientLocality), enableLocalityLoadBalance(enableLocalityLoadBalance), - lockAware(lockAware), apiVersion(apiVersion), provisional(false), - transactionReadVersions(0), transactionLogicalReads(0), transactionPhysicalReads(0), transactionCommittedMutations(0), transactionCommittedMutationBytes(0), - transactionsCommitStarted(0), transactionsCommitCompleted(0), transactionsTooOld(0), transactionsFutureVersions(0), transactionsNotCommitted(0), - transactionsMaybeCommitted(0), transactionsResourceConstrained(0), transactionsProcessBehind(0), outstandingWatches(0), transactionTimeout(0.0), transactionMaxRetries(-1), - latencies(1000), readLatencies(1000), commitLatencies(1000), GRVLatencies(1000), mutationsPerCommit(1000), bytesPerCommit(1000), mvCacheInsertLocation(0), - healthMetricsLastUpdated(0), detailedHealthMetricsLastUpdated(0) -{ +DatabaseContext::DatabaseContext(Reference cluster, Reference> clientInfo, + Future clientInfoMonitor, Standalone dbId, int taskID, + LocalityData const& clientLocality, bool enableLocalityLoadBalance, bool lockAware, + int apiVersion, bool switchable) + : cluster(cluster), clientInfo(clientInfo), clientInfoMonitor(clientInfoMonitor), dbId(dbId), taskID(taskID), + clientLocality(clientLocality), enableLocalityLoadBalance(enableLocalityLoadBalance), lockAware(lockAware), + apiVersion(apiVersion), switchable(switchable), provisional(false), transactionReadVersions(0), + transactionLogicalReads(0), transactionPhysicalReads(0), transactionCommittedMutations(0), + transactionCommittedMutationBytes(0), transactionsCommitStarted(0), transactionsCommitCompleted(0), + transactionsTooOld(0), transactionsFutureVersions(0), transactionsNotCommitted(0), transactionsMaybeCommitted(0), + transactionsResourceConstrained(0), transactionsProcessBehind(0), outstandingWatches(0), transactionTimeout(0.0), + transactionMaxRetries(-1), latencies(1000), readLatencies(1000), commitLatencies(1000), GRVLatencies(1000), + mutationsPerCommit(1000), bytesPerCommit(1000), mvCacheInsertLocation(0), healthMetricsLastUpdated(0), + detailedHealthMetricsLastUpdated(0) { metadataVersionCache.resize(CLIENT_KNOBS->METADATA_VERSION_CACHE_SIZE); maxOutstandingWatches = CLIENT_KNOBS->DEFAULT_MAX_OUTSTANDING_WATCHES; @@ -605,8 +608,12 @@ Database DatabaseContext::create(Reference>> return Database(new DatabaseContext(cluster, clientInfo, clientInfoMonitor, LiteralStringRef(""), TaskDefaultEndpoint, clientLocality, true, false)); } -Database DatabaseContext::create(Reference> clientInfo, Future clientInfoMonitor, LocalityData clientLocality, bool enableLocalityLoadBalance, int taskID, bool lockAware, int apiVersion) { - return Database( new DatabaseContext( Reference(nullptr), clientInfo, clientInfoMonitor, LiteralStringRef(""), taskID, clientLocality, enableLocalityLoadBalance, lockAware, apiVersion ) ); +Database DatabaseContext::create(Reference> clientInfo, Future clientInfoMonitor, + LocalityData clientLocality, bool enableLocalityLoadBalance, int taskID, + bool lockAware, int apiVersion, bool switchable) { + return Database(new DatabaseContext(Reference(nullptr), clientInfo, clientInfoMonitor, + LiteralStringRef(""), taskID, clientLocality, enableLocalityLoadBalance, + lockAware, apiVersion, switchable)); } DatabaseContext::~DatabaseContext() { @@ -818,6 +825,7 @@ Reference DatabaseContext::getConnectionFile() { } Future DatabaseContext::switchConnectionFile(Reference standby) { + ASSERT(switchable); return switchConnectionFileImpl(standby, this); } @@ -834,10 +842,13 @@ Database Database::createDatabase( Reference connFile, in DatabaseContext *db; if(preallocatedDb) { - db = new (preallocatedDb) DatabaseContext(cluster, clientInfo, clientInfoMonitor, LiteralStringRef(""), TaskDefaultEndpoint, clientLocality, true, false, apiVersion); + db = new (preallocatedDb) + DatabaseContext(cluster, clientInfo, clientInfoMonitor, LiteralStringRef(""), TaskDefaultEndpoint, + clientLocality, true, false, apiVersion, /* switchable */ true); } else { - db = new DatabaseContext(cluster, clientInfo, clientInfoMonitor, LiteralStringRef(""), TaskDefaultEndpoint, clientLocality, true, false, apiVersion); + db = new DatabaseContext(cluster, clientInfo, clientInfoMonitor, LiteralStringRef(""), TaskDefaultEndpoint, + clientLocality, true, false, apiVersion, /* switchable */ true); } return Database(db); diff --git a/fdbserver/storageserver.actor.cpp b/fdbserver/storageserver.actor.cpp index 916b6ea883..1db32c43f5 100644 --- a/fdbserver/storageserver.actor.cpp +++ b/fdbserver/storageserver.actor.cpp @@ -1831,8 +1831,7 @@ ACTOR Future> tryGetRange( Database cx, Version versi if( *isTooOld ) throw transaction_too_old(); - cx->minAcceptableReadVersion = - std::min(cx->minAcceptableReadVersion, version); // Suppress minAcceptableReadVersion check + ASSERT(!cx->switchable); tr.setVersion( version ); limits.minRows = 0;