[asterisk-scf-commits] asterisk-scf/release/servicediscovery.git branch "ami" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon Nov 22 09:11:37 CST 2010


branch "ami" has been created
        at  4e2fc7fe6b4405bda7fdf6c6f465455aeae5e88c (commit)

- Log -----------------------------------------------------------------
commit 4e2fc7fe6b4405bda7fdf6c6f465455aeae5e88c
Author: David M. Lee <dlee at digium.com>
Date:   Mon Nov 22 08:42:23 2010 -0600

    Removed stray #include.

diff --git a/src/ServiceLocator.cpp b/src/ServiceLocator.cpp
index f16fda5..d5242fa 100644
--- a/src/ServiceLocator.cpp
+++ b/src/ServiceLocator.cpp
@@ -14,8 +14,6 @@
  * at the top of the source tree.
  */
 
-#include <boost/thread.hpp>
-
 #include <Ice/Ice.h>
 #include <IceStorm/IceStorm.h>
 #include <IceBox/IceBox.h>

commit c3a005c4fba65370be3abe014d626aed30ba1d41
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 23:29:50 2010 -0600

    Commenting, formating and general clean up

diff --git a/src/ServiceLocator.cpp b/src/ServiceLocator.cpp
index e2e1159..f16fda5 100644
--- a/src/ServiceLocator.cpp
+++ b/src/ServiceLocator.cpp
@@ -65,9 +65,18 @@ class ServiceLocatorImpl : public ServiceLocator
 public:
     ServiceLocatorImpl(ServiceLocatorManagementImpl* LocatorServiceManagement) :
         mLocatorServiceManagement(LocatorServiceManagement) { };
-
-    void locate_async(const ::AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locatePtr&, const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const ::Ice::Current&);
-    void locateAll_async(const ::AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locateAllPtr&, const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const ::Ice::Current&);
+    /**
+     * Asynchronously locate a service for the given parameters.
+     * @see ServiceLocator::locate_async
+     */
+    void locate_async(const AMD_ServiceLocator_locatePtr&,
+        const ServiceLocatorParamsPtr&, const Ice::Current&);
+    /**
+     * Asynchronously locate all service for the given parameters.
+     * @see ServiceLocator::locateAll_async
+     */
+    void locateAll_async(const AMD_ServiceLocator_locateAllPtr&,
+        const ServiceLocatorParamsPtr&, const ::Ice::Current&);
 private:
     /**
      * A pointer to the ServiceManagement implementation as that is where everything is
@@ -83,6 +92,7 @@ void ServiceLocatorImpl::locate_async(const AMD_ServiceLocator_locatePtr& cb,
     const ServiceLocatorParamsPtr& params,
     const ::Ice::Current&)
 {
+    // delegate to the management object, where the data is kept
     mLocatorServiceManagement->locate(cb, params);
 }
 
@@ -90,6 +100,7 @@ void ServiceLocatorImpl::locateAll_async(const AMD_ServiceLocator_locateAllPtr&
     const ServiceLocatorParamsPtr& params,
     const ::Ice::Current&)
 {
+    // delegate to the management object, where the data is kept
     mLocatorServiceManagement->locateAll(cb, params);
 }
 
diff --git a/src/ServiceLocatorManagement.cpp b/src/ServiceLocatorManagement.cpp
index 6ffdfd7..7fed90f 100644
--- a/src/ServiceLocatorManagement.cpp
+++ b/src/ServiceLocatorManagement.cpp
@@ -30,19 +30,17 @@ using namespace std;
 using namespace AsteriskSCF::System::Discovery;
 using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::ServiceDiscovery;
 
 namespace
 {
-Logger const &lg = getLoggerFactory().getLogger("AsteriskSCF.System.Discovery");
-}
 
-namespace AsteriskSCF
-{
-namespace ServiceDiscovery
-{
+Logger const &lg = getLoggerFactory().getLogger("AsteriskSCF.System.Discovery");
 
 /**
- * Callback class for isSupported AMI calls.
+ * Callback class for isSupported AMI calls.  Acts as a bridge between
+ * Ice callbacks and IsSupportedCallback.
+ * @see IsSupportedCallback
  */
 class Comparator_IsSupported_Callback : public IceUtil::Shared
 {
@@ -59,6 +57,7 @@ public:
 
         try
         {
+            // forward result to callback
             callback->result(comparator->end_isSupported(r));
         }
         catch (std::exception const &e)
@@ -99,11 +98,18 @@ public:
      * Results are returned via callback object.
      *
      * @param params Service locator parameters that describe a locator request.
+     * @param callback Callback object which receives the results.
      */
-    void isSupported(const ServiceLocatorParamsPtr& params, IsSupportedCallbackPtr const &callback)
+    void isSupported(const ServiceLocatorParamsPtr& params,
+        IsSupportedCallbackPtr const &callback)
     {
-        Comparator_IsSupported_CallbackPtr iceCallback = new Comparator_IsSupported_Callback(callback);
-        Ice::CallbackPtr d = Ice::newCallback(iceCallback, &Comparator_IsSupported_Callback::finished);
+        // wrap our callback with an Ice callback
+        Comparator_IsSupported_CallbackPtr iceCallback =
+            new Comparator_IsSupported_Callback(callback);
+        // which is wrapped again...
+        Ice::CallbackPtr d = Ice::newCallback(iceCallback,
+            &Comparator_IsSupported_Callback::finished);
+        // async forward to the comparator
         mCompare->begin_isSupported(params, d);
     }
 private:
@@ -114,68 +120,34 @@ private:
 };
 
 /**
- * Small internal class which is used to store private details for
- * ServiceLocatorManagementImpl.
+ * Interface that the LocateCallback uses for collecting information on which
+ * services are supported and which are not.
  */
-class ServiceLocatorManagementImplPriv : public Ice::Object
+class LocateCollector : public IceUtil::Shared
 {
 public:
-    ServiceLocatorManagementImplPriv(const Ice::ObjectAdapterPtr& adapter, const EventsPrx& serviceDiscoveryTopic) :
-        mAdapter(adapter), mLocatorTopic(serviceDiscoveryTopic)
-    {
-    };
-
-    /**
-     * Shared mutex lock which protects the services and comparators.
-     */
-    boost::shared_mutex mLock;
-
-    /**
-     * Object adapter that our service management proxies originate from, it is houses the
-     * main management service.
-     */
-    Ice::ObjectAdapterPtr mAdapter;
-
-    /**
-     * A map of all the comparators that have been added by external components. The key
-     * is the unique identifier that they add themselves with.
-     */
-    std::map<std::string, ServiceLocatorComparator> mCompares;
-
-    /**
-     * A vector of all the services that have been added.
-     */
-    std::vector<ServiceManagementImplPtr> mServices;
-
+    virtual ~LocateCollector() {}
     /**
-     * A proxy that can be used to publish locator events.
+     * Invoked for every service in ServiceLocatorManagementImplPriv::mServices.
+     * @param management Pointer to the management object
+     * @param supported resultsf from ServiceManagementImplPtr::isSupported
      */
-    AsteriskSCF::System::Discovery::EventsPrx mLocatorTopic;
+    virtual void isSupported(ServiceManagementImplPtr management,
+        bool supported) = 0;
 };
-} /* end of ServiceDiscovery */
-} /* end of AsteriskSCF */
-
-using namespace AsteriskSCF::ServiceDiscovery;
 
 /**
- * Implementation of a constructor for the ServiceLocatorManagementImpl class.
+ * A LocateCollector which forwards the first supported service to the
+ * given Ice callback.
  */
-ServiceLocatorManagementImpl::ServiceLocatorManagementImpl(const Ice::ObjectAdapterPtr& adapter,
-    const EventsPrx& serviceDiscoveryTopic) :
-    mImpl(new ServiceLocatorManagementImplPriv(adapter, serviceDiscoveryTopic))
-{
-}
-
-class LocateCollector : public IceUtil::Shared
-{
-public:
-    virtual ~LocateCollector() {}
-    virtual void isSupported(ServiceManagementImplPtr management, bool supported) = 0;
-};
-
 class LocateOneCollector : public LocateCollector
 {
 public:
+    /**
+     * ctor.
+     * @param cb Ice callback.
+     * @param numVotes The number of times isSupported will be called.
+     */
     LocateOneCollector(const AMD_ServiceLocator_locatePtr& cb, int numVotes) :
         cb(cb), numVotes(numVotes)
     {
@@ -193,29 +165,45 @@ public:
 
         if (supported && cb)
         {
-            lg(Debug) << "  ...locate() = " << management->getService()->ice_toString() << '\n';
+            lg(Debug) << "  ...locate() = "
+                      << management->getService()->ice_toString() << '\n';
             cb->ice_response(management->getService());
+            // clear the cb pointer so we only answer once
             cb = 0;
         }
 
+        assert(numVotes > 0); // isSupported was called too many times
+
         if (--numVotes == 0 && cb)
         {
             lg(Debug) << "  ...locate() = ServiceNotFound\n";
             ServiceNotFound e;
             cb->ice_exception(e);
+            // clear the cb pointer so we only answer once
             cb = 0;
         }
     }
 
 private:
     boost::mutex mLock;
+    /** Ice callback */
     AMD_ServiceLocator_locatePtr cb;
+    /** The number of times isSupported will be called. */
     int numVotes;
 };
 
