void SubscriptionService::onServerStop(RcfServer &server) { RCF_UNUSED_VARIABLE(server); mPeriodicTimer.stop(); Subscriptions subs; { Lock writeLock(mSubscriptionsMutex); subs = mSubscriptions; } for (Subscriptions::iterator iter = subs.begin(); iter != subs.end(); ++iter) { SubscriptionPtr subscriptionPtr = iter->lock(); if (subscriptionPtr) { subscriptionPtr->close(); } } { Lock writeLock(mSubscriptionsMutex); RCF_ASSERT(mSubscriptions.empty()); } mSubscriptions.clear(); subs.clear(); mpServer = NULL; }
void SubscriptionService::pingAllSubscriptions() { // Send oneway pings on all our subscriptions, so the publisher // knows we're still alive. Subscriptions subs; { Lock lock(mSubscriptionsMutex); subs = mSubscriptions; } Subscriptions::iterator iter; for (iter = subs.begin(); iter != subs.end(); ++iter) { SubscriptionPtr subPtr = iter->lock(); if (subPtr) { Subscription & sub = * subPtr; if (sub.mPingsEnabled && sub.isConnected()) { // Lock will be unlocked when the asynchronous send completes. // Using recursive lock here because the ping may result in a // disconnect, which will then automatically close the connection // and close the subscription, which requires the lock to be taken again. boost::shared_ptr<RecursiveLock> lockPtr( new RecursiveLock(sub.mMutex) ); // TODO: async pings bool asyncPings = false; if (asyncPings) { AsioErrorCode ecDummy; sub.mConnectionPtr->getClientStub().ping( RCF::AsyncOneway(boost::bind( &SubscriptionService::sOnPingCompleted, lockPtr))); } else { try { sub.mConnectionPtr->getClientStub().ping(RCF::Oneway); } catch(const RCF::Exception & e) { std::string errMsg = e.getErrorString(); RCF_UNUSED_VARIABLE(errMsg); } } } } } }
void SubscriptionService::harvestExpiredSubscriptions() { // Kill off subscriptions that haven't received any recent pings. Subscriptions subsToDrop; { Lock lock(mSubscriptionsMutex); Subscriptions::iterator iter; for (iter = mSubscriptions.begin(); iter != mSubscriptions.end(); ++iter) { SubscriptionPtr subPtr = iter->lock(); if (subPtr) { Subscription & sub = * subPtr; RecursiveLock lock(sub.mMutex); RcfSessionPtr sessionPtr = sub.mRcfSessionWeakPtr.lock(); if (!sessionPtr) { RCF_LOG_2()(sub.mPublisherUrl)(sub.mTopic) << "Dropping subscription. Publisher has closed connection."; subsToDrop.insert(*iter); } else if (sub.mPingsEnabled) { boost::uint32_t pingIntervalMs = sub.mPingIntervalMs; if (pingIntervalMs) { RCF::Timer pingTimer(sessionPtr->getPingTimestamp()); if (pingTimer.elapsed(5000 + 2*pingIntervalMs)) { RCF_LOG_2()(sub.mPublisherUrl)(sub.mTopic)(sub.mPingIntervalMs) << "Dropping subscription. Publisher has not sent pings."; subsToDrop.insert(*iter); } } } } } for (iter = subsToDrop.begin(); iter != subsToDrop.end(); ++iter) { mSubscriptions.erase(*iter); } } subsToDrop.clear(); }
TMessageSystem::Subscriptions::iterator TMessageSystem::FindSubscription(Subscriptions& subscriptions, const MessageID& messageId) { auto it = subscriptions.begin(); const auto iend = subscriptions.end(); while (it != iend) { if (it->first != messageId) { ++it; } else { break; } } return it; }
HTTPCode SubscriberManager::modify_subscriptions( const std::string& public_id, const Subscriptions& update_subscriptions, const std::vector<std::string>& remove_subscriptions, HSSConnection::irs_info& irs_info, SAS::TrailId trail) { int now = time(NULL); // Get cached subscriber information from the HSS. std::string aor_id; HTTPCode rc = get_cached_default_id(public_id, aor_id, irs_info, trail); if (rc != HTTP_OK) { TRC_DEBUG("Unable to modify subscription for %s - HSS lookup failed with " " return code %d", public_id.c_str(), rc); return rc; } AoR* orig_aor = NULL; uint64_t unused_version; rc = _s4->handle_get(aor_id, &orig_aor, unused_version, trail); // There must be an existing AoR since there must be bindings to subscribe to. if (rc != HTTP_OK) { TRC_DEBUG("Modifying subscription for AoR %s failed during S4 lookup " "with return code %d", aor_id.c_str(), rc); return rc; } PatchObject patch_object; build_patch(patch_object, update_subscriptions, remove_subscriptions, irs_info._associated_uris); // PATCH the existing AoR. AoR* updated_aor = NULL; rc = _s4->handle_patch(aor_id, patch_object, &updated_aor, trail); if (rc != HTTP_OK) { TRC_DEBUG("Modifying subscription for AoR %s failed during S4 update with " "return code %d", aor_id.c_str(), rc); } else { // At this point modifying the subscription has been successful - we'll return // OK to the client. // Write an analytics log for the modified subscription. std::string subscription_id = (remove_subscriptions.empty()) ? update_subscriptions.begin()->first : remove_subscriptions[0]; log_subscriptions(aor_id, *orig_aor, *updated_aor, {subscription_id}, now); // Finally, send any NOTIFYs. send_notifys(aor_id, orig_aor, updated_aor, SubscriberDataUtils::EventTrigger::USER, now, trail); } // Delete both AoRs - the client doesn't need either of these. delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; }