/* **************************************************************************** * * mongoUnsubscribeContextAvailability - */ HttpStatusCode mongoUnsubscribeContextAvailability ( UnsubscribeContextAvailabilityRequest* requestP, UnsubscribeContextAvailabilityResponse* responseP, const std::string& tenant ) { bool reqSemTaken; std::string err; reqSemTake(__FUNCTION__, "ngsi9 unsubscribe request", SemWriteOp, &reqSemTaken); LM_T(LmtMongo, ("Unsubscribe Context Availability")); /* No matter if success or failure, the subscriptionId in the response is always the one * in the request */ responseP->subscriptionId = requestP->subscriptionId; /* Look for document */ BSONObj sub; OID id; if (!safeGetSubId(requestP->subscriptionId, &id, &(responseP->statusCode))) { reqSemGive(__FUNCTION__, "ngsi9 unsubscribe request (safeGetSubId fail)", reqSemTaken); if (responseP->statusCode.code == SccContextElementNotFound) { // FIXME: doubt: invalid OID format? Or, subscription not found? std::string details = std::string("invalid OID format: '") + requestP->subscriptionId.get() + "'"; alarmMgr.badInput(clientIp, details); } else // SccReceiverInternalError { LM_E(("Runtime Error (exception getting OID: %s)", responseP->statusCode.details.c_str())); } return SccOk; } if (!collectionFindOne(getSubscribeContextAvailabilityCollectionName(tenant), BSON("_id" << id), &sub, &err)) { reqSemGive(__FUNCTION__, "ngsi9 unsubscribe request (mongo db exception)", reqSemTaken); responseP->statusCode.fill(SccReceiverInternalError, err); return SccOk; } alarmMgr.dbErrorReset(); if (sub.isEmpty()) { responseP->statusCode.fill(SccContextElementNotFound); reqSemGive(__FUNCTION__, "ngsi9 unsubscribe request (no subscriptions)", reqSemTaken); return SccOk; } /* Remove document in MongoDB */ // FIXME: I would prefer to do the find and remove in a single operation. Is the some similar // to findAndModify for this? if (!collectionRemove(getSubscribeContextAvailabilityCollectionName(tenant), BSON("_id" << OID(requestP->subscriptionId.get())), &err)) { reqSemGive(__FUNCTION__, "ngsi9 unsubscribe request (mongo db exception)", reqSemTaken); responseP->statusCode.fill(SccReceiverInternalError, err); return SccOk; } reqSemGive(__FUNCTION__, "ngsi9 unsubscribe request", reqSemTaken); responseP->statusCode.fill(SccOk); return SccOk; }
/* **************************************************************************** * * mongoUnsubscribeContext - */ HttpStatusCode mongoUnsubscribeContext(UnsubscribeContextRequest* requestP, UnsubscribeContextResponse* responseP, const std::string& tenant) { bool reqSemTaken; std::string err; reqSemTake(__FUNCTION__, "ngsi10 unsubscribe request", SemWriteOp, &reqSemTaken); LM_T(LmtMongo, ("Unsubscribe Context")); /* No matter if success or failure, the subscriptionId in the response is always the one * in the request */ responseP->subscriptionId = requestP->subscriptionId; if (responseP->subscriptionId.get() == "") { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (no subscriptions found)", reqSemTaken); responseP->statusCode.fill(SccContextElementNotFound); alarmMgr.badInput(clientIp, "no subscriptionId"); return SccOk; } /* Look for document */ BSONObj sub; OID id; if (!safeGetSubId(requestP->subscriptionId, &id, &(responseP->statusCode))) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (safeGetSubId fail)", reqSemTaken); if (responseP->statusCode.code == SccContextElementNotFound) { // FIXME: Doubt - invalid OID format? Or, just a subscription that was not found? std::string details = std::string("invalid OID format: '") + requestP->subscriptionId.get() + "'"; alarmMgr.badInput(clientIp, details); } else // SccReceiverInternalError { LM_E(("Runtime Error (exception getting OID: %s)", responseP->statusCode.details.c_str())); } return SccOk; } if (!collectionFindOne(getSubscribeContextCollectionName(tenant), BSON("_id" << id), &sub, &err)) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (mongo db exception)", reqSemTaken); responseP->statusCode.fill(SccReceiverInternalError, err); return SccOk; } if (sub.isEmpty()) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (no subscriptions found)", reqSemTaken); responseP->statusCode.fill(SccContextElementNotFound, std::string("subscriptionId: /") + requestP->subscriptionId.get() + "/"); return SccOk; } /* Remove document in MongoDB */ // FIXME: I would prefer to do the find and remove in a single operation. Is there something similar // to findAndModify for this? if (!collectionRemove(getSubscribeContextCollectionName(tenant), BSON("_id" << OID(requestP->subscriptionId.get())), &err)) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (mongo db exception)", reqSemTaken); responseP->statusCode.fill(SccReceiverInternalError, err); return SccOk; } /* Destroy any previous ONTIMEINTERVAL thread */ getNotifier()->destroyOntimeIntervalThreads(requestP->subscriptionId.get()); // // Removing subscription from mongo subscription cache // LM_T(LmtSubCache, ("removing subscription '%s' (tenant '%s') from mongo subscription cache", requestP->subscriptionId.get().c_str(), tenant.c_str())); cacheSemTake(__FUNCTION__, "Removing subscription from cache"); CachedSubscription* cSubP = subCacheItemLookup(tenant.c_str(), requestP->subscriptionId.get().c_str()); if (cSubP != NULL) { subCacheItemRemove(cSubP); } cacheSemGive(__FUNCTION__, "Removing subscription from cache"); reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request", reqSemTaken); responseP->statusCode.fill(SccOk); return SccOk; }
/* **************************************************************************** * * mongoUnsubscribeContext - */ HttpStatusCode mongoUnsubscribeContext(UnsubscribeContextRequest* requestP, UnsubscribeContextResponse* responseP, const std::string& tenant) { bool reqSemTaken; std::string err; reqSemTake(__FUNCTION__, "ngsi10 unsubscribe request", SemWriteOp, &reqSemTaken); LM_T(LmtMongo, ("Unsubscribe Context")); /* No matter if success or failure, the subscriptionId in the response is always the one * in the request */ responseP->subscriptionId = requestP->subscriptionId; if (responseP->subscriptionId.get() == "") { responseP->statusCode.fill(SccContextElementNotFound); LM_W(("Bad Input (no subscriptionId)")); return SccOk; } /* Look for document */ BSONObj sub; OID id; try { id = OID(requestP->subscriptionId.get()); } catch (const AssertionException &e) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (mongo assertion exception)", reqSemTaken); // // This happens when OID format is wrong // FIXME: this checking should be done at parsing stage, without progressing to // mongoBackend. For the moment we can live this here, but we should remove in the future // (old issue #95) // responseP->statusCode.fill(SccContextElementNotFound); LM_W(("Bad Input (invalid OID format)")); return SccOk; } if (!collectionFindOne(getSubscribeContextCollectionName(tenant), BSON("_id" << id), &sub, &err)) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (mongo db exception)", reqSemTaken); responseP->statusCode.fill(SccReceiverInternalError, err); return SccOk; } if (sub.isEmpty()) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (no subscriptions found)", reqSemTaken); responseP->statusCode.fill(SccContextElementNotFound, std::string("subscriptionId: /") + requestP->subscriptionId.get() + "/"); return SccOk; } /* Remove document in MongoDB */ // FIXME: I would prefer to do the find and remove in a single operation. Is there something similar // to findAndModify for this? if (!collectionRemove(getSubscribeContextCollectionName(tenant), BSON("_id" << OID(requestP->subscriptionId.get())), &err)) { reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request (mongo db exception)", reqSemTaken); responseP->statusCode.fill(SccReceiverInternalError, err); return SccOk; } /* Destroy any previous ONTIMEINTERVAL thread */ getNotifier()->destroyOntimeIntervalThreads(requestP->subscriptionId.get()); // FIXME P7: mongoSubCache stuff could be avoided if subscription is not patterned // // Removing subscription from mongo subscription cache // LM_T(LmtMongoSubCache, ("removing subscription '%s' (tenant '%s') from mongo subscription cache", requestP->subscriptionId.get().c_str(), tenant.c_str())); cacheSemTake(__FUNCTION__, "Removing subscription from cache"); CachedSubscription* cSubP = mongoSubCacheItemLookup(tenant.c_str(), requestP->subscriptionId.get().c_str()); if (cSubP != NULL) // Will only enter here if wildcard subscription { mongoSubCacheItemRemove(cSubP); } cacheSemGive(__FUNCTION__, "Removing subscription from cache"); reqSemGive(__FUNCTION__, "ngsi10 unsubscribe request", reqSemTaken); responseP->statusCode.fill(SccOk); return SccOk; }