+/**
+ * A LocateCollector which makes a list of all supported services to
+ * forward to the given Ice callback.
+ */
 class LocateAllCollector : public LocateCollector
 {
 public:
+    /**
+     * ctor.
+     * @param cb Ice callback.
+     * @param numVotes The number of times isSupported will be called.
+     */
     LocateAllCollector(const AMD_ServiceLocator_locateAllPtr& cb, int numVotes) :
         cb(cb), numVotes(numVotes)
     {
@@ -238,6 +226,7 @@ public:
 
         if (--numVotes == 0 && cb)
         {
+            // the votes are in!
             if (!value.empty())
             {
                 cb->ice_response(value);
@@ -247,17 +236,29 @@ public:
                 ServiceNotFound e;
                 cb->ice_exception(e);
             }
+            // we're done with the callback
+            cb = 0;
         }
     }
 
 private:
     boost::mutex mLock;
+    /** Ice callback */
     AMD_ServiceLocator_locateAllPtr cb;
+    /** The number of times isSupported will be called. */
     int numVotes;
+    /** Collected results */
     Ice::ObjectProxySeq value;
 };
-
 typedef IceUtil::Handle<LocateCollector> LocateCollectorPtr;
+
+/**
+ * Callback with the results for ServiceManagementImpl::isSupported.  This
+ * implementation simply forwards the info on to a LocateCollector.
+ *
+ * @see ServiceManagementImpl::isSupported
+ * @see LocateCollector
+ */
 class LocateCallback : public IsSupportedCallback
 {
 public:
@@ -281,6 +282,64 @@ private:
 };
 typedef IceUtil::Handle<LocateCallback> LocateCallbackPtr;
 
+} // end of anonymous namespace
+
+IsSupportedCallback::~IsSupportedCallback()
+{
+    // no-op
+}
+
+/**
+ * Small internal class which is used to store private details for
+ * ServiceLocatorManagementImpl.
+ */
+class AsteriskSCF::ServiceDiscovery::ServiceLocatorManagementImplPriv :
+    public Ice::Object
+{
+public:
+    ServiceLocatorManagementImplPriv(const Ice::ObjectAdapterPtr& adapter,
+        const EventsPrx& serviceDiscoveryTopic) :
+        mAdapter(adapter), mLocatorTopic(serviceDiscoveryTopic)
+    {
+    };
+
+    /**
+     * Shared mutex lock which protects the services and comparators.
+     */
+    boost::shared_mutex mLock;
+
+    /**
+     * Object adapter that our service management proxies originate from, it is
+     * houses the main management service.
+     */
+    Ice::ObjectAdapterPtr mAdapter;
+
+    /**
+     * A map of all the comparators that have been added by external components.
+     * The key is the unique identifier that they add themselves with.
+     */
+    std::map<std::string, ServiceLocatorComparator> mCompares;
+
+    /**
+     * A vector of all the services that have been added.
+     */
+    std::vector<ServiceManagementImplPtr> mServices;
+
+    /**
+     * A proxy that can be used to publish locator events.
+     */
+    AsteriskSCF::System::Discovery::EventsPrx mLocatorTopic;
+};
+
+/**
+ * Implementation of a constructor for the ServiceLocatorManagementImpl class.
+ */
+ServiceLocatorManagementImpl::ServiceLocatorManagementImpl(
+    const Ice::ObjectAdapterPtr& adapter,
+    const EventsPrx& serviceDiscoveryTopic) :
+    mImpl(new ServiceLocatorManagementImplPriv(adapter, serviceDiscoveryTopic))
+{
+}
 
 void ServiceLocatorManagementImpl::locate(const AMD_ServiceLocator_locatePtr& cb,
     const ServiceLocatorParamsPtr& params)
@@ -288,23 +347,33 @@ void ServiceLocatorManagementImpl::locate(const AMD_ServiceLocator_locatePtr& cb
     lg(Debug) << "locate(" << params->category << ")\n";
     boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
 
-    LocateCollectorPtr collector = new LocateOneCollector(cb, mImpl->mServices.size());
+    LocateCollectorPtr collector = new LocateOneCollector(cb,
+        mImpl->mServices.size());
 
-    for (vector<ServiceManagementImplPtr>::iterator service = mImpl->mServices.begin(); service != mImpl->mServices.end(); ++service)
+    for (vector<ServiceManagementImplPtr>::iterator service =
+             mImpl->mServices.begin();
+         service != mImpl->mServices.end();
+         ++service)
     {
         LocateCallbackPtr callback = new LocateCallback(collector,  *service);
         (*service)->isSupported(params, callback);
     }
 }
 
