MultiVersionDatabase
| 1659 | |
| 1660 | // MultiVersionDatabase |
| 1661 | MultiVersionDatabase::MultiVersionDatabase(MultiVersionApi* api, |
| 1662 | int threadIdx, |
| 1663 | ClusterConnectionRecord const& connectionRecord, |
| 1664 | Reference<IDatabase> db, |
| 1665 | Reference<IDatabase> versionMonitorDb, |
| 1666 | bool openConnectors) |
| 1667 | : dbState(new DatabaseState(connectionRecord, versionMonitorDb)) { |
| 1668 | dbState->db = db; |
| 1669 | dbState->dbVar->set(db); |
| 1670 | if (openConnectors) { |
| 1671 | if (!api->localClientDisabled) { |
| 1672 | dbState->addClient(api->getLocalClient()); |
| 1673 | } |
| 1674 | |
| 1675 | api->runOnExternalClients(threadIdx, [this](Reference<ClientInfo> client) { dbState->addClient(client); }); |
| 1676 | |
| 1677 | api->runOnExternalClientsAllThreads([&connectionRecord](Reference<ClientInfo> client) { |
| 1678 | // This creates a database to initialize some client state on the external library. |
| 1679 | // We only do this on 6.2+ clients to avoid some bugs associated with older versions. |
| 1680 | // This deletes the new database immediately to discard its connections. |
| 1681 | // |
| 1682 | // Simultaneous attempts to create a database could result in us running this initialization |
| 1683 | // code in multiple threads simultaneously. It is necessary that each attempt have a chance |
| 1684 | // to run this initialization in case the other fails, and it's safe to run them in parallel. |
| 1685 | if (client->protocolVersion.hasCloseUnusedConnection() && !client->initialized) { |
| 1686 | try { |
| 1687 | Reference<IDatabase> newDb = connectionRecord.createDatabase(client->api); |
| 1688 | client->initialized = true; |
| 1689 | } catch (Error& e) { |
| 1690 | // This connection is not initialized. It is still possible to connect with it, |
| 1691 | // but we may not see trace logs from this client until a successful connection |
| 1692 | // is established. |
| 1693 | TraceEvent(SevWarnAlways, "FailedToInitializeExternalClient") |
| 1694 | .error(e) |
| 1695 | .detail("LibraryPath", client->libPath) |
| 1696 | .detail("ConnectionRecord", connectionRecord); |
| 1697 | } |
| 1698 | } |
| 1699 | }); |
| 1700 | |
| 1701 | // For clients older than 6.2 we create and maintain our database connection |
| 1702 | api->runOnExternalClients(threadIdx, [this, &connectionRecord](Reference<ClientInfo> client) { |
| 1703 | if (!client->protocolVersion.hasCloseUnusedConnection()) { |
| 1704 | try { |
| 1705 | dbState->legacyDatabaseConnections[client->protocolVersion] = |
| 1706 | connectionRecord.createDatabase(client->api); |
| 1707 | } catch (Error& e) { |
| 1708 | // This connection is discarded |
| 1709 | TraceEvent(SevWarnAlways, "FailedToCreateLegacyDatabaseConnection") |
| 1710 | .error(e) |
| 1711 | .detail("LibraryPath", client->libPath) |
| 1712 | .detail("ConnectionRecord", connectionRecord); |
| 1713 | } |
| 1714 | } |
| 1715 | }); |
| 1716 | |
| 1717 | Reference<DatabaseState> dbStateRef = dbState; |
| 1718 | onMainThreadVoid([dbStateRef]() { dbStateRef->protocolVersionMonitor = dbStateRef->monitorProtocolVersion(); }); |
nothing calls this directly
no test coverage detected