diff --git a/fdbclient/MultiVersionTransaction.actor.cpp b/fdbclient/MultiVersionTransaction.actor.cpp index bca3549651..552db4c3ac 100644 --- a/fdbclient/MultiVersionTransaction.actor.cpp +++ b/fdbclient/MultiVersionTransaction.actor.cpp @@ -892,15 +892,26 @@ MultiVersionDatabase::MultiVersionDatabase(MultiVersionApi* api, dbState->addClient(api->getLocalClient()); } + api->runOnExternalClients(threadIdx, [this](Reference client) { dbState->addClient(client); }); + if (!externalClientsInitialized.test_and_set()) { api->runOnExternalClientsAllThreads([&clusterFilePath](Reference client) { - // This creates a database to initialize some client state on the external library, - // but it gets deleted immediately so that we don't keep open connections - Reference newDb = client->api->createDatabase(clusterFilePath.c_str()); + // This creates a database to initialize some client state on the external library + // We only do this on 6.2+ clients to avoid some bugs associated with older versions + // This deletes the new database immediately to discard its connections + if (client->protocolVersion.hasCloseUnusedConnection()) { + Reference newDb = client->api->createDatabase(clusterFilePath.c_str()); + } }); } - api->runOnExternalClients(threadIdx, [this](Reference client) { dbState->addClient(client); }); + // For clients older than 6.2 we create and maintain our database connection + api->runOnExternalClients(threadIdx, [this, &clusterFilePath](Reference client) { + if (!client->protocolVersion.hasCloseUnusedConnection()) { + dbState->legacyDatabaseConnections[client->protocolVersion] = + client->api->createDatabase(clusterFilePath.c_str()); + } + }); onMainThreadVoid([this]() { dbState->protocolVersionMonitor = dbState->monitorProtocolVersion(); }, nullptr); } @@ -1158,7 +1169,10 @@ void MultiVersionDatabase::LegacyVersionMonitor::startConnectionMonitor( if (!monitorRunning) { monitorRunning = true; - db = client->api->createDatabase(dbState->clusterFilePath.c_str()); + auto itr = dbState->legacyDatabaseConnections.find(client->protocolVersion); + ASSERT(itr != dbState->legacyDatabaseConnections.end()); + + db = itr->second; tr = Reference(); TraceEvent("StartingLegacyVersionMonitor").detail("ProtocolVersion", client->protocolVersion); diff --git a/fdbclient/MultiVersionTransaction.h b/fdbclient/MultiVersionTransaction.h index 388db1bd3b..2244ec2c6e 100644 --- a/fdbclient/MultiVersionTransaction.h +++ b/fdbclient/MultiVersionTransaction.h @@ -510,7 +510,16 @@ public: ThreadFuture dbReady; ThreadFuture protocolVersionMonitor; + + // Versions older than 6.1 do not benefit from having their database connections closed. Additionally, + // there are various issues that result in negative behavior in some cases if the connections are closed. + // Therefore, we leave them open. + std::map> legacyDatabaseConnections; + + // Versions 5.0 and older do not support connection packet monitoring and require alternate techniques to + // determine the cluster version. std::list legacyVersionMonitors; + Optional dbProtocolVersion; // This maps a normalized protocol version to the client associated with it. This prevents compatible diff --git a/flow/ProtocolVersion.h b/flow/ProtocolVersion.h index 07a2675f1b..d3c601a9b5 100644 --- a/flow/ProtocolVersion.h +++ b/flow/ProtocolVersion.h @@ -118,6 +118,7 @@ public: // introduced features PROTOCOL_VERSION_FEATURE(0x0FDB00B062010001LL, BackupMutations); PROTOCOL_VERSION_FEATURE(0x0FDB00B062010001LL, ClusterControllerPriorityInfo); PROTOCOL_VERSION_FEATURE(0x0FDB00B062010001LL, ProcessIDFile); + PROTOCOL_VERSION_FEATURE(0x0FDB00B062010001LL, CloseUnusedConnection); PROTOCOL_VERSION_FEATURE(0x0FDB00B063010000LL, DBCoreState); PROTOCOL_VERSION_FEATURE(0x0FDB00B063010000LL, TagThrottleValue); PROTOCOL_VERSION_FEATURE(0x0FDB00B063010000LL, ServerListValue);