Beispiel #1
0
 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()));
  }
}
Beispiel #3
0
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;
}
Beispiel #7
0
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); });
}
Beispiel #8
0
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, &notifAttributesV);

      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()));
}