Called when a change to the protocol version of the cluster has been detected. Must be called from the main thread
| 1918 | // Called when a change to the protocol version of the cluster has been detected. |
| 1919 | // Must be called from the main thread |
| 1920 | void MultiVersionDatabase::DatabaseState::protocolVersionChanged(ProtocolVersion protocolVersion) { |
| 1921 | if (closed) { |
| 1922 | return; |
| 1923 | } |
| 1924 | |
| 1925 | // If the protocol version changed but is still compatible, update our local version but keep the same connection |
| 1926 | if (dbProtocolVersion.present() && |
| 1927 | protocolVersion.normalizedVersion() == dbProtocolVersion.get().normalizedVersion()) { |
| 1928 | dbProtocolVersion = protocolVersion; |
| 1929 | |
| 1930 | ASSERT(protocolVersionMonitor.isValid()); |
| 1931 | protocolVersionMonitor.cancel(); |
| 1932 | protocolVersionMonitor = monitorProtocolVersion(); |
| 1933 | } |
| 1934 | |
| 1935 | // The protocol version has changed to a different, incompatible version |
| 1936 | else { |
| 1937 | TraceEvent("ProtocolVersionChanged") |
| 1938 | .detail("NewProtocolVersion", protocolVersion) |
| 1939 | .detail("OldProtocolVersion", dbProtocolVersion); |
| 1940 | // When the protocol version changes, clear the corresponding entry in the shared state map |
| 1941 | // so it can be re-initialized. Only do so if there was a valid previous protocol version. |
| 1942 | if (dbProtocolVersion.present() && MultiVersionApi::api->getApiVersion().hasClusterSharedStateMap()) { |
| 1943 | MultiVersionApi::api->clearClusterSharedStateMapEntry(clusterId, dbProtocolVersion.get()); |
| 1944 | } |
| 1945 | |
| 1946 | dbProtocolVersion = protocolVersion; |
| 1947 | |
| 1948 | auto itr = clients.find(protocolVersion.normalizedVersion()); |
| 1949 | if (itr != clients.end()) { |
| 1950 | auto& client = itr->second; |
| 1951 | TraceEvent("CreatingDatabaseOnClient") |
| 1952 | .detail("LibraryPath", client->libPath) |
| 1953 | .detail("Failed", client->failed) |
| 1954 | .detail("External", client->external); |
| 1955 | |
| 1956 | Reference<IDatabase> newDb; |
| 1957 | try { |
| 1958 | newDb = connectionRecord.createDatabase(client->api); |
| 1959 | } catch (Error& e) { |
| 1960 | TraceEvent(SevWarnAlways, "MultiVersionClientFailedToCreateDatabase") |
| 1961 | .error(e) |
| 1962 | .detail("LibraryPath", client->libPath) |
| 1963 | .detail("External", client->external) |
| 1964 | .detail("ConnectionRecord", connectionRecord); |
| 1965 | |
| 1966 | // Put the client in a disconnected state until the version changes again |
| 1967 | updateDatabase(Reference<IDatabase>(), Reference<ClientInfo>()); |
| 1968 | return; |
| 1969 | } |
| 1970 | |
| 1971 | if (client->external && !MultiVersionApi::api->getApiVersion().hasInlineUpdateDatabase()) { |
| 1972 | // Old API versions return a future when creating the database, so we need to wait for it |
| 1973 | Reference<DatabaseState> self = Reference<DatabaseState>::addRef(this); |
| 1974 | dbReady = mapThreadFuture<Void, Void>( |
| 1975 | newDb.castTo<DLDatabase>()->onReady(), [self, newDb, client](ErrorOr<Void> ready) { |
| 1976 | if (!ready.isError()) { |
| 1977 | onMainThreadVoid([self, newDb, client]() { self->updateDatabase(newDb, client); }); |
no test coverage detected