/* **************************************************************************** * * stringToformat - */ TEST(commonFormat, stringToformat) { Format format; format = stringToFormat("XML"); EXPECT_EQ(XML, format); format = stringToFormat("JSON"); EXPECT_EQ(JSON, format); format = stringToFormat("noFormat"); EXPECT_EQ(NOFORMAT, format); }
/* **************************************************************************** * * SubscriptionCache::insert - */ void SubscriptionCache::insert(const std::string& tenant, BSONObj bobj) { BSONElement idField = bobj.getField("_id"); if (idField.eoo() == true) { LM_E(("Database Error (error retrieving _id field in doc: '%s')", bobj.toString().c_str())); return; } // // 01. Extract values from database object 'bobj' // std::string subId = idField.OID().toString(); int64_t expiration = bobj.hasField(CSUB_EXPIRATION)? bobj.getField(CSUB_EXPIRATION).Long() : 0; std::string reference = bobj.getField(CSUB_REFERENCE).String(); int64_t throttling = bobj.hasField(CSUB_THROTTLING)? bobj.getField(CSUB_THROTTLING).Long() : -1; std::vector<BSONElement> eVec = bobj.getField(CSUB_ENTITIES).Array(); std::vector<BSONElement> attrVec = bobj.getField(CSUB_ATTRS).Array(); std::vector<BSONElement> condVec = bobj.getField(CSUB_CONDITIONS).Array(); std::string formatString = bobj.hasField(CSUB_FORMAT)? bobj.getField(CSUB_FORMAT).String() : "XML"; std::string servicePath = bobj.hasField(CSUB_SERVICE_PATH)? bobj.getField(CSUB_SERVICE_PATH).String() : "/"; Format format = stringToFormat(formatString); int lastNotification = bobj.hasField(CSUB_LASTNOTIFICATION)? bobj.getField(CSUB_LASTNOTIFICATION).Int() : 0; std::vector<EntityInfo*> eiV; std::vector<std::string> attrV; Restriction restriction; NotifyConditionVector notifyConditionVector; // // 02. Push Entity-data names to EntityInfo Vector (eiV) // for (unsigned int ix = 0; ix < eVec.size(); ++ix) { BSONObj entity = eVec[ix].embeddedObject(); if (!entity.hasField(CSUB_ENTITY_ID)) { LM_W(("Runtime Error (got a subscription without id)")); continue; } std::string id = entity.getStringField(ENT_ENTITY_ID); if (!entity.hasField(CSUB_ENTITY_ISPATTERN)) { continue; } std::string isPattern = entity.getStringField(CSUB_ENTITY_ISPATTERN); if (isPattern != "true") { continue; } std::string type = ""; if (entity.hasField(CSUB_ENTITY_TYPE)) { type = entity.getStringField(CSUB_ENTITY_TYPE); } EntityInfo* eiP = new EntityInfo(id, type); eiV.push_back(eiP); } if (eiV.size() == 0) { return; } // // 03. Push attribute names to Attribute Vector (attrV) // for (unsigned int ix = 0; ix < attrVec.size(); ++ix) { std::string attributeName = attrVec[ix].String(); attrV.push_back(attributeName); } // // 04. FIXME P4: Restriction not implemented // // // 05. Fill in notifyConditionVector from condVec // for (unsigned int ix = 0; ix < condVec.size(); ++ix) { BSONObj condition = condVec[ix].embeddedObject(); std::string condType; std::vector<BSONElement> valueVec; condType = condition.getStringField(CSUB_CONDITIONS_TYPE); if (condType != "ONCHANGE") { continue; } NotifyCondition* ncP = new NotifyCondition(); ncP->type = condType; valueVec = condition.getField(CSUB_CONDITIONS_VALUE).Array(); for (unsigned int vIx = 0; vIx < valueVec.size(); ++vIx) { std::string condValue; condValue = valueVec[vIx].String(); ncP->condValueList.push_back(condValue); } notifyConditionVector.push_back(ncP); } if (notifyConditionVector.size() == 0) { for (unsigned int ix = 0; ix < eiV.size(); ++ix) { delete(eiV[ix]); } eiV.clear(); restriction.release(); return; } // // 06. Create Subscription and add it to the subscription-cache // Subscription* subP = new Subscription(tenant, servicePath, subId, eiV, attrV, throttling, expiration, restriction, notifyConditionVector, reference, lastNotification, format); subCache->insert(subP); notifyConditionVector.release(); // Subscription constructor makes a copy }
/* **************************************************************************** * * mongoSubscribeContext - */ HttpStatusCode mongoSubscribeContext ( SubscribeContextRequest* requestP, SubscribeContextResponse* responseP, const std::string& tenant, std::map<std::string, std::string>& uriParam, const std::string& xauthToken, const std::vector<std::string>& servicePathV ) { const std::string notifyFormatAsString = uriParam[URI_PARAM_NOTIFY_FORMAT]; Format notifyFormat = stringToFormat(notifyFormatAsString); std::string servicePath = (servicePathV.size() == 0)? "" : servicePathV[0]; bool reqSemTaken = false; LM_T(LmtMongo, ("Subscribe Context Request: notifications sent in '%s' format", notifyFormatAsString.c_str())); reqSemTake(__FUNCTION__, "ngsi10 subscribe request", SemWriteOp, &reqSemTaken); // // Calculate expiration (using the current time and the duration field in the request). // If expiration is not present, use a default value // long long expiration = -1; if (requestP->expires > 0) { expiration = requestP->expires; } else { if (requestP->duration.isEmpty()) { requestP->duration.set(DEFAULT_DURATION); } expiration = getCurrentTime() + requestP->duration.parse(); } LM_T(LmtMongo, ("Subscription expiration: %lu", expiration)); /* Create the mongoDB subscription document */ BSONObjBuilder sub; OID oid; oid.init(); sub.append("_id", oid); sub.append(CSUB_EXPIRATION, expiration); sub.append(CSUB_REFERENCE, requestP->reference.get()); /* Throttling */ long long throttling = 0; if (requestP->throttling.seconds != -1) { throttling = (long long) requestP->throttling.seconds; sub.append(CSUB_THROTTLING, throttling); } else if (!requestP->throttling.isEmpty()) { throttling = (long long) requestP->throttling.parse(); sub.append(CSUB_THROTTLING, throttling); } if (servicePath != "") { sub.append(CSUB_SERVICE_PATH, servicePath); } /* Build entities array */ BSONArrayBuilder entities; for (unsigned int ix = 0; ix < requestP->entityIdVector.size(); ++ix) { EntityId* en = requestP->entityIdVector[ix]; if (en->type == "") { entities.append(BSON(CSUB_ENTITY_ID << en->id << CSUB_ENTITY_ISPATTERN << en->isPattern)); } else { entities.append(BSON(CSUB_ENTITY_ID << en->id << CSUB_ENTITY_TYPE << en->type << CSUB_ENTITY_ISPATTERN << en->isPattern)); } } sub.append(CSUB_ENTITIES, entities.arr()); /* Build attributes array */ BSONArrayBuilder attrs; for (unsigned int ix = 0; ix < requestP->attributeList.size(); ++ix) { attrs.append(requestP->attributeList[ix]); } sub.append(CSUB_ATTRS, attrs.arr()); /* Build conditions array (including side-effect notifications and threads creation) */ bool notificationDone = false; BSONArray conds = processConditionVector(&requestP->notifyConditionVector, requestP->entityIdVector, requestP->attributeList, oid.toString(), requestP->reference.get(), ¬ificationDone, notifyFormat, tenant, xauthToken, servicePathV, requestP->expression.q); sub.append(CSUB_CONDITIONS, conds); /* Build expression */ BSONObjBuilder expression; expression << CSUB_EXPR_Q << requestP->expression.q << CSUB_EXPR_GEOM << requestP->expression.geometry << CSUB_EXPR_COORDS << requestP->expression.coords << CSUB_EXPR_GEOREL << requestP->expression.georel; sub.append(CSUB_EXPR, expression.obj()); /* Last notification */ long long lastNotificationTime = 0; if (notificationDone) { lastNotificationTime = (long long) getCurrentTime(); sub.append(CSUB_LASTNOTIFICATION, lastNotificationTime); sub.append(CSUB_COUNT, 1); } /* Adding format to use in notifications */ sub.append(CSUB_FORMAT, notifyFormatAsString); /* Insert document in database */ std::string err; if (!collectionInsert(getSubscribeContextCollectionName(tenant), sub.obj(), &err)) { reqSemGive(__FUNCTION__, "ngsi10 subscribe request (mongo db exception)", reqSemTaken); responseP->subscribeError.errorCode.fill(SccReceiverInternalError, err); return SccOk; } // // 3. Create Subscription for the cache // std::string oidString = oid.toString(); LM_T(LmtSubCache, ("inserting a new sub in cache (%s)", oidString.c_str())); cacheSemTake(__FUNCTION__, "Inserting subscription in cache"); subCacheItemInsert(tenant.c_str(), servicePath.c_str(), requestP, oidString.c_str(), expiration, throttling, notifyFormat, notificationDone, lastNotificationTime, requestP->expression.q, requestP->expression.geometry, requestP->expression.coords, requestP->expression.georel); cacheSemGive(__FUNCTION__, "Inserting subscription in cache"); reqSemGive(__FUNCTION__, "ngsi10 subscribe request", reqSemTaken); /* Fill int the response element */ responseP->subscribeResponse.duration = requestP->duration; responseP->subscribeResponse.subscriptionId.set(oid.toString()); responseP->subscribeResponse.throttling = requestP->throttling; return SccOk; }