void AutoGetCollectionForRead::_ensureMajorityCommittedSnapshotIsValid(const NamespaceString& nss) { while (true) { auto coll = _autoColl->getCollection(); if (!coll) { return; } auto minSnapshot = coll->getMinimumVisibleSnapshot(); if (!minSnapshot) { return; } auto mySnapshot = _txn->recoveryUnit()->getMajorityCommittedSnapshot(); if (!mySnapshot) { return; } if (mySnapshot >= minSnapshot) { return; } // Yield locks. _autoColl = boost::none; repl::ReplicationCoordinator::get(_txn)->waitUntilSnapshotCommitted(_txn, *minSnapshot); uassertStatusOK(_txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot()); { stdx::lock_guard<Client> lk(*_txn->getClient()); CurOp::get(_txn)->yielded(); } // Relock. _autoColl.emplace(_txn, nss, MODE_IS); } }
MinVisibleTimestampMap closeCatalog(OperationContext* opCtx) { invariant(opCtx->lockState()->isW()); MinVisibleTimestampMap minVisibleTimestampMap; std::vector<std::string> allDbs; opCtx->getServiceContext()->getStorageEngine()->listDatabases(&allDbs); auto databaseHolder = DatabaseHolder::get(opCtx); for (auto&& dbName : allDbs) { const auto db = databaseHolder->getDb(opCtx, dbName); for (auto collIt = db->begin(opCtx); collIt != db->end(opCtx); ++collIt) { auto coll = *collIt; if (!coll) { break; } OptionalCollectionUUID uuid = coll->uuid(); boost::optional<Timestamp> minVisible = coll->getMinimumVisibleSnapshot(); // If there's a minimum visible, invariant there's also a UUID. invariant(!minVisible || uuid); if (uuid && minVisible) { LOG(1) << "closeCatalog: preserving min visible timestamp. Collection: " << coll->ns() << " UUID: " << uuid << " TS: " << minVisible; minVisibleTimestampMap[*uuid] = *minVisible; } } } // Need to mark the UUIDCatalog as open if we our closeAll fails, dismissed if successful. auto reopenOnFailure = makeGuard([opCtx] { UUIDCatalog::get(opCtx).onOpenCatalog(opCtx); }); // Closing UUID Catalog: only lookupNSSByUUID will fall back to using pre-closing state to // allow authorization for currently unknown UUIDs. This is needed because authorization needs // to work before acquiring locks, and might otherwise spuriously regard a UUID as unknown // while reloading the catalog. UUIDCatalog::get(opCtx).onCloseCatalog(opCtx); LOG(1) << "closeCatalog: closing UUID catalog"; // Close all databases. log() << "closeCatalog: closing all databases"; databaseHolder->closeAll(opCtx); // Close the storage engine's catalog. log() << "closeCatalog: closing storage engine catalog"; opCtx->getServiceContext()->getStorageEngine()->closeCatalog(opCtx); reopenOnFailure.dismiss(); return minVisibleTimestampMap; }