Пример #1
0
    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;
    }
Пример #2
0
    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);
                        }
                    }
                }
            }
        }
    }
Пример #3
0
    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();
    }
Пример #4
0
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;
}
Пример #5
0
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;
}