-void ServiceLocatorManagementImpl::locateAll(const AMD_ServiceLocator_locateAllPtr& cb,
+void ServiceLocatorManagementImpl::locateAll(
+    const AMD_ServiceLocator_locateAllPtr& cb,
     const ServiceLocatorParamsPtr& params)
 {
+    lg(Debug) << "locateAll(" << params->category << ")\n";
     boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
 
-    LocateCollectorPtr collector = new LocateAllCollector(cb, mImpl->mServices.size());
+    LocateCollectorPtr collector = new LocateAllCollector(cb,
+        mImpl->mServices.size());
 
-    for (vector<ServiceManagementImplPtr>::iterator service = mImpl->mServices.begin(); service != mImpl->mServices.end(); ++service)
+    for (vector<ServiceManagementImplPtr>::iterator service =
+             mImpl->mServices.begin();
+         service != mImpl->mServices.end();
+         ++service)
     {
         LocateCallbackPtr callback = new LocateCallback(collector,  *service);
         (*service)->isSupported(params, callback);
diff --git a/src/ServiceLocatorManagement.h b/src/ServiceLocatorManagement.h
index a2f4f31..4dddc41 100644
--- a/src/ServiceLocatorManagement.h
+++ b/src/ServiceLocatorManagement.h
@@ -39,36 +39,55 @@ typedef IceUtil::Handle<ServiceManagementImpl> ServiceManagementImplPtr;
  */
 class ServiceLocatorManagementImplPriv;
 
+/**
+ * Callback interface for ServiceLocatorManagementImpl::isSupported.
+ * @see ServiceLocatorManagementImpl::isSupported
+ */
 class IsSupportedCallback : public IceUtil::Shared
 {
 public:
+    virtual ~IsSupportedCallback();
+    /**
+     * Callback for the results from ServiceLocatorManagementImpl::isSupported.
+     */
     virtual void result(bool result) = 0;
 };
 typedef IceUtil::Handle<IsSupportedCallback> IsSupportedCallbackPtr;
 
 /**
- * Implementation of the ServiceLocatorManagement interface as defined in service_locator.ice
+ * Implementation of the ServiceLocatorManagement interface as defined in
+ * service_locator.ice
  */
-class ServiceLocatorManagementImpl : public AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagement
+class ServiceLocatorManagementImpl :
+        public AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagement
 {
 public:
     ServiceLocatorManagementImpl(const Ice::ObjectAdapterPtr& adapter,
         const AsteriskSCF::System::Discovery::EventsPrx& serviceDiscoveryTopic);
-    void locate(const AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locatePtr& cb,
+    void locate(
+        const AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locatePtr&,
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
-    void locateAll(const AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locateAllPtr&,
+    void locateAll(
+        const AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locateAllPtr&,
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
 
     //
     // AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagement interface.
     //
-    AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx addService(const Ice::ObjectPrx&, const std::string&, const Ice::Current&);
-    AsteriskSCF::Core::Discovery::V1::ServiceInfoSeq getServices(const ::Ice::Current&) const;
-    AsteriskSCF::Core::Discovery::V1::ServiceInfo getService(const std::string &, const ::Ice::Current&) const;
-    void addCompare(const std::string&, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsComparePrx&, const Ice::Current&);
+    AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx addService(
+        const Ice::ObjectPrx&, const std::string&, const Ice::Current&);
+    AsteriskSCF::Core::Discovery::V1::ServiceInfoSeq getServices(
+        const ::Ice::Current&) const;
+    AsteriskSCF::Core::Discovery::V1::ServiceInfo getService(
+        const std::string &, const ::Ice::Current&) const;
+    void addCompare(const std::string&,
+        const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsComparePrx&,
+        const Ice::Current&);
     void removeCompare(const std::string&, const Ice::Current&);
 
-    void isSupported(const std::string&, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, IsSupportedCallbackPtr const &);
+    void isSupported(const std::string&,
+        const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&,
+        IsSupportedCallbackPtr const &);
     void removeService(const ServiceManagementImplPtr&);
 private:
     /**
diff --git a/src/ServiceManagement.cpp b/src/ServiceManagement.cpp
index eda51e1..4f96399 100644
--- a/src/ServiceManagement.cpp
+++ b/src/ServiceManagement.cpp
@@ -46,8 +46,10 @@ namespace ServiceDiscovery
 class ServiceLocatorParamsSpec
 {
 public:
-    ServiceLocatorParamsSpec(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& params, const std::string& compareGuid,
-        ServiceLocatorManagementImpl* management) :
+    ServiceLocatorParamsSpec(const ServiceLocatorParamsPtr& params,
+        const std::string& compareGuid,
+        ServiceLocatorManagementImpl* management)
+        :
         mParams(params),
         mCompareGuid(compareGuid),
         mManagement(management)
@@ -174,6 +176,11 @@ ServiceManagementPrx ServiceManagementImpl::getServiceManagementPrx()
     return mImpl->mManagementPrx;
 }
 
+/**
+ * An IsSupportedCallback that maps a certain number of callback
+ * invocations to a single callback.  If any callbacks are true, true is
+ * called back.  If none are true, false is called back.
+ */
 class CountedIsSupported : public IsSupportedCallback
 {
 public:
@@ -215,20 +222,24 @@ private:
 };
 
 /**
- * An internal function which is called by the service locator to perform a locator parameters comparison
- * at the service level.
+ * An internal function which is called by the service locator to perform a
+ * locator parameters comparison at the service level.
  *
- * @param params A concrete class containing parameters describing the service that is trying to be found.
+ * @param params A concrete class containing parameters describing the
+ *               service that is trying to be found.
+ * @param callback Callback to asynchronously rx the results.
  */
 void ServiceManagementImpl::isSupported(const ServiceLocatorParamsPtr& params, const IsSupportedCallbackPtr& callback)
 {
     boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
-    lg(Debug) << __PRETTY_FUNCTION__ << "(" << params->category << ")\n";
+    lg(Debug) << "isSupported(" << params->category << ")\n";
 
-    /* If this service is suspended we can just skip the entire check and return false now, easy as pie */
+    /* If this service is suspended we can just skip the entire check and
+     * return false now, easy as pie
+     */
     if (mImpl->mSuspended)
     {
-        lg(Debug) << "  ..." << __PRETTY_FUNCTION__ << "(" << params->category << ") = false\n";
+        lg(Debug) << "  ...isSupported(" << params->category << ") = false\n";
         callback->result(false);
         return;
     }
@@ -236,7 +247,10 @@ void ServiceManagementImpl::isSupported(const ServiceLocatorParamsPtr& params, c
     IsSupportedCallbackPtr myCallback = new CountedIsSupported(
         callback, mImpl->mSupportedLocatorParams.size());
 
-    for (vector<ServiceLocatorParamsSpec>::iterator spec = mImpl->mSupportedLocatorParams.begin(); spec != mImpl->mSupportedLocatorParams.end(); ++spec)
+    for (vector<ServiceLocatorParamsSpec>::iterator
+             spec = mImpl->mSupportedLocatorParams.begin();
+         spec != mImpl->mSupportedLocatorParams.end();
+         ++spec)
     {
         spec->isSupported(params, myCallback);
     }
@@ -248,25 +262,28 @@ std::string const &ServiceManagementImpl::getGuid() const
 }
 
 /**
- * An internal function which is called by the service locator to perform a locator parameters comparison
- * at the parameter and perhaps comparator level.
- *
- * @param params A concrete class containing parameters describing the service that is trying to be found.
+ * An internal function which is called by the service locator to perform a
+ * locator parameters comparison at the parameter and perhaps comparator level.
  *
+ * @param params A concrete class containing parameters describing the service
+ *               that is trying to be found.
+ * @param callback Callback to asynchronously rx the results.
  */
 void ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params, const IsSupportedCallbackPtr& callback)
 {
-    lg(Debug) << __PRETTY_FUNCTION__ << "(" << params->category << ")\n";
-    // If no category is passed to us then the component doing the locate wants everything/anything, so give it to them
+    lg(Debug) << "isSupported(" << params->category << ")\n";
+    // If no category is passed to us then the component doing the locate wants
+    // everything/anything, so give it to them
     if (params->category.empty())
     {
-        lg(Debug) << "  ..." << __PRETTY_FUNCTION__ << "(" << params->category << ") = true\n";
+        lg(Debug) << "  ...isSupported(" << params->category << ") = true\n";
         callback->result(true);
     }
-    /* This is just a simple comparison that acts as a preliminary, and perhaps final, check */
+    /* This is just a simple comparison that acts as a preliminary, and
+     * perhaps final, check */
     else if (mParams->category != params->category)
     {
-        lg(Debug) << "  ..." << __PRETTY_FUNCTION__ << "(" << params->category << ") = false\n";
+        lg(Debug) << "  ...isSupported(" << params->category << ") = false\n";
         callback->result(false);
     }
     /* If a comparator was provided then yield to it for a final yay or nay */
@@ -274,6 +291,7 @@ void ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params
     {
         mManagement->isSupported(mCompareGuid, params, callback);
     }
+    /* category matches, no comparator to turn us down.  it's a match. */
     else
     {
         callback->result(true);
diff --git a/src/ServiceManagement.h b/src/ServiceManagement.h
index a70ccec..24236c1 100644
--- a/src/ServiceManagement.h
+++ b/src/ServiceManagement.h
@@ -47,7 +47,9 @@ public:
 
     Ice::ObjectPrx getService();
     AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx getServiceManagementPrx();
-    void isSupported(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const IsSupportedCallbackPtr&);
+    void isSupported(
+        const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&,
+        const IsSupportedCallbackPtr&);
     const std::string &getGuid() const;
     AsteriskSCF::Core::Discovery::V1::ServiceStatus getStatus() const;
 private:
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 4176ec2..d5dd7fc 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -13,7 +13,8 @@ asterisk_scf_component_add_slice(service_locator_test ServiceLocatorEventsIf)
 asterisk_scf_component_add_file(service_locator_test TestServiceLocator.cpp)
 asterisk_scf_component_add_file(service_locator_test TestComparatorBlocking.cpp)
 asterisk_scf_component_add_ice_libraries(service_locator_test IceStorm)
-asterisk_scf_component_add_boost_libraries(service_locator_test unit_test_framework thread)
+asterisk_scf_component_add_boost_libraries(service_locator_test
+    unit_test_framework thread)
 asterisk_scf_component_build_icebox(service_locator_test)
 #asterisk_scf_component_install(service_locator_test RUNTIME bin "Service Locator Test Driver." Core)
 
diff --git a/test/TestComparatorBlocking.cpp b/test/TestComparatorBlocking.cpp
index 2e0ccfd..d3701e2 100644
--- a/test/TestComparatorBlocking.cpp
+++ b/test/TestComparatorBlocking.cpp
@@ -14,6 +14,15 @@
  * at the top of the source tree.
  */
 
+/*
+ * The purpose of these tests are to verify the resilience of the service
+ * locator in the event of wacky comparators.  For example, the machine
+ * hosting a comparator may suddenly die, at which point Ice calls to the
+ * comparator could take as long as a minute to time out.  Per call.
+ * Without special efforts in implementation, the service locator would be
+ * unable to service calls while it was waiting on the comparator.
+ */
+
 #define BOOST_TEST_DYN_LINK
 
 #include <iostream>
@@ -40,7 +49,7 @@ class BlockingComparator : public ServiceLocatorParamsCompare
 public:
     BlockingComparator() : blocked(true), completed(false) {}
 
-    bool isSupported(const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&,
+    bool isSupported(const ServiceLocatorParamsPtr&,
         const ::Ice::Current&)
     {
         boost::unique_lock<boost::mutex> lock(mut);
@@ -59,6 +68,7 @@ public:
     {
         boost::unique_lock<boost::mutex> lock(mut);
         blocked = false;
+        BOOST_TEST_MESSAGE("  ...Unblocking\n");
         cond.notify_one();
     }
 
@@ -69,11 +79,17 @@ private:
     boost::mutex mut;
     bool blocked, completed;
 };
+typedef IceUtil::Handle<BlockingComparator> BlockingComparatorPtr;
 
+/**
+ * An Ice callback object which can pause execution until the callback has
+ * been invoked.
+ */
 class BlockingCallback : public IceUtil::Shared
 {
 public:
     BlockingCallback() : beenCalled(false) {}
+
     void locateCB(const Ice::ObjectPrx&located)
     {
         boost::unique_lock<boost::mutex> lock(mut);
@@ -88,6 +104,13 @@ public:
         cond.notify_one();
     }
 
+    /**
+     * Blocks waiting for callback notification, or until the given timeout
+     * has expired.
+     *
+     * @param waitTimeMillis Max number of milliseconds to wait for callback.
+     * @return True if the callback was invoked.  False if timed out.
+     */
     bool waitForCallback(int waitTimeMillis)
     {
         boost::unique_lock<boost::mutex> lock(mut);
@@ -103,8 +126,6 @@ private:
     boost::mutex mut;
     bool beenCalled;
 };
-
-typedef IceUtil::Handle<BlockingComparator> BlockingComparatorPtr;
 typedef IceUtil::Handle<BlockingCallback> BlockingCallbackPtr;
 
 class Fixture
@@ -114,14 +135,20 @@ public:
         // create an register the blocker
         blockerCommunicator(Ice::initialize()),
         blocker(new BlockingComparator()),
-        blockerAdapter(blockerCommunicator->createObjectAdapterWithEndpoints("blocker", "default")),
-        blockerProxy(ServiceLocatorParamsComparePrx::checkedCast(blockerAdapter->addWithUUID(blocker))),
-        // get references to discovery on different communictor
+        blockerAdapter(
+            blockerCommunicator->createObjectAdapterWithEndpoints(
+                "blocker", "default")),
+        blockerProxy(
+            ServiceLocatorParamsComparePrx::checkedCast(
+                blockerAdapter->addWithUUID(blocker))),
+        // get references to discovery on different communicator
         discoveryCommunicator(Ice::initialize()),
         management(ServiceLocatorManagementPrx::checkedCast(
-                discoveryCommunicator->stringToProxy("LocatorServiceManagement:tcp -p 4422"))),
+                discoveryCommunicator->stringToProxy(
+                    "LocatorServiceManagement:tcp -p 4422"))),
         discovery(ServiceLocatorPrx::checkedCast(
-                discoveryCommunicator->stringToProxy("LocatorService:tcp -p 4411"))),
+                discoveryCommunicator->stringToProxy(
+                    "LocatorService:tcp -p 4411"))),
         proxy(management->addService(management, "self")),
         params(new ServiceLocatorParams())
     {
@@ -211,10 +238,11 @@ BOOST_AUTO_TEST_CASE(testBlocking)
 
     discovery->begin_locate(dne, undiscoveredCB);
 
+    // 10 seconds is ample time to discover something that doesn't exist
     bool secondDiscoveryCompleted = callback->waitForCallback(10000);
     BOOST_REQUIRE(secondDiscoveryCompleted);
-    BOOST_REQUIRE(!blocker->hasCompleted());
 
+    BOOST_REQUIRE(!blocker->hasCompleted());
     blocker->unblock();
     asyncDiscovered->waitForCompleted();
     BOOST_REQUIRE(blocker->hasCompleted());

commit e5b9f4a036dc687b2720383ccdc2a4fe552fe3b0
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 15:45:47 2010 -0600

    Unit tests pass.

diff --git a/src/ServiceLocator.cpp b/src/ServiceLocator.cpp
index e16dc03..e2e1159 100644
--- a/src/ServiceLocator.cpp
+++ b/src/ServiceLocator.cpp
@@ -77,92 +77,20 @@ private:
     ServiceLocatorManagementImpl* mLocatorServiceManagement;
 };
 
-class LocateThread
-{
-public:
-    LocateThread(const AMD_ServiceLocator_locatePtr& cb,
-        const ServiceLocatorParamsPtr& params,
-        ServiceLocatorManagementImpl* locatorServiceManagement) :
-        mCallback(cb),
-        mParams(params),
-        mLocatorServiceManagement(locatorServiceManagement)
-    {
-    }
-
-    void operator()()
-    {
-        try
-        {
-            lg(Info) << "locate(" << mParams->category << ")\n";
-            mCallback->ice_response(mLocatorServiceManagement->locate(mParams));
-            lg(Info) << "locate(" << mParams->category << "): complete\n";
-        }
-        catch(std::exception const &e)
-        {
-            lg(Info) << "locate(" << mParams->category << "): std::exception(" << e.what() << ")\n";
-            mCallback->ice_exception(e);
-        }
-        catch(...)
-        {
-            lg(Info) << "locate(" << mParams->category << "): bad::exception\n";
-            mCallback->ice_exception();
-        }
-    }
-private:
-    AMD_ServiceLocator_locatePtr mCallback;
-    ServiceLocatorParamsPtr mParams;
-    ServiceLocatorManagementImpl* mLocatorServiceManagement;
-};
-
-class LocateAllThread
-{
-public:
-    LocateAllThread(const AMD_ServiceLocator_locateAllPtr& cb,
-        const ServiceLocatorParamsPtr& params,
-        ServiceLocatorManagementImpl* locatorServiceManagement) :
-        mCallback(cb),
-        mParams(params),
-        mLocatorServiceManagement(locatorServiceManagement)
-    {
-    }
-
-    void operator()()
-    {
-        try
-        {
-            mCallback->ice_response(mLocatorServiceManagement->locateAll(mParams));
-        }
-catch(std::exception const &e)
-        {
-            lg(Info) << "locate(" << mParams->category << "): std::exception(" << e.what() << ")\n";
-            mCallback->ice_exception(e);
-        }
-        catch(...)
-        {
-            lg(Info) << "locate(" << mParams->category << "): bad::exception\n";
-            mCallback->ice_exception();
-        }
-    }
-private:
-    AMD_ServiceLocator_locateAllPtr mCallback;
-    ServiceLocatorParamsPtr mParams;
-    ServiceLocatorManagementImpl* mLocatorServiceManagement;
-};
-
 }
 
 void ServiceLocatorImpl::locate_async(const AMD_ServiceLocator_locatePtr& cb,
     const ServiceLocatorParamsPtr& params,
     const ::Ice::Current&)
 {
-    boost::thread(LocateThread(cb, params, mLocatorServiceManagement));
+    mLocatorServiceManagement->locate(cb, params);
 }
 
 void ServiceLocatorImpl::locateAll_async(const AMD_ServiceLocator_locateAllPtr& cb,
     const ServiceLocatorParamsPtr& params,
     const ::Ice::Current&)
 {
-    boost::thread(LocateAllThread(cb, params, mLocatorServiceManagement));
+    mLocatorServiceManagement->locateAll(cb, params);
 }
 
 void ServiceLocatorApp::start(const string& name, const Ice::CommunicatorPtr& communicator,
diff --git a/src/ServiceLocatorManagement.cpp b/src/ServiceLocatorManagement.cpp
index fdef99d..6ffdfd7 100644
--- a/src/ServiceLocatorManagement.cpp
+++ b/src/ServiceLocatorManagement.cpp
@@ -42,6 +42,43 @@ namespace ServiceDiscovery
 {
 
 /**
+ * Callback class for isSupported AMI calls.
+ */
+class Comparator_IsSupported_Callback : public IceUtil::Shared
+{
+public:
+    Comparator_IsSupported_Callback(IsSupportedCallbackPtr const &callback) :
+        callback(callback)
+    {
+    }
+
+    void finished(const Ice::AsyncResultPtr& r)
+    {
+        ServiceLocatorParamsComparePrx comparator =
+            ServiceLocatorParamsComparePrx::uncheckedCast(r->getProxy());
+
+        try
+        {
+            callback->result(comparator->end_isSupported(r));
+        }
+        catch (std::exception const &e)
+        {
+            lg(Error) << "Error communicating with comparator: " << e.what();
+            callback->result(false);
+        }
+        catch(...)
+        {
+            lg(Error) << "Error communicating with comparator";
+            callback->result(false);
+        }
+    }
+
+private:
+    IsSupportedCallbackPtr callback;
+};
+typedef IceUtil::Handle<Comparator_IsSupported_Callback> Comparator_IsSupported_CallbackPtr;
+
+/**
  * Small internal class which is used to store information about a comparator.
  */
 class ServiceLocatorComparator
@@ -59,15 +96,15 @@ public:
 
     /**
      * API call which forwards an isSupported over ICE to a remote comparator.
+     * Results are returned via callback object.
      *
      * @param params Service locator parameters that describe a locator request.
-     *
-     * @return A boolean value with true indicating the parameters are supported while
-     *         false indicates otherwise.
      */
-    bool isSupported(const ServiceLocatorParamsPtr& params)
+    void isSupported(const ServiceLocatorParamsPtr& params, IsSupportedCallbackPtr const &callback)
     {
-        return mCompare->isSupported(params);
+        Comparator_IsSupported_CallbackPtr iceCallback = new Comparator_IsSupported_Callback(callback);
+        Ice::CallbackPtr d = Ice::newCallback(iceCallback, &Comparator_IsSupported_Callback::finished);
+        mCompare->begin_isSupported(params, d);
     }
 private:
     /**
@@ -129,49 +166,148 @@ ServiceLocatorManagementImpl::ServiceLocatorManagementImpl(const Ice::ObjectAdap
 {
 }
 
-/**
- * Implementation of the locate method as defined in service_locator.ice
- */
-Ice::ObjectPrx ServiceLocatorManagementImpl::locate(const ServiceLocatorParamsPtr& params)
+class LocateCollector : public IceUtil::Shared
 {
-    boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
+public:
+    virtual ~LocateCollector() {}
+    virtual void isSupported(ServiceManagementImplPtr management, bool supported) = 0;
+};
 
-    for (vector<ServiceManagementImplPtr>::iterator service = mImpl->mServices.begin(); service != mImpl->mServices.end(); ++service)
+class LocateOneCollector : public LocateCollector
+{
+public:
+    LocateOneCollector(const AMD_ServiceLocator_locatePtr& cb, int numVotes) :
+        cb(cb), numVotes(numVotes)
     {
-        if ((*service)->isSupported(params) == true)
+        if (numVotes == 0)
         {
-            return (*service)->getService();
+            ServiceNotFound e;
+            cb->ice_exception(e);
+            this->cb = 0;
         }
     }
 
-    throw ServiceNotFound();
-}
+    void isSupported(ServiceManagementImplPtr management, bool supported)
+    {
+        boost::lock_guard<boost::mutex> guard(mLock);
 
-/**
- * Implementation of the locateAll method as defined in service_locator.ice
- */
-Ice::ObjectProxySeq ServiceLocatorManagementImpl::locateAll(
-    const ServiceLocatorParamsPtr& params)
+        if (supported && cb)
+        {
+            lg(Debug) << "  ...locate() = " << management->getService()->ice_toString() << '\n';
+            cb->ice_response(management->getService());
+            cb = 0;
+        }
+
+        if (--numVotes == 0 && cb)
+        {
+            lg(Debug) << "  ...locate() = ServiceNotFound\n";
+            ServiceNotFound e;
+            cb->ice_exception(e);
+            cb = 0;
+        }
+    }
+
+private:
+    boost::mutex mLock;
+    AMD_ServiceLocator_locatePtr cb;
+    int numVotes;
+};
+
+class LocateAllCollector : public LocateCollector
 {
-    boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
-    Ice::ObjectProxySeq applicableServices;
+public:
+    LocateAllCollector(const AMD_ServiceLocator_locateAllPtr& cb, int numVotes) :
+        cb(cb), numVotes(numVotes)
+    {
+        if (numVotes == 0)
+        {
+            ServiceNotFound e;
+            cb->ice_exception(e);
+            this->cb = 0;
+        }
+    }
 
-    for (vector<ServiceManagementImplPtr>::iterator service = mImpl->mServices.begin();
-         service != mImpl->mServices.end(); ++service)
+    void isSupported(ServiceManagementImplPtr management, bool supported)
     {
-        if ((*service)->isSupported(params) == true)
+        boost::lock_guard<boost::mutex> guard(mLock);
+
+        if (supported)
+        {
+            value.push_back(management->getService());
+        }
+
+        if (--numVotes == 0 && cb)
         {
-            applicableServices.push_back((*service)->getService());
+            if (!value.empty())
+            {
+                cb->ice_response(value);
+            }
+            else
+            {
+                ServiceNotFound e;
+                cb->ice_exception(e);
+            }
         }
     }
 
-    if (!applicableServices.empty())
+private:
+    boost::mutex mLock;
+    AMD_ServiceLocator_locateAllPtr cb;
+    int numVotes;
+    Ice::ObjectProxySeq value;
+};
+
+typedef IceUtil::Handle<LocateCollector> LocateCollectorPtr;
+class LocateCallback : public IsSupportedCallback
+{
+public:
+    LocateCallback(const LocateCollectorPtr& collector,
+        const ServiceManagementImplPtr& management) :
+        collector(collector),
+        management(management)
+    {
+    }
+
+    void result(bool result)
+    {
+        // delegation to thread safe object
+        // no lock needed
+        collector->isSupported(management, result);
+        collector = 0;
+    }
+private:
+    LocateCollectorPtr collector;
+    ServiceManagementImplPtr management;
+};
+typedef IceUtil::Handle<LocateCallback> LocateCallbackPtr;
+
+
+void ServiceLocatorManagementImpl::locate(const AMD_ServiceLocator_locatePtr& cb,
+    const ServiceLocatorParamsPtr& params)
+{
+    lg(Debug) << "locate(" << params->category << ")\n";
+    boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+    LocateCollectorPtr collector = new LocateOneCollector(cb, mImpl->mServices.size());
+
+    for (vector<ServiceManagementImplPtr>::iterator service = mImpl->mServices.begin(); service != mImpl->mServices.end(); ++service)
     {
-        return applicableServices;
+        LocateCallbackPtr callback = new LocateCallback(collector,  *service);
+        (*service)->isSupported(params, callback);
     }
-    else
+}
+
+void ServiceLocatorManagementImpl::locateAll(const AMD_ServiceLocator_locateAllPtr& cb,
+    const ServiceLocatorParamsPtr& params)
+{
+    boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+    LocateCollectorPtr collector = new LocateAllCollector(cb, mImpl->mServices.size());
+
+    for (vector<ServiceManagementImplPtr>::iterator service = mImpl->mServices.begin(); service != mImpl->mServices.end(); ++service)
     {
-        throw ServiceNotFound();
+        LocateCallbackPtr callback = new LocateCallback(collector,  *service);
+        (*service)->isSupported(params, callback);
     }
 }
 
@@ -265,8 +401,9 @@ void ServiceLocatorManagementImpl::removeCompare(const string& guid, const Ice::
 /**
  * Implementation of the isSupported method as defined in service_locator.ice
  */
-bool ServiceLocatorManagementImpl::isSupported(const string& compareGuid,
-    const ServiceLocatorParamsPtr& params)
+void ServiceLocatorManagementImpl::isSupported(const string& compareGuid,
+    const ServiceLocatorParamsPtr& params,
+    IsSupportedCallbackPtr const &callback)
 {
     /* You'll note there is no lock here. This is because we already have a lock in the locate or locateAll
      * functions.
@@ -276,18 +413,11 @@ bool ServiceLocatorManagementImpl::isSupported(const string& compareGuid,
 
     if (comparator == mImpl->mCompares.end())
     {
-        return false;
+        callback->result(false);
+        return;
     }
 
-    try
-    {
-        return (comparator->second).isSupported(params);
-    }
-    catch (...)
-    {
-        lg(Error) << "An exception was raised when attempting to contact comparator " << compareGuid << ".";
-        return false;
-    }
+    (comparator->second).isSupported(params, callback);
 }
 
 /**
diff --git a/src/ServiceLocatorManagement.h b/src/ServiceLocatorManagement.h
index 2e6a361..a2f4f31 100644
--- a/src/ServiceLocatorManagement.h
+++ b/src/ServiceLocatorManagement.h
@@ -18,6 +18,8 @@
 
 #include <boost/shared_ptr.hpp>
 
+#include <IceUtil/Shared.h>
+
 namespace AsteriskSCF
 {
 namespace ServiceDiscovery
@@ -37,6 +39,13 @@ typedef IceUtil::Handle<ServiceManagementImpl> ServiceManagementImplPtr;
  */
 class ServiceLocatorManagementImplPriv;
 
+class IsSupportedCallback : public IceUtil::Shared
+{
+public:
+    virtual void result(bool result) = 0;
+};
+typedef IceUtil::Handle<IsSupportedCallback> IsSupportedCallbackPtr;
+
 /**
  * Implementation of the ServiceLocatorManagement interface as defined in service_locator.ice
  */
@@ -45,8 +54,10 @@ class ServiceLocatorManagementImpl : public AsteriskSCF::Core::Discovery::V1::Se
 public:
     ServiceLocatorManagementImpl(const Ice::ObjectAdapterPtr& adapter,
         const AsteriskSCF::System::Discovery::EventsPrx& serviceDiscoveryTopic);
-    Ice::ObjectPrx locate(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
-    Ice::ObjectProxySeq locateAll(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
+    void locate(const AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locatePtr& cb,
+        const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
+    void locateAll(const AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locateAllPtr&,
+        const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
 
     //
     // AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagement interface.
@@ -57,7 +68,7 @@ public:
     void addCompare(const std::string&, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsComparePrx&, const Ice::Current&);
     void removeCompare(const std::string&, const Ice::Current&);
 
-    bool isSupported(const std::string&, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
+    void isSupported(const std::string&, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, IsSupportedCallbackPtr const &);
     void removeService(const ServiceManagementImplPtr&);
 private:
     /**
diff --git a/src/ServiceManagement.cpp b/src/ServiceManagement.cpp
index f8ae230..eda51e1 100644
--- a/src/ServiceManagement.cpp
+++ b/src/ServiceManagement.cpp
@@ -54,7 +54,7 @@ public:
     {
     }
 
-    bool isSupported(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
+    void isSupported(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const IsSupportedCallbackPtr&);
 
 private:
     /**
@@ -174,34 +174,72 @@ ServiceManagementPrx ServiceManagementImpl::getServiceManagementPrx()
     return mImpl->mManagementPrx;
 }
 
+class CountedIsSupported : public IsSupportedCallback
+{
+public:
+    CountedIsSupported(const IsSupportedCallbackPtr& callback, int numVotes) :
+        callback(callback),
+        numVotes(numVotes)
+    {
+        if (numVotes == 0)
+        {
+            callback->result(false);
+            lg(Debug) << "  ...isSupported() = false\n";
+            this->callback = 0;
+        }
+    }
+
+    void result(bool result)
+    {
+        boost::lock_guard<boost::mutex> guard(mLock);
+        // any affirmitive vote means success
+        if (result && callback)
+        {
+            lg(Debug) << "  ...isSupported() = true\n";
+            callback->result(true);
+            callback = 0;
+        }
+        // all negative votes means failure
+        if (--numVotes == 0 && callback)
+        {
+            lg(Debug) << "  ...isSupported() = false\n";
+            callback->result(false);
+            callback = 0;
+        }
+    }
+
+private:
+    boost::mutex mLock;
+    IsSupportedCallbackPtr callback;
+    int numVotes;
+};
+
 /**
  * An internal function which is called by the service locator to perform a locator parameters comparison
  * at the service level.
  *
  * @param params A concrete class containing parameters describing the service that is trying to be found.
- *
- * @return A boolean value with true meaning the parameters are supported and false if not.
- *
  */
-bool ServiceManagementImpl::isSupported(const ServiceLocatorParamsPtr& params)
+void ServiceManagementImpl::isSupported(const ServiceLocatorParamsPtr& params, const IsSupportedCallbackPtr& callback)
 {
     boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
+    lg(Debug) << __PRETTY_FUNCTION__ << "(" << params->category << ")\n";
 
     /* If this service is suspended we can just skip the entire check and return false now, easy as pie */
     if (mImpl->mSuspended)
     {
-        return false;
+        lg(Debug) << "  ..." << __PRETTY_FUNCTION__ << "(" << params->category << ") = false\n";
+        callback->result(false);
+        return;
     }
 
+    IsSupportedCallbackPtr myCallback = new CountedIsSupported(
+        callback, mImpl->mSupportedLocatorParams.size());
+
     for (vector<ServiceLocatorParamsSpec>::iterator spec = mImpl->mSupportedLocatorParams.begin(); spec != mImpl->mSupportedLocatorParams.end(); ++spec)
     {
-        if ((*spec).isSupported(params) == true)
-        {
-            return true;
-        }
+        spec->isSupported(params, myCallback);
     }
-
-    return false;
 }
 
 std::string const &ServiceManagementImpl::getGuid() const
@@ -215,30 +253,31 @@ std::string const &ServiceManagementImpl::getGuid() const
  *
  * @param params A concrete class containing parameters describing the service that is trying to be found.
  *
- * @return A boolean value with true meaning the parameters are supported and false if not.
- *
  */
-bool ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params)
+void ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params, const IsSupportedCallbackPtr& callback)
 {
+    lg(Debug) << __PRETTY_FUNCTION__ << "(" << params->category << ")\n";
     // If no category is passed to us then the component doing the locate wants everything/anything, so give it to them
     if (params->category.empty())
     {
-        return true;
+        lg(Debug) << "  ..." << __PRETTY_FUNCTION__ << "(" << params->category << ") = true\n";
+        callback->result(true);
     }
-
     /* This is just a simple comparison that acts as a preliminary, and perhaps final, check */
-    if (mParams->category != params->category)
+    else if (mParams->category != params->category)
     {
-        return false;
+        lg(Debug) << "  ..." << __PRETTY_FUNCTION__ << "(" << params->category << ") = false\n";
+        callback->result(false);
     }
-
     /* If a comparator was provided then yield to it for a final yay or nay */
-    if (!mCompareGuid.empty())
+    else if (!mCompareGuid.empty())
     {
-        return mManagement->isSupported(mCompareGuid, params);
+        mManagement->isSupported(mCompareGuid, params, callback);
+    }
+    else
+    {
+        callback->result(true);
     }
-
-    return true;
 }
 
 /**
diff --git a/src/ServiceManagement.h b/src/ServiceManagement.h
index 1f30b10..a70ccec 100644
--- a/src/ServiceManagement.h
+++ b/src/ServiceManagement.h
@@ -47,7 +47,7 @@ public:
 
     Ice::ObjectPrx getService();
     AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx getServiceManagementPrx();
-    bool isSupported(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&);
+    void isSupported(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const IsSupportedCallbackPtr&);
     const std::string &getGuid() const;
     AsteriskSCF::Core::Discovery::V1::ServiceStatus getStatus() const;
 private:
diff --git a/test/TestComparatorBlocking.cpp b/test/TestComparatorBlocking.cpp
index f2621f4..2e0ccfd 100644
--- a/test/TestComparatorBlocking.cpp
+++ b/test/TestComparatorBlocking.cpp
@@ -78,12 +78,14 @@ public:
     {
         boost::unique_lock<boost::mutex> lock(mut);
         beenCalled = true;
+        cond.notify_one();
     }
 
     void locateFailureCB(const Ice::Exception& e)
     {
         boost::unique_lock<boost::mutex> lock(mut);
         beenCalled = true;
+        cond.notify_one();
     }
 
     bool waitForCallback(int waitTimeMillis)

commit 4cadd2f7e17aa2b01da0fd13cec7fefb615228f5
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 12:16:17 2010 -0600

    Disable collocation optimization.

diff --git a/config/test_component.config.in b/config/test_component.config.in
index b06ab7f..b793c27 100644
--- a/config/test_component.config.in
+++ b/config/test_component.config.in
@@ -1,6 +1,13 @@
 # This is a configuration file used in conjunction with the service discovery test driver
 
 #
+# Ice configuration
+#
+
+# Collocation is incompatible with AMI/AMD which sharing a communicator
+Ice.Default.CollocationOptimized=0
+
+#
 # icebox configuration
 #
 IceBox.InheritProperties=1
diff --git a/config/test_service_locator.config b/config/test_service_locator.config
index 8eb93ff..d058ee6 100644
--- a/config/test_service_locator.config
+++ b/config/test_service_locator.config
@@ -1,5 +1,17 @@
 # This is a configuration file used in conjunction with the service discovery test driver
 
+
+#
+# Ice configuration
+#
+
+# Collocation is incompatible with AMI/AMD which sharing a communicator
+Ice.Default.CollocationOptimized=0
+
+#
+# IceBox configuration
+#
+
 IceBox.InheritProperties=1
 IceBox.Service.ServiceDiscovery=service_locator:create
 

commit 94ab5e476840703f71784a2fd82dee124f9ab2f2
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 11:07:57 2010 -0600

    Formatting.

diff --git a/test/TestComparatorBlocking.cpp b/test/TestComparatorBlocking.cpp
index 615dd66..f2621f4 100644
--- a/test/TestComparatorBlocking.cpp
+++ b/test/TestComparatorBlocking.cpp
@@ -35,13 +35,17 @@ namespace
  * real-world(TM) scenario where this might happen is a dead server, where
  * TCP timeouts would cause comparator's to block for a minute or so.
  */
-class BlockingComparator : public ServiceLocatorParamsCompare {
+class BlockingComparator : public ServiceLocatorParamsCompare
+{
 public:
     BlockingComparator() : blocked(true), completed(false) {}
 
-    bool isSupported(const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const ::Ice::Current&) {
+    bool isSupported(const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&,
+        const ::Ice::Current&)
+    {
         boost::unique_lock<boost::mutex> lock(mut);
-        while (blocked) {
+        while (blocked)
+        {
             BOOST_TEST_MESSAGE("Blocking\n");
             cond.wait(lock);
             BOOST_TEST_MESSAGE("Unblocked\n");

commit dd4d3d7d801b7babf5cf24b66c88cb14869a1fae
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 10:33:56 2010 -0600

    Fixed unit test, but not in an optimal way.
    
    ServiceLocator's AMD operations spawn off new threads to allow
    concurrent discovery.  Ideally, we want to avoid new threads and
    simply use AMI to contact comparators.  But it's a step in the right
    direction.

diff --git a/src/ServiceLocator.cpp b/src/ServiceLocator.cpp
index d3d5d77..e16dc03 100644
--- a/src/ServiceLocator.cpp
+++ b/src/ServiceLocator.cpp
@@ -14,6 +14,8 @@
  * at the top of the source tree.
  */
 
+#include <boost/thread.hpp>
+
 #include <Ice/Ice.h>
 #include <IceStorm/IceStorm.h>
 #include <IceBox/IceBox.h>
@@ -75,20 +77,92 @@ private:
     ServiceLocatorManagementImpl* mLocatorServiceManagement;
 };
 
+class LocateThread
+{
+public:
+    LocateThread(const AMD_ServiceLocator_locatePtr& cb,
+        const ServiceLocatorParamsPtr& params,
+        ServiceLocatorManagementImpl* locatorServiceManagement) :
+        mCallback(cb),
+        mParams(params),
+        mLocatorServiceManagement(locatorServiceManagement)
+    {
+    }
+
+    void operator()()
+    {
+        try
+        {
+            lg(Info) << "locate(" << mParams->category << ")\n";
+            mCallback->ice_response(mLocatorServiceManagement->locate(mParams));
+            lg(Info) << "locate(" << mParams->category << "): complete\n";
+        }
+        catch(std::exception const &e)
+        {
+            lg(Info) << "locate(" << mParams->category << "): std::exception(" << e.what() << ")\n";
+            mCallback->ice_exception(e);
+        }
+        catch(...)
+        {
+            lg(Info) << "locate(" << mParams->category << "): bad::exception\n";
+            mCallback->ice_exception();
+        }
+    }
+private:
+    AMD_ServiceLocator_locatePtr mCallback;
+    ServiceLocatorParamsPtr mParams;
+    ServiceLocatorManagementImpl* mLocatorServiceManagement;
+};
+
+class LocateAllThread
+{
+public:
+    LocateAllThread(const AMD_ServiceLocator_locateAllPtr& cb,
+        const ServiceLocatorParamsPtr& params,
+        ServiceLocatorManagementImpl* locatorServiceManagement) :
+        mCallback(cb),
+        mParams(params),
+        mLocatorServiceManagement(locatorServiceManagement)
+    {
+    }
+
+    void operator()()
+    {
+        try
+        {
+            mCallback->ice_response(mLocatorServiceManagement->locateAll(mParams));
+        }
+catch(std::exception const &e)
+        {
+            lg(Info) << "locate(" << mParams->category << "): std::exception(" << e.what() << ")\n";
+            mCallback->ice_exception(e);
+        }
+        catch(...)
+        {
+            lg(Info) << "locate(" << mParams->category << "): bad::exception\n";
+            mCallback->ice_exception();
+        }
+    }
+private:
+    AMD_ServiceLocator_locateAllPtr mCallback;
+    ServiceLocatorParamsPtr mParams;
+    ServiceLocatorManagementImpl* mLocatorServiceManagement;
+};
+
 }
 
 void ServiceLocatorImpl::locate_async(const AMD_ServiceLocator_locatePtr& cb,
     const ServiceLocatorParamsPtr& params,
     const ::Ice::Current&)
 {
-    cb->ice_response(mLocatorServiceManagement->locate(params));
+    boost::thread(LocateThread(cb, params, mLocatorServiceManagement));
 }
 
 void ServiceLocatorImpl::locateAll_async(const AMD_ServiceLocator_locateAllPtr& cb,
     const ServiceLocatorParamsPtr& params,
     const ::Ice::Current&)
 {
-    cb->ice_response(mLocatorServiceManagement->locateAll(params));
+    boost::thread(LocateAllThread(cb, params, mLocatorServiceManagement));
 }
 
 void ServiceLocatorApp::start(const string& name, const Ice::CommunicatorPtr& communicator,

commit 169e47bf4b05b6a721b6473905bc5d76e0411b09
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 09:40:36 2010 -0600

    ServiceLocator now uses AMD to dispatch operations.
    
    This is the first step toward getting ServiceLocator to be resilient
    to non-responsive comparators.

diff --git a/src/ServiceLocator.cpp b/src/ServiceLocator.cpp
index b76772c..d3d5d77 100644
--- a/src/ServiceLocator.cpp
+++ b/src/ServiceLocator.cpp
@@ -63,8 +63,9 @@ class ServiceLocatorImpl : public ServiceLocator
 public:
     ServiceLocatorImpl(ServiceLocatorManagementImpl* LocatorServiceManagement) :
         mLocatorServiceManagement(LocatorServiceManagement) { };
-    Ice::ObjectPrx locate(const ServiceLocatorParamsPtr&, const Ice::Current&);
-    Ice::ObjectProxySeq locateAll(const ServiceLocatorParamsPtr&, const Ice::Current&);
+
+    void locate_async(const ::AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locatePtr&, const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const ::Ice::Current&);
+    void locateAll_async(const ::AsteriskSCF::Core::Discovery::V1::AMD_ServiceLocator_locateAllPtr&, const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const ::Ice::Current&);
 private:
     /**
      * A pointer to the ServiceManagement implementation as that is where everything is
@@ -76,26 +77,18 @@ private:
 
 }
 
-/**
- * Implementation of the locate method as defined in service_locator.ice
- */
-Ice::ObjectPrx ServiceLocatorImpl::locate(const ServiceLocatorParamsPtr& params,
-    const Ice::Current&)
+void ServiceLocatorImpl::locate_async(const AMD_ServiceLocator_locatePtr& cb,
+    const ServiceLocatorParamsPtr& params,
+    const ::Ice::Current&)
 {
-    /* This API call forwards into the management implementation, it is separated to
-     * provide a level of security. */
-    return mLocatorServiceManagement->locate(params);
+    cb->ice_response(mLocatorServiceManagement->locate(params));
 }
 
-/**
- * Implementation of the locateAll method as defined in service_locator.ice
- */
-Ice::ObjectProxySeq ServiceLocatorImpl::locateAll(const ServiceLocatorParamsPtr& params,
-    const Ice::Current&)
+void ServiceLocatorImpl::locateAll_async(const AMD_ServiceLocator_locateAllPtr& cb,
+    const ServiceLocatorParamsPtr& params,
+    const ::Ice::Current&)
 {
-    /* This API call forwards into the management implementation, it is separated to
-     * provide a level of security. */
-    return mLocatorServiceManagement->locateAll(params);
+    cb->ice_response(mLocatorServiceManagement->locateAll(params));
 }
 
 void ServiceLocatorApp::start(const string& name, const Ice::CommunicatorPtr& communicator,

commit f0ff0f1b9a5de9eb233d8e70ac68c39184b88eac
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 09:21:02 2010 -0600

    Improved unit test for TestComparatorBlocking.
    
    * Initialize fixture using initializer list
    * Wait longer for second discovery
    * More readable assertions

diff --git a/test/TestComparatorBlocking.cpp b/test/TestComparatorBlocking.cpp
index b63c5a3..615dd66 100644
--- a/test/TestComparatorBlocking.cpp
+++ b/test/TestComparatorBlocking.cpp
@@ -37,17 +37,17 @@ namespace
  */
 class BlockingComparator : public ServiceLocatorParamsCompare {
 public:
-    BlockingComparator() : blocked(true), beenCalled(false) {}
+    BlockingComparator() : blocked(true), completed(false) {}
 
     bool isSupported(const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const ::Ice::Current&) {
         boost::unique_lock<boost::mutex> lock(mut);
         while (blocked) {
-            std::clog << "Blocking\n";
+            BOOST_TEST_MESSAGE("Blocking\n");
             cond.wait(lock);
-            std::clog << "Unblocked\n";
+            BOOST_TEST_MESSAGE("Unblocked\n");
         }
         blocked = true;
-        beenCalled = true;
+        completed = true;
         return true;
     }
 
@@ -58,10 +58,12 @@ public:
         cond.notify_one();
     }
 
+    bool hasCompleted() const { return completed; }
+
 private:
     boost::condition_variable cond;
     boost::mutex mut;
-    bool blocked, beenCalled;
+    bool blocked, completed;
 };
 
 class BlockingCallback : public IceUtil::Shared
@@ -102,42 +104,55 @@ typedef IceUtil::Handle<BlockingCallback> BlockingCallbackPtr;
 class Fixture
 {
 public:
-    Fixture()
+    Fixture() :
+        // create an register the blocker
+        blockerCommunicator(Ice::initialize()),
+        blocker(new BlockingComparator()),
+        blockerAdapter(blockerCommunicator->createObjectAdapterWithEndpoints("blocker", "default")),
+        blockerProxy(ServiceLocatorParamsComparePrx::checkedCast(blockerAdapter->addWithUUID(blocker))),
+        // get references to discovery on different communictor
+        discoveryCommunicator(Ice::initialize()),
+        management(ServiceLocatorManagementPrx::checkedCast(
+                discoveryCommunicator->stringToProxy("LocatorServiceManagement:tcp -p 4422"))),
+        discovery(ServiceLocatorPrx::checkedCast(
+                discoveryCommunicator->stringToProxy("LocatorService:tcp -p 4411"))),
+        proxy(management->addService(management, "self")),
+        params(new ServiceLocatorParams())
     {
-        communicator = Ice::initialize();
-        blocker = new BlockingComparator();
-        adapter = communicator->createObjectAdapterWithEndpoints("blocker", "default");
-        blockerProxy = ServiceLocatorParamsComparePrx::checkedCast(adapter->addWithUUID(blocker));
         BOOST_REQUIRE(blockerProxy != 0);
-
-        management = ServiceLocatorManagementPrx::checkedCast(
-            communicator->stringToProxy("LocatorServiceManagement:tcp -p 4422"));
         BOOST_REQUIRE(management != 0);
-
-        discovery = ServiceLocatorPrx::checkedCast(
-            communicator->stringToProxy("LocatorService:tcp -p 4411"));
         BOOST_REQUIRE(discovery != 0);
 
-        adapter->activate();
+        blockerAdapter->activate();
         management->addCompare("blocker", blockerProxy);
+
+        params->category = "self";
+        proxy->addLocatorParams(params, "blocker");
     }
 
     ~Fixture()
     {
         blocker->unblock();
+        proxy->unregister();
         management->removeCompare("blocker");
-        adapter->deactivate();
-        communicator->shutdown();
-        communicator->waitForShutdown();
+        blockerCommunicator->shutdown();
+        blockerCommunicator->waitForShutdown();
+
+        discoveryCommunicator->shutdown();
+        discoveryCommunicator->waitForShutdown();
     }
 
 protected:
-    Ice::CommunicatorPtr communicator;
+    Ice::CommunicatorPtr blockerCommunicator;
     BlockingComparatorPtr blocker;
-    Ice::ObjectAdapterPtr adapter;
+    Ice::ObjectAdapterPtr blockerAdapter;
     ServiceLocatorParamsComparePrx blockerProxy;
+
+    Ice::CommunicatorPtr discoveryCommunicator;
     ServiceLocatorManagementPrx management;
     ServiceLocatorPrx discovery;
+    ServiceManagementPrx proxy;
+    ServiceLocatorParamsPtr params;
 };
 
 }
@@ -174,15 +189,11 @@ BOOST_AUTO_TEST_CASE(testNonBlocking)
 
 BOOST_AUTO_TEST_CASE(testBlocking)
 {
-    ServiceManagementPrx proxy = management->addService(management, "self");
-    ServiceLocatorParamsPtr params = new ServiceLocatorParams();
-    params->category = "self";
-    proxy->addLocatorParams(params, "blocker");
-
     Ice::AsyncResultPtr asyncDiscovered = discovery->begin_locate(params);
     asyncDiscovered->waitForSent();
     // discovery has now called our blocker comparator, which is not returning
 
+    // try to locate something else while blocker is blocking
     ServiceLocatorParamsPtr dne = new ServiceLocatorParams();
     dne->category = "dne";
 
@@ -194,8 +205,13 @@ BOOST_AUTO_TEST_CASE(testBlocking)
 
     discovery->begin_locate(dne, undiscoveredCB);
 
-    bool wasCalled = callback->waitForCallback(1000);
-    BOOST_REQUIRE(wasCalled);
+    bool secondDiscoveryCompleted = callback->waitForCallback(10000);
+    BOOST_REQUIRE(secondDiscoveryCompleted);
+    BOOST_REQUIRE(!blocker->hasCompleted());
+
+    blocker->unblock();
+    asyncDiscovered->waitForCompleted();
+    BOOST_REQUIRE(blocker->hasCompleted());
 }
 
 BOOST_AUTO_TEST_SUITE_END()

commit 7bb5853cb3cc3b5913c75be61bafdb51a6cfc39d
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 00:37:47 2010 -0600

    Added unit tests for AMD/AMI.

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e868a5a..4176ec2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -11,8 +11,9 @@ asterisk_scf_component_init(service_locator_test CXX)
 asterisk_scf_component_add_slice(service_locator_test ServiceLocatorIf)
 asterisk_scf_component_add_slice(service_locator_test ServiceLocatorEventsIf)
 asterisk_scf_component_add_file(service_locator_test TestServiceLocator.cpp)
+asterisk_scf_component_add_file(service_locator_test TestComparatorBlocking.cpp)
 asterisk_scf_component_add_ice_libraries(service_locator_test IceStorm)
-asterisk_scf_component_add_boost_libraries(service_locator_test unit_test_framework)
+asterisk_scf_component_add_boost_libraries(service_locator_test unit_test_framework thread)
 asterisk_scf_component_build_icebox(service_locator_test)
 #asterisk_scf_component_install(service_locator_test RUNTIME bin "Service Locator Test Driver." Core)
 
diff --git a/test/TestComparatorBlocking.cpp b/test/TestComparatorBlocking.cpp
new file mode 100644
index 0000000..b63c5a3
--- /dev/null
+++ b/test/TestComparatorBlocking.cpp
@@ -0,0 +1,201 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#define BOOST_TEST_DYN_LINK
+
+#include <iostream>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/debug.hpp>
+#include <boost/thread.hpp>
+
+#include <Ice/Ice.h>
+
+#include "Core/Discovery/ServiceLocatorIf.h"
+
+using namespace AsteriskSCF::Core::Discovery::V1;
+
+namespace
+{
+/**
+ * A comparator which simply hangs until unblock is called.  The most likely
+ * real-world(TM) scenario where this might happen is a dead server, where
+ * TCP timeouts would cause comparator's to block for a minute or so.
+ */
+class BlockingComparator : public ServiceLocatorParamsCompare {
+public:
+    BlockingComparator() : blocked(true), beenCalled(false) {}
+
+    bool isSupported(const ::AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr&, const ::Ice::Current&) {
+        boost::unique_lock<boost::mutex> lock(mut);
+        while (blocked) {
+            std::clog << "Blocking\n";
+            cond.wait(lock);
+            std::clog << "Unblocked\n";
+        }
+        blocked = true;
+        beenCalled = true;
+        return true;
+    }
+
+    void unblock()
+    {
+        boost::unique_lock<boost::mutex> lock(mut);
+        blocked = false;
+        cond.notify_one();
+    }
+
+private:
+    boost::condition_variable cond;
+    boost::mutex mut;
+    bool blocked, beenCalled;
+};
+
+class BlockingCallback : public IceUtil::Shared
+{
+public:
+    BlockingCallback() : beenCalled(false) {}
+    void locateCB(const Ice::ObjectPrx&located)
+    {
+        boost::unique_lock<boost::mutex> lock(mut);
+        beenCalled = true;
+    }
+
+    void locateFailureCB(const Ice::Exception& e)
+    {
+        boost::unique_lock<boost::mutex> lock(mut);
+        beenCalled = true;
+    }
+
+    bool waitForCallback(int waitTimeMillis)
+    {
+        boost::unique_lock<boost::mutex> lock(mut);
+        if (!beenCalled)
+        {
+            cond.timed_wait(lock, boost::posix_time::millisec(waitTimeMillis));
+        }
+        return beenCalled;
+    }
+
+private:
+    boost::condition_variable cond;
+    boost::mutex mut;
+    bool beenCalled;
+};
+
+typedef IceUtil::Handle<BlockingComparator> BlockingComparatorPtr;
+typedef IceUtil::Handle<BlockingCallback> BlockingCallbackPtr;
+
+class Fixture
+{
+public:
+    Fixture()
+    {
+        communicator = Ice::initialize();
+        blocker = new BlockingComparator();
+        adapter = communicator->createObjectAdapterWithEndpoints("blocker", "default");
+        blockerProxy = ServiceLocatorParamsComparePrx::checkedCast(adapter->addWithUUID(blocker));
+        BOOST_REQUIRE(blockerProxy != 0);
+
+        management = ServiceLocatorManagementPrx::checkedCast(
+            communicator->stringToProxy("LocatorServiceManagement:tcp -p 4422"));
+        BOOST_REQUIRE(management != 0);
+
+        discovery = ServiceLocatorPrx::checkedCast(
+            communicator->stringToProxy("LocatorService:tcp -p 4411"));
+        BOOST_REQUIRE(discovery != 0);
+
+        adapter->activate();
+        management->addCompare("blocker", blockerProxy);
+    }
+
+    ~Fixture()
+    {
+        blocker->unblock();
+        management->removeCompare("blocker");
+        adapter->deactivate();
+        communicator->shutdown();
+        communicator->waitForShutdown();
+    }
+
+protected:
+    Ice::CommunicatorPtr communicator;
+    BlockingComparatorPtr blocker;
+    Ice::ObjectAdapterPtr adapter;
+    ServiceLocatorParamsComparePrx blockerProxy;
+    ServiceLocatorManagementPrx management;
+    ServiceLocatorPrx discovery;
+};
+
+}
+
+BOOST_FIXTURE_TEST_SUITE(TestComparatorBlocking, Fixture)
+
+/**
+ * Pretty much just tests the test; ensuring blocker works as expected.
+ */
+BOOST_AUTO_TEST_CASE(testNonBlocking)
+{
+    ServiceManagementPrx proxy = management->addService(management, "self");
+    ServiceLocatorParamsPtr params = new ServiceLocatorParams();
+    params->category = "self";
+    proxy->addLocatorParams(params, "blocker");
+
+    // unblock, to test our test logic
+    blocker->unblock();
+
+    Ice::ObjectPrx discovered = discovery->locate(params);
+    BOOST_REQUIRE(discovered == management);
+
+    ServiceLocatorParamsPtr dne = new ServiceLocatorParams();
+    dne->category = "dne";
+
+    try
+    {
+        Ice::ObjectPrx undiscovered = discovery->locate(dne);
+        BOOST_FAIL("Should not have found dne");
+    } catch (ServiceNotFound const &expected) {
+        // expected
+    }
+}
+
+BOOST_AUTO_TEST_CASE(testBlocking)
+{
+    ServiceManagementPrx proxy = management->addService(management, "self");
+    ServiceLocatorParamsPtr params = new ServiceLocatorParams();
+    params->category = "self";
+    proxy->addLocatorParams(params, "blocker");
+
+    Ice::AsyncResultPtr asyncDiscovered = discovery->begin_locate(params);
+    asyncDiscovered->waitForSent();
+    // discovery has now called our blocker comparator, which is not returning
+
+    ServiceLocatorParamsPtr dne = new ServiceLocatorParams();
+    dne->category = "dne";
+
+    BlockingCallbackPtr callback = new BlockingCallback();
+
+    Callback_ServiceLocator_locatePtr undiscoveredCB =
+        newCallback_ServiceLocator_locate(callback,
+            &BlockingCallback::locateCB, &BlockingCallback::locateFailureCB);
+
+    discovery->begin_locate(dne, undiscoveredCB);
+
+    bool wasCalled = callback->waitForCallback(1000);
+    BOOST_REQUIRE(wasCalled);
+}
+
+BOOST_AUTO_TEST_SUITE_END()

commit 9bc9f9a355ad8847bceb4b496e75b938001e2d94
Author: David M. Lee <dlee at digium.com>
Date:   Fri Nov 19 00:37:04 2010 -0600

    Additional logging.

diff --git a/src/ServiceLocatorManagement.cpp b/src/ServiceLocatorManagement.cpp
index e48dbd7..fdef99d 100644
--- a/src/ServiceLocatorManagement.cpp
+++ b/src/ServiceLocatorManagement.cpp
... 18 lines suppressed ...


-- 
asterisk-scf/release/servicediscovery.git



More information about the asterisk-scf-commits mailing list