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