BSONArray versionArray(){ static BSONArray out; if (out.isEmpty()) { BSONArray tmp = _versionArray(versionString); out = tmp; return tmp; } return out; }
/* **************************************************************************** * * setAttrs - */ static void setAttrs(const SubscriptionUpdate& subUp, const BSONObj& subOrig, BSONObjBuilder* b) { if (subUp.notificationProvided) { setAttrs(subUp, b); } else { BSONArray attrs = getArrayFieldF(subOrig, CSUB_ATTRS); b->append(CSUB_ATTRS, attrs); LM_T(LmtMongo, ("Subscription attrs: %s", attrs.toString().c_str())); } }
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(); }
/* **************************************************************************** * * setEntities - */ static void setEntities(const SubscriptionUpdate& subUp, const BSONObj& subOrig, BSONObjBuilder* b) { if (subUp.subjectProvided && !subUp.fromNgsiv1) { // // NGSIv1 doesn't allow to change entities, // see https://fiware-orion.readthedocs.io/en/master/user/updating_regs_and_subs/index.html // setEntities(subUp, b); } else { BSONArray entities = getArrayFieldF(subOrig, CSUB_ENTITIES); b->append(CSUB_ENTITIES, entities); LM_T(LmtMongo, ("Subscription entities: %s", entities.toString().c_str())); } }
/* **************************************************************************** * * setMetadata - */ static void setMetadata(const SubscriptionUpdate& subUp, const BSONObj& subOrig, BSONObjBuilder* b) { if (subUp.notificationProvided) { setMetadata(subUp, b); } else { // // Note that if subOrig doesn't have CSUB_METADATA (e.g. old subscription in the DB created before // this feature) BSONArray constructor ensures an empty array // BSONArray metadata; if (subOrig.hasField(CSUB_METADATA)) { metadata = getArrayFieldF(subOrig, CSUB_METADATA); } b->append(CSUB_METADATA, metadata); LM_T(LmtMongo, ("Subscription metadata: %s", metadata.toString().c_str())); } }
void DocumentStructureEnumerator::_enumerateFixedLenArrs( const DocumentStructureEnumeratorConfig& config, const ScalarGenerator* scalarGenerator, BSONArray arr, std::vector<BSONArray>* arrs) { if (!config.length) { // Base case: no more room for any other elements. arrs->push_back(arr); return; } // Otherwise, go through our choices, similar to the approach to documents. // DocumentStructureEnumeratorConfig nextElementConfig(config); nextElementConfig.length--; // Scalar. BSONArrayBuilder scalarArr = _getArrayBuilderFromArr(arr); scalarGenerator->generateScalar().addToBsonArray(&scalarArr); _enumerateFixedLenArrs(nextElementConfig, scalarGenerator, scalarArr.arr(), arrs); if (config.depth <= 0) { return; } DocumentStructureEnumeratorConfig nextLayerConfig(config); nextLayerConfig.depth--; nextLayerConfig.length += arr.nFields(); // Subarray. std::vector<BSONArray> subArrs = _enumerateArrs(nextLayerConfig, scalarGenerator); for (auto subArr : subArrs) { BSONArrayBuilder arrayArr = _getArrayBuilderFromArr(arr); arrayArr.append(subArr); _enumerateFixedLenArrs(nextElementConfig, scalarGenerator, arrayArr.arr(), arrs); } // Document. if (!config.skipSubDocs) { BSONObj blankDoc; std::vector<BSONObj> subDocs; _enumerateDocs(nextLayerConfig, scalarGenerator, blankDoc, &subDocs); for (auto subDoc : subDocs) { BSONArrayBuilder docArr = _getArrayBuilderFromArr(arr); docArr.append(subDoc); _enumerateFixedLenArrs(nextElementConfig, scalarGenerator, docArr.arr(), arrs); } } return; }
void ViewCatalog::_createOrUpdateView_inlock(OperationContext* txn, const NamespaceString& viewName, const NamespaceString& viewOn, const BSONArray& pipeline) { invariant(_valid.load()); BSONObj viewDef = BSON("_id" << viewName.ns() << "viewOn" << viewOn.coll() << "pipeline" << pipeline); _durable->upsert(txn, viewName, viewDef); BSONObj ownedPipeline = pipeline.getOwned(); _viewMap[viewName.ns()] = std::make_shared<ViewDefinition>( viewName.db(), viewName.coll(), viewOn.coll(), ownedPipeline); txn->recoveryUnit()->onRollback([this, viewName]() { this->_viewMap.erase(viewName.ns()); }); // We may get invalidated, but we're exclusively locked, so the change must be ours. txn->recoveryUnit()->onCommit([this]() { this->_valid.store(true); }); }
Status ViewCatalog::_createOrUpdateView(WithLock lk, OperationContext* opCtx, const NamespaceString& viewName, const NamespaceString& viewOn, const BSONArray& pipeline, std::unique_ptr<CollatorInterface> collator) { _requireValidCatalog(lk, 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(lk, 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(); }
/* **************************************************************************** * * setCondsAndInitialNotify - */ static void setCondsAndInitialNotify ( const SubscriptionUpdate& subUp, const BSONObj& subOrig, const std::string& tenant, const std::vector<std::string>& servicePathV, const std::string& xauthToken, const std::string& fiwareCorrelator, BSONObjBuilder* b, const bool& skipInitialNotification, bool* notificationDone ) { // notification can be changed to true by setCondsAndInitialNotify() *notificationDone = false; if (subUp.subjectProvided) { std::string status; HttpInfo httpInfo; bool blacklist; std::vector<std::string> notifAttributesV; std::vector<std::string> metadataV; RenderFormat attrsFormat = NGSI_V2_NORMALIZED; if (subUp.statusProvided) { status = subUp.status; } else { status = subOrig.hasField(CSUB_STATUS)? getStringFieldF(subOrig, CSUB_STATUS) : STATUS_ACTIVE; } if (subUp.notificationProvided) { httpInfo = subUp.notification.httpInfo; blacklist = subUp.notification.blacklist; metadataV = subUp.notification.metadata; notifAttributesV = subUp.notification.attributes; } else { httpInfo.fill(subOrig); blacklist = subOrig.hasField(CSUB_BLACKLIST)? getBoolFieldF(subOrig, CSUB_BLACKLIST) : false; setStringVectorF(subOrig, CSUB_ATTRS, ¬ifAttributesV); if (subOrig.hasField(CSUB_METADATA)) { setStringVectorF(subOrig, CSUB_METADATA, &metadataV); } } if (subUp.attrsFormatProvided) { attrsFormat = subUp.attrsFormat; } else if (subOrig.hasField(CSUB_FORMAT)) { attrsFormat = stringToRenderFormat(getStringFieldF(subOrig, CSUB_FORMAT)); } if (subUp.fromNgsiv1) { // // In NGSIv1 is legal updating conditions without updating entities, which is not possible // in NGSIv2 (as both entities and coditions are part of 'subject' and they are updated as // a whole). In addition, NGSIv1 doesn't allow to update notification attributes. Both // (entities and notification attributes) are passed in subOrig. // // See: https://fiware-orion.readthedocs.io/en/master/user/updating_regs_and_subs/index.html // setCondsAndInitialNotifyNgsiv1(subUp, subOrig, subUp.id, status, httpInfo.url, attrsFormat, tenant, servicePathV, xauthToken, fiwareCorrelator, b, skipInitialNotification, notificationDone); } else { setCondsAndInitialNotify(subUp, subUp.id, status, notifAttributesV, metadataV, httpInfo, blacklist, attrsFormat, tenant, servicePathV, xauthToken, fiwareCorrelator, b, notificationDone, skipInitialNotification, V2); } } else { BSONArray conds = getArrayFieldF(subOrig, CSUB_CONDITIONS); b->append(CSUB_CONDITIONS, conds); LM_T(LmtMongo, ("Subscription conditions: %s", conds.toString().c_str())); } }
/* **************************************************************************** * * setCondsAndInitialNotifyNgsiv1 - * * This method could be removed along with the rest of NGSIv1 stuff */ static void setCondsAndInitialNotifyNgsiv1 ( const Subscription& sub, const BSONObj& subOrig, const std::string& subId, const std::string& status, const std::string& url, RenderFormat attrsFormat, const std::string& tenant, const std::vector<std::string>& servicePathV, const std::string& xauthToken, const std::string& fiwareCorrelator, BSONObjBuilder* b, const bool& skipInitialNotification, bool* notificationDone ) { // // Similar to setCondsAndInitialNotify() in MongoCommonSubscripion.cpp, but // entities and notifications attributes are not taken from sub but from subOrig // // Most of the following code is copied from mongoGetSubscription logic but, given // that this function is temporal, I don't worry too much about DRY-ness here std::vector<EntID> entities; std::vector<BSONElement> ents = getFieldF(subOrig, CSUB_ENTITIES).Array(); for (unsigned int ix = 0; ix < ents.size(); ++ix) { BSONObj ent = ents[ix].embeddedObject(); std::string id = getStringFieldF(ent, CSUB_ENTITY_ID); std::string type = ent.hasField(CSUB_ENTITY_TYPE)? getStringFieldF(ent, CSUB_ENTITY_TYPE) : ""; std::string isPattern = getStringFieldF(ent, CSUB_ENTITY_ISPATTERN); EntID en; if (isFalse(isPattern)) { en.id = id; } else { en.idPattern = id; } en.type = type; entities.push_back(en); } std::vector<std::string> attributes; std::vector<std::string> metadata; setStringVectorF(subOrig, CSUB_ATTRS, &attributes); if (subOrig.hasField(CSUB_METADATA)) { setStringVectorF(subOrig, CSUB_METADATA, &metadata); } /* Conds vector (and maybe an initial notification) */ *notificationDone = false; BSONArray conds = processConditionVector(sub.subject.condition.attributes, entities, attributes, metadata, subId, ngsiv2::HttpInfo(url), notificationDone, attrsFormat, tenant, xauthToken, servicePathV, &(sub.restriction), status, fiwareCorrelator, sub.notification.attributes, sub.notification.blacklist, skipInitialNotification, V1); b->append(CSUB_CONDITIONS, conds); LM_T(LmtMongo, ("Subscription conditions: %s", conds.toString().c_str())); }