Status ViewCatalog::dropView(OperationContext* opCtx, const NamespaceString& viewName) { stdx::lock_guard<stdx::mutex> lk(_mutex); _requireValidCatalog_inlock(opCtx); // Save a copy of the view definition in case we need to roll back. auto viewPtr = _lookup_inlock(opCtx, viewName.ns()); if (!viewPtr) { return {ErrorCodes::NamespaceNotFound, str::stream() << "cannot drop missing view: " << viewName.ns()}; } ViewDefinition savedDefinition = *viewPtr; invariant(_valid.load()); _durable->remove(opCtx, viewName); _viewGraph.remove(savedDefinition.name()); _viewMap.erase(viewName.ns()); opCtx->recoveryUnit()->onRollback([this, viewName, savedDefinition]() { this->_viewGraphNeedsRefresh = true; this->_viewMap[viewName.ns()] = std::make_shared<ViewDefinition>(savedDefinition); }); // We may get invalidated, but we're exclusively locked, so the change must be ours. opCtx->recoveryUnit()->onCommit([this]() { this->_valid.store(true); }); return Status::OK(); }
void ViewCatalog::iterate(OperationContext* opCtx, ViewIteratorCallback callback) { stdx::lock_guard<stdx::mutex> lk(_mutex); _requireValidCatalog_inlock(opCtx); for (auto&& view : _viewMap) { callback(*view.second); } }
Status ViewCatalog::_createOrUpdateView_inlock(OperationContext* txn, const NamespaceString& viewName, const NamespaceString& viewOn, const BSONArray& pipeline) { _requireValidCatalog_inlock(txn); BSONObj viewDef = BSON("_id" << viewName.ns() << "viewOn" << viewOn.coll() << "pipeline" << pipeline); BSONObj ownedPipeline = pipeline.getOwned(); auto view = std::make_shared<ViewDefinition>( viewName.db(), viewName.coll(), viewOn.coll(), ownedPipeline); // Check that the resulting dependency graph is acyclic and within the maximum depth. Status graphStatus = _upsertIntoGraph(txn, *(view.get())); if (!graphStatus.isOK()) { return graphStatus; } _durable->upsert(txn, viewName, viewDef); _viewMap[viewName.ns()] = view; txn->recoveryUnit()->onRollback([this, viewName]() { this->_viewMap.erase(viewName.ns()); this->_viewGraphNeedsRefresh = true; }); // We may get invalidated, but we're exclusively locked, so the change must be ours. txn->recoveryUnit()->onCommit([this]() { this->_valid.store(true); }); return Status::OK(); }
Status ViewCatalog::_createOrUpdateView_inlock(OperationContext* opCtx, const NamespaceString& viewName, const NamespaceString& viewOn, const BSONArray& pipeline, std::unique_ptr<CollatorInterface> collator) { _requireValidCatalog_inlock(opCtx); // Build the BSON definition for this view to be saved in the durable view catalog. If the // collation is empty, omit it from the definition altogether. BSONObjBuilder viewDefBuilder; viewDefBuilder.append("_id", viewName.ns()); viewDefBuilder.append("viewOn", viewOn.coll()); viewDefBuilder.append("pipeline", pipeline); if (collator) { viewDefBuilder.append("collation", collator->getSpec().toBSON()); } BSONObj ownedPipeline = pipeline.getOwned(); auto view = std::make_shared<ViewDefinition>( viewName.db(), viewName.coll(), viewOn.coll(), ownedPipeline, std::move(collator)); // Check that the resulting dependency graph is acyclic and within the maximum depth. Status graphStatus = _upsertIntoGraph(opCtx, *(view.get())); if (!graphStatus.isOK()) { return graphStatus; } _durable->upsert(opCtx, viewName, viewDefBuilder.obj()); _viewMap[viewName.ns()] = view; opCtx->recoveryUnit()->onRollback([this, viewName]() { this->_viewMap.erase(viewName.ns()); this->_viewGraphNeedsRefresh = true; }); // We may get invalidated, but we're exclusively locked, so the change must be ours. opCtx->recoveryUnit()->onCommit( [this](boost::optional<Timestamp>) { this->_valid.store(true); }); return Status::OK(); }