[asterisk-scf-commits] asterisk-scf/release/ice-util-cpp.git branch "master" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon Aug 8 03:06:28 CDT 2011


branch "master" has been updated
       via  94660b642445ea1bf456d1106276d154939f462e (commit)
      from  acb89ff28ec27b52e11c8b3376178f3f0ca601df (commit)

Summary of changes:
 include/AsteriskSCF/Component/Component.h          |  326 ++++++
 include/AsteriskSCF/Component/TestContext.h        |   96 ++
 .../Discovery/LocatorRegistrationWrapper.h         |   59 +-
 include/AsteriskSCF/Discovery/SmartProxy.h         |   84 ++-
 include/AsteriskSCF/Helpers/PropertyHelper.h       |   40 +
 .../AsteriskSCF/Replication/ReplicationContext.h   |   77 ++
 src/CMakeLists.txt                                 |    2 +
 src/Component/CMakeLists.txt                       |    2 +
 src/Component/Component.cpp                        | 1053 ++++++++++++++++++++
 src/Component/TestContext.cpp                      |  102 ++
 src/Replication/CMakeLists.txt                     |    1 +
 src/Replication/ReplicationContext.cpp             |   59 ++
 test/CMakeLists.txt                                |    1 +
 test/Component/CMakeLists.txt                      |   25 +
 test/Component/ComponentTest.cpp                   |  287 ++++++
 test/Component/ComponentTestIf.ice                 |   55 +
 test/Component/MockComponent.cpp                   |  169 ++++
 test/Component/component-base-test.conf            |   86 ++
 .../LocatorRegistrationTest.cpp                    |   12 +-
 test/PropertyHelper/PropertyHelperTest.cpp         |   24 +
 20 files changed, 2538 insertions(+), 22 deletions(-)
 create mode 100644 include/AsteriskSCF/Component/Component.h
 create mode 100644 include/AsteriskSCF/Component/TestContext.h
 create mode 100644 include/AsteriskSCF/Replication/ReplicationContext.h
 create mode 100644 src/Component/CMakeLists.txt
 create mode 100644 src/Component/Component.cpp
 create mode 100644 src/Component/TestContext.cpp
 create mode 100644 src/Replication/CMakeLists.txt
 create mode 100644 src/Replication/ReplicationContext.cpp
 create mode 100644 test/Component/CMakeLists.txt
 create mode 100644 test/Component/ComponentTest.cpp
 create mode 100644 test/Component/ComponentTestIf.ice
 create mode 100644 test/Component/MockComponent.cpp
 create mode 100644 test/Component/component-base-test.conf


- Log -----------------------------------------------------------------
commit 94660b642445ea1bf456d1106276d154939f462e
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Mon Aug 8 03:06:04 2011 -0500

    Changes to support a base Component class.

diff --git a/include/AsteriskSCF/Component/Component.h b/include/AsteriskSCF/Component/Component.h
new file mode 100644
index 0000000..5377bc8
--- /dev/null
+++ b/include/AsteriskSCF/Component/Component.h
@@ -0,0 +1,326 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, 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.
+ */
+#pragma once
+
+#include <Ice/Ice.h>
+#include <IceBox/IceBox.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Replication/ReplicationContext.h>
+#include <AsteriskSCF/Component/TestContext.h>
+#include <AsteriskSCF/Discovery/LocatorRegistrationWrapper.h>
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+#include <AsteriskSCF/System/Component/ReplicaIf.h>
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+class ASTSCF_DLL_EXPORT Component : public IceBox::Service
+{
+public:
+    Component(const AsteriskSCF::System::Logging::Logger& logger,
+              const std::string& componentDiscoveryCategory);
+
+    /////////////////////////////////////////////////////////////////////
+    // Support for ComponentService interface.
+    void suspended();
+    void resumed();
+    void shutdown();
+
+    /////////////////////////////////////////////////////////////////////
+    // Support for ComponentTest interface.
+    void setTestMode(const std::string& mode);
+    void setTestModeWithArgs(const std::string& mode,
+                                     const AsteriskSCF::System::Component::V1::ComponentTestParamSeq& args);
+    void clearTestModes();
+    void clearTestMode(const std::string& mode);
+
+    ////////////////////////////////
+    // Support for Replica control interface.
+    bool isActive();
+    void activated();
+    void standby();
+
+protected:
+   
+    /////////////////////////////////////////////////////////////////////
+    // Notification for some of 
+    // the component events. 
+    virtual void onPreInitialize() {}
+    virtual void onPostInitialize() {}
+    virtual void onSuspend() {}
+    virtual void onResume() {}
+    virtual void onStop() {}
+    virtual void onStart() {}
+    virtual void onActivated() {}
+    virtual void onStandby() {}
+    virtual void onRegisterPrimaryServices() {}
+    virtual void onRegisterBackplaneServices() {}
+    virtual void onUnregisterPrimaryServices() {}
+    virtual void onUnregisterBackplaneServices() {}
+    virtual void onSuspendPrimaryServices() {}
+    virtual void onSuspendBackplaneServices() {}
+    virtual void onUnsuspendPrimaryServices() {}
+    virtual void onUnsuspendBackplaneServices() {}
+
+    /////////////////////////////////////////////////////////////////////
+    // Every component must provide custom
+    // implementations of these replication
+    // operations. 
+    virtual void createReplicationStateListeners() = 0;
+
+    /** 
+     * Unregister as a listener to our state replicator. 
+     * A component in active mode doesn't neeed to listen to
+     * state replication data. 
+     */
+    virtual void stopListeningToStateReplicators() = 0;
+
+    /** 
+     * Register as a listener to our state replicator. 
+     * A component in standby mode will do this to monitor state changes
+     * being sent from an active component. 
+     */
+    virtual void listenToStateReplicators() = 0;
+
+    /** 
+     * A factory method. 
+     * Allows subclasses to easily extend the ReplicationContext if needed. 
+     */
+    virtual AsteriskSCF::Replication::ReplicationContextPtr createReplicationContext(
+           AsteriskSCF::Replication::ReplicationStateType state);
+
+    /////////////////////////////////////////////////////////////////////
+    // Operations called by the initialize() method. The initialize() method
+    // implements the Template Method pattern. These methods are called in 
+    // the order declared below. If you override any of the default implementations,
+    // you probably want to call the default implementation from your override. 
+
+    /**
+     * Verifies the configured parameters in the Ice config file meet
+     * minimum expectations, particularly thread pool sizes. If the do not, 
+     * this method alters the configuration and logs the changes.
+     */
+    virtual void verifyProperties();
+
+    /**
+     * Creates the primary service adapter and the backplane adapters. 
+     * If you need other adapter you can override this, but be sure to 
+     * call the default implementation from you override. 
+     */
+    virtual void createAdapters();
+
+    /** 
+     * Activates the primary and backplane adapters. 
+     */
+    virtual void activateAdapters();
+
+    /**
+     * Acquires references to the Service Locator proxies that can be accessed
+     * with the getServiceLocatorManagement() and getServiceLocator() accessors. 
+     * The adapters must be activated prior to calling, which should always be
+     * the case due to the flow of the initialize() template method. 
+     */
+    virtual void initServiceLocatorProxies();
+
+    /**
+     * Creates a replication context using the factory method
+     * createReplicationContext(). Override the factory method if 
+     * you want to create a custom replication context. 
+     * Note: Custom context must derive from AsteriskSCF::Replication::ReplicationContext.
+     */
+    virtual void initReplicationContext();
+
+    /**
+     * Creates a test context for component to use to detemine if it
+     * has test modes enabled. Support for test modes is optional. 
+     */
+    virtual void initTestContext();
+
+    /**
+     * Create the logger. The generic implementation creates an IceLogger. 
+     */
+    virtual void configureLogger();
+
+    /**
+     * Create all services to be associated with the primary service adapter. 
+     * Note: This is a REQUIRED override. 
+     */
+    virtual void createPrimaryServices() = 0;
+
+    /**
+     * Create any services to be associated with the primary service adapter. 
+     * If you override this operation, you should call the default implementation. 
+     */
+    virtual void createBackplaneServices();
+
+    /**
+     * A required override for the component to locate and cache any 
+     * proxies to remote services that it needs to operate. 
+     * Note: This is a REQUIRED override. 
+     */
+    virtual void findRemoteServices() = 0;
+
+
+    /////////////////////////////////////////////////////////////////////
+    // Remote service registration operations. 
+    // Components are usually discovered via the Service Locator,
+    // but some components may need to push proxies directly to other
+    // components. These operations assume you should only be registered
+    // when you're active. 
+
+    /**
+     * Register this component's proxies with some service
+     * (other than the ServiceLocator).
+     */
+    virtual void registerWithRemoteServices() {}
+
+    /**
+     * Unregister this component's proxies from service
+     * (other than the ServiceLocator).
+     */
+    virtual void unregisterFromRemoteServices() {}
+
+    /////////////////////////////////////////////////////////////////////
+    // Service locator operations
+
+    /**
+     * Helper that caches the service references for the primary adapter.
+     */
+    void managePrimaryService(const AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr& service);
+
+    /**
+     * Helper that caches the service references for the backplane adapter. 
+     */
+    void manageBackplaneService(const AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr& service);
+    
+    /** 
+     * Helper that wraps a service for registration. 
+     */
+    AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr 
+        wrapServiceForRegistration(const Ice::ObjectPrx& proxy, 
+                                   const std::string& category,
+                                   const std::string& service,
+                                   const std::string& id) const;
+
+    /**
+     * Overload that uses the <adapterName>.ServiceName and <adapterName> as 
+     * the values for the service and id. 
+     */
+    AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr
+        wrapServiceForRegistration(const Ice::ObjectPrx& proxy, 
+                 const std::string& category) const;
+
+    /**
+     * The derived component is expected to wrap each 
+     * primary adapter service that should be 
+     * registered with the Service Locator. Refer to
+     * documentation. 
+     */
+    virtual void preparePrimaryServicesForDiscovery() = 0;
+    void registerPrimaryServices();
+    void unregisterPrimaryServices();
+    void suspendPrimaryServices();
+    void unsuspendPrimaryServices();
+
+    /**
+     * The derived component should override this operation only if it wishes
+     * register its own backplane services. If this method is overridden, 
+     * this class's implmentation should be called from the override. 
+     */
+    virtual void prepareBackplaneServicesForDiscovery();
+    void registerBackplaneServices();
+    void unregisterBackplaneServices();
+    void suspendBackplaneServices();
+    void unsuspendBackplaneServices();
+
+    /////////////////////////////////////////////////////////////////////
+    // Accessors to state. 
+    const AsteriskSCF::Replication::ReplicationContextPtr& getReplicationContext() const {return mReplicationContext;}
+    const AsteriskSCF::Component::TestContextPtr& getTestContext() const {return mTestContext;}
+    const std::string& getName() const {return mName;}
+    const std::string& getServiceName() const {return mServiceName;}
+    const Ice::CommunicatorPtr& getCommunicator() const {return mCommunicator;}
+    const Ice::StringSeq& getArgs() const {return mArgs;}
+    const AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagementPrx& getServiceLocatorManagement() const {return mServiceLocatorManagement;}
+    const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx&  getServiceLocator() const {return mServiceLocator;}
+    const Ice::ObjectAdapterPtr& getServiceAdapter() const {return mServiceAdapter;}
+    const Ice::ObjectAdapterPtr& getBackplaneAdapter() const {return mBackplaneAdapter;}
+    std::string getServiceLocatorManagementProperty() const;
+
+    // Allow setting an alternative communicator. 
+    // This should only be done in onPreInitialize() override, or 
+    // things may already be using the IceBox-provided communicator. 
+    void setCommunicator(const Ice::CommunicatorPtr& communicator) {mCommunicator = communicator;}
+
+    // State data
+    AsteriskSCF::System::Logging::Logger mLogger;
+
+private:
+    void initialize();
+    void suspendService(bool shuttingDown);
+
+    /////////////////////////////////////////////////////////////////////
+    // Overrides for IceBox::Service
+    void start(const std::string& name, 
+               const Ice::CommunicatorPtr& communicator, 
+               const Ice::StringSeq& args);
+    void stop();
+
+    /////////////////////////////////////////////////////////////////////
+    // State data
+
+    bool mInitialized;
+    bool mRunning;
+    bool mPublishTestInterface;
+
+    std::string mComponentDiscoveryCategory;
+
+    std::string mName;
+    std::string mServiceName;
+    Ice::CommunicatorPtr mCommunicator;
+    Ice::StringSeq mArgs;
+
+    AsteriskSCF::System::Component::V1::ComponentServicePtr mComponentService;
+    AsteriskSCF::System::Component::V1::ComponentServicePrx mComponentServicePrx;
+    AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr mComponentRegistration;
+
+    AsteriskSCF::System::Component::V1::ReplicaPtr mReplica;
+    AsteriskSCF::System::Component::V1::ReplicaPrx mReplicaPrx;
+    AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr mReplicaRegistration;
+
+    AsteriskSCF::System::Component::V1::ComponentTestPtr mComponentTest;
+    AsteriskSCF::System::Component::V1::ComponentTestPrx mComponentTestPrx;
+
+    AsteriskSCF::Replication::ReplicationContextPtr mReplicationContext;
+    AsteriskSCF::Component::TestContextPtr mTestContext;
+
+    Ice::ObjectAdapterPtr mServiceAdapter;
+    Ice::ObjectAdapterPtr mBackplaneAdapter;
+
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagementPrx mServiceLocatorManagement;
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx mServiceLocator;
+
+    std::vector<AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr> mPrimaryServices;
+    std::vector<AsteriskSCF::Discovery::LocatorRegistrationWrapperPtr> mBackplaneServices;
+};
+
+
+} // end Component
+} // end AsteriskSCF
diff --git a/include/AsteriskSCF/Component/TestContext.h b/include/AsteriskSCF/Component/TestContext.h
new file mode 100644
index 0000000..0934abf
--- /dev/null
+++ b/include/AsteriskSCF/Component/TestContext.h
@@ -0,0 +1,96 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, 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.
+ */
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+class ASTSCF_DLL_EXPORT InvalidTestMode : public std::exception
+{
+public:
+    InvalidTestMode(const std::string& mode)
+    {
+        mMsg = "Invalid Test Mode. Mode " + mode + " is not set.";
+    }
+
+    ~InvalidTestMode() throw() {};
+
+    virtual const char* what() const throw()
+    {
+        return mMsg.c_str();
+    }
+
+private:
+    std::string mMsg;
+};
+
+/** 
+ * This class provides the component's classes with the context 
+ * needed for testing.
+ */
+class ASTSCF_DLL_EXPORT TestContext 
+{
+public:
+    TestContext() ;
+
+    /**
+     * Indicates whether a test mode with given name
+     * has been set. 
+     * @param mode The name of the mode to query.
+     */
+    bool hasTestMode(const std::string& mode);
+   
+    /** 
+     * Gets the paramters to for the test mode. 
+     * If the mode hasn't been set, throws InvalidTestMode. 
+     */
+    AsteriskSCF::System::Component::V1::ComponentTestParamSeq 
+         getTestModeParams(const std::string& mode);
+
+    /**
+     * Sets a test mode. 
+     */
+    void setTestMode(const std::string& mode);
+    
+    /**
+     * Sets a current test mode with parameters. 
+     */
+    void setTestMode(const std::string& mode, 
+         const AsteriskSCF::System::Component::V1::ComponentTestParamSeq& params);
+
+    /**
+     * Clears a testing mode.
+     */
+    void clearTestMode(const std::string& mode);
+
+    /**
+     * Clears testing mode.
+     */
+    void clearAllTestModes();
+
+private:
+    std::map<std::string, AsteriskSCF::System::Component::V1::ComponentTestParamSeq> mTestModeMap;
+    boost::shared_mutex mLock;
+};
+typedef boost::shared_ptr<TestContext> TestContextPtr;
+
+} // end Component
+} // end AsteriskSCF
diff --git a/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h b/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h
index ca8e81a..2cef1fa 100644
--- a/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h
+++ b/include/AsteriskSCF/Discovery/LocatorRegistrationWrapper.h
@@ -27,14 +27,13 @@ namespace Discovery
 
 /**
  * 
- * Helper template for services that need to be registered with the locator service. If the service may not
+ * Helper class for services that need to be registered with the locator service. If the service is not
  * immediately available, the RegisterThread can be used to continue to try and register the service.
  *
  * TODO: It might be handy to add some "termination conditions" so it doesn't simply wait forever.
  *
  **/
-template <class T>   
-class LocatorRegistrationWrapper : public IceUtil::Shared
+class ASTSCF_DLL_EXPORT LocatorRegistrationWrapper : public IceUtil::Shared
 {
 public:
 
@@ -42,10 +41,12 @@ public:
      * Normally, I avoid default args, but you can't really implement one constructor in terms of another
      * so it's less maintenance overhead to have the single constructor with the defaults.
      **/
-    LocatorRegistrationWrapper(const Ice::CommunicatorPtr& communicator, const std::string& proxyString,
-            const T& service, const std::string& name,
-            const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& params, 
-            const std::string& comparatorGUID = "") :
+    LocatorRegistrationWrapper(const Ice::CommunicatorPtr& communicator, 
+                               const std::string& proxyString,
+                               const Ice::ObjectPrx& service, 
+                               const std::string& name,
+                               const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& params, 
+                               const std::string& comparatorGUID = "") :
         mCommunicator(communicator),
         mProxyString(proxyString),
         mService(service),
@@ -97,6 +98,35 @@ public:
         mServiceManagement->unregister();
     }
 
+    void suspend()
+    {
+        {
+            IceUtil::Mutex::Lock lock(mLock);
+            if(!mServiceManagement)
+            {
+                return;
+            }
+        }
+        mServiceManagement->suspend();
+    }
+
+    void unsuspend()
+    {
+        {
+            IceUtil::Mutex::Lock lock(mLock);
+            if(!mServiceManagement)
+            {
+                return;
+            }
+        }
+        mServiceManagement->unsuspend();
+    }
+
+    AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx getServiceMangement()
+    {
+        return mServiceManagement;
+    }
+
 private:
 
     //
@@ -106,30 +136,30 @@ private:
     IceUtil::Mutex mLock;
     Ice::CommunicatorPtr mCommunicator;
     std::string mProxyString;
-    T mService;
+    Ice::ObjectPrx mService;
     std::string mName;
     AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr mParameters;
     AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx mServiceManagement;
     std::string mComparatorGUID;
 };
+typedef ASTSCF_DLL_EXPORT IceUtil::Handle<LocatorRegistrationWrapper> LocatorRegistrationWrapperPtr;
 
 /**
 * This thread takes care of registering the registration wrapper instance if the service discovery components are
  * unavailable during startup.
  **/
-template <class T>
-class RegisterThread : public IceUtil::Thread
+class ASTSCF_DLL_EXPORT RegisterThread : public IceUtil::Thread
 {
 public:
-    RegisterThread(const IceUtil::Handle<LocatorRegistrationWrapper<T> >& registration,
-            const IceUtil::Time& retryInterval) :
+    RegisterThread(const LocatorRegistrationWrapperPtr& registration,
+                   const IceUtil::Time& retryInterval) :
         mRegistration(registration),
         mRetryInterval(retryInterval),
         mStopped(false)
     {
     }
 
-    RegisterThread(const IceUtil::Handle<LocatorRegistrationWrapper<T> >& registration) :
+    RegisterThread(const LocatorRegistrationWrapperPtr& registration) :
         mRegistration(registration),
         mRetryInterval(IceUtil::Time::seconds(15)),
         mStopped(false)
@@ -167,10 +197,11 @@ public:
 
 private:
     IceUtil::Monitor<IceUtil::Mutex> mMonitor;
-    IceUtil::Handle<LocatorRegistrationWrapper<T> > mRegistration;
+    LocatorRegistrationWrapperPtr mRegistration;
     IceUtil::Time mRetryInterval;
     bool mStopped;
 };
+typedef ASTSCF_DLL_EXPORT IceUtil::Handle<RegisterThread> RegisterThreadPtr;
 
 } /* End of namespace Discovery */
 
diff --git a/include/AsteriskSCF/Discovery/SmartProxy.h b/include/AsteriskSCF/Discovery/SmartProxy.h
index 68a781c..ed7e44f 100644
--- a/include/AsteriskSCF/Discovery/SmartProxy.h
+++ b/include/AsteriskSCF/Discovery/SmartProxy.h
@@ -44,7 +44,7 @@ template <class P>
 class SmartProxy
 {
 public:
-    SmartProxy() : mServiceLocator(0), mLocatorParams(0), mLogger(0) {}
+    SmartProxy() : mServiceLocator(0), mLocatorParams(0), mLogger(0), mSupportsOneWay(false) {}
 
     SmartProxy(const SmartProxy &rhs)
     {
@@ -55,7 +55,8 @@ public:
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& locator,
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& params,
         AsteriskSCF::System::Logging::Logger const &lg)
-        :  mServiceLocator(locator), mLocatorParams(params), mLogger(&lg)
+        :  mServiceLocator(locator), mLocatorParams(params), mLogger(&lg),
+           mSupportsOneWay(false)
     {
         using namespace AsteriskSCF::System::Logging;
         if (!mLocatorParams)
@@ -80,6 +81,42 @@ public:
         return t;
     }
 
+    /** 
+     * Attempts to offer a oneway proxy. If oneway isn't supported due to the proxy not 
+     * supporting a stream-oriented protocol (based on configuration), this operation will return the
+     * two-way proxy without throwing the typical NoEndpointException that ice_oneway
+     * might have thrown. If the caller needs to know, the supportsOneWay() is available. 
+     * Note that TwoWayOnly exception can still be generated if
+     * calling an operation that needs to send info back to client (via return values, out
+     * parameters or exceptions). 
+     * @see supportsOneWay
+     */
+    P tryOneWay()
+    {
+        initOneWay();
+
+        return mOneWayProxy;
+    }
+
+    /**
+     * If you want to know whether or not a one_way proxy can even be 
+     * created, you can test with this. 
+     */
+    bool supportsOneWay()
+    {        
+        try
+        {
+            initOneWay();
+        }
+        catch(const steriskSCF::Core::Discovery::V1::ServiceNotFound&)
+        {
+            // The original proxy isn't reachable. 
+            return false;
+        }
+
+        return mSupportsOneWay;
+    }
+
     SmartProxy &operator=(const SmartProxy &rhs)
     {
         // copy is thread safe.  no need to lock.
@@ -167,6 +204,45 @@ public:
 
 private:
 
+    /**
+     * Attempts to create (and cache) a oneway proxy for 
+     * this proxy. 
+     */
+    void initOneWay()
+    {
+        {
+            IceUtil::Mutex::Lock myLock(mMutex);
+            if (mOneWayProxy != 0)
+            {
+                // This has been done. 
+                return;
+            }
+        }
+
+        Ice::ObjectPrx oneway;
+        try
+        {
+            P t = initialize();
+            if (!t)
+            {
+                // We can't create a one way to a proxy we haven't located yet. 
+                throw AsteriskSCF::Core::Discovery::V1::ServiceNotFound();
+            }
+
+            IceUtil::Mutex::Lock myLock(mMutex);
+            oneway = t->ice_oneway();
+            mOneWayProxy = P::uncheckedCast(oneway);
+            mSupportsOneWay = true;
+        }
+        catch (const Ice::NoEndpointException&)
+        {
+            (*mLogger)(AsteriskSCF::System::Logging::Warning) << "No endpoint for oneway invocation. Defaulting to two-way.";
+
+            IceUtil::Mutex::Lock myLock(mMutex);
+            mOneWayProxy = mProxy;
+        }
+    }
+
     void copy(const SmartProxy &rhs)
     {
         // thread safe
@@ -174,17 +250,21 @@ private:
         IceUtil::Mutex::Lock rhsLock(rhs.mMutex);
 
         mProxy = rhs.mProxy;
+        mOneWayProxy = rhs.mOneWayProxy;
         mServiceLocator = rhs.mServiceLocator;
         mLocatorParams = rhs.mLocatorParams;
         mLogger = rhs.mLogger;
+        mSupportsOneWay = rhs.mSupportsOneWay;
     }
 
     // we want to lock even const instances, so mMutex must be mutable
     mutable IceUtil::Mutex mMutex;
     P mProxy;
+    P mOneWayProxy; 
     AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx mServiceLocator;
     AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr mLocatorParams;
     AsteriskSCF::System::Logging::Logger const *mLogger;
+    bool mSupportsOneWay;
 };
 
 }; // end SmartProxy
diff --git a/include/AsteriskSCF/Helpers/PropertyHelper.h b/include/AsteriskSCF/Helpers/PropertyHelper.h
index b6579b8..fd92045 100644
--- a/include/AsteriskSCF/Helpers/PropertyHelper.h
+++ b/include/AsteriskSCF/Helpers/PropertyHelper.h
@@ -19,6 +19,7 @@
 #include <string>
 #include <vector>
 #include <boost/shared_ptr.hpp>
+#include <boost/algorithm/string/predicate.hpp>
 
 namespace AsteriskSCF
 {
@@ -41,6 +42,45 @@ inline std::string propGetSet(const Ice::PropertiesPtr& p, const std::string& pr
 }
 
 /**
+ * A method to convert a string to a boolean value. Useful for 
+ * converting string property values. 
+ *
+ * Values that result in 'true': 
+ *   - "true", "True", "TRUE" or other case variants of "true"
+ *   - "yes", "Yes", "Yes" or other case variants of "yes"
+ *   - "1" 
+ * 
+ * All other values for valueStr result in a return of 'false'. 
+ */
+inline bool stringToBool(const std::string& valueStr)
+{
+    return boost::iequals(valueStr, "yes") || 
+           boost::iequals(valueStr, "true") ||
+           (valueStr.compare("1") == 0);
+}
+
+/**
+ * A method to get the boolean value represented by a named property from
+ * a Property set. 
+ *  @param properties The property expected to contain the named property. 
+ *  @param propertyName The name of the property that represents some boolean value.
+ *  @param defaultValue The value to return if the named property doesn't exist. 
+ *
+ *  @return The boolean value of the property with name 'propertyName', or 
+ * 'defaultvalue' if it the named property isn't found in 'properties'. 
+ */
+inline bool getBooleanPropertyValueWithDefault(const Ice::PropertiesPtr& properties, const std::string& propertyName, bool defaultValue)
+{
+    std::string defaultStr("no");
+    if (defaultValue)
+    {
+        defaultStr = "yes";
+    }
+
+    return AsteriskSCF::stringToBool(properties->getPropertyWithDefault(propertyName, defaultStr));
+}
+
+/**
  *
  * A generic helper template that can be specialized to help convert different types to std::strings
  * for the StringVectorAsArgs template.
diff --git a/include/AsteriskSCF/Replication/ReplicationContext.h b/include/AsteriskSCF/Replication/ReplicationContext.h
new file mode 100644
index 0000000..5b02e9e
--- /dev/null
+++ b/include/AsteriskSCF/Replication/ReplicationContext.h
@@ -0,0 +1,77 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, 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.
+ */
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+namespace AsteriskSCF
+{
+namespace Replication
+{
+
+enum ASTSCF_DLL_EXPORT ReplicationStateType
+{
+    ACTIVE_STANDALONE,
+    ACTIVE_IN_REPLICA_GROUP,
+    STANDBY_IN_REPLICA_GROUP
+};
+
+/** 
+ * This class provides the component with context
+ * related to state replication. 
+ */
+class ASTSCF_DLL_EXPORT ReplicationContext 
+{
+public:
+    ReplicationContext(ReplicationStateType initialState);
+
+    /**
+     * The default implementation returns true if this component is 
+     * in ACTIVE_IN_REPLICA_GROUP state.
+     *
+     * This operation is virtual so that subclasses can 
+     * add other criteria, such as whether the component
+     * has valid proxies to state replicators. 
+     */
+    virtual bool isReplicating();
+
+    /**
+     * Returns true if the component is in 
+     * any of the active states. 
+     */
+    bool isActive();
+
+    /**
+     * Gets the current state. 
+     * @see isReplicating
+     */
+    ReplicationStateType getState();
+
+    /**
+     * Changes this context to reflect a specific state.
+     * @param newState New context state. 
+     */
+    void setState(ReplicationStateType newState);
+
+private:
+    boost::shared_mutex mLock;
+    ReplicationStateType mState;
+};
+typedef ASTSCF_DLL_EXPORT boost::shared_ptr<ReplicationContext> ReplicationContextPtr;
+
+} // namespace Replication
+} // namespace AsteriskSCF
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d0a9c90..ae964db 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,6 +2,8 @@ astscf_component_init(astscf-ice-util-cpp)
 file(GLOB_RECURSE project_headers ../include/*.h)
 astscf_component_add_files(astscf-ice-util-cpp ${project_headers})
 add_subdirectory(CollocatedIceStorm)
+add_subdirectory(Component)
+add_subdirectory(Replication)
 add_subdirectory(WorkQueue)
 add_subdirectory(ThreadPool)
 add_subdirectory(Helpers)
diff --git a/src/Component/CMakeLists.txt b/src/Component/CMakeLists.txt
new file mode 100644
index 0000000..34df0fa
--- /dev/null
+++ b/src/Component/CMakeLists.txt
@@ -0,0 +1,2 @@
+astscf_component_add_files(astscf-ice-util-cpp Component.cpp)
+astscf_component_add_files(astscf-ice-util-cpp TestContext.cpp)
diff --git a/src/Component/Component.cpp b/src/Component/Component.cpp
new file mode 100644
index 0000000..afef647
--- /dev/null
+++ b/src/Component/Component.cpp
@@ -0,0 +1,1053 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, 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.
+ */
+
+#include <boost/lexical_cast.hpp>
+
+#include <Ice/Ice.h>
+#include <IceBox/IceBox.h>
+
+#include <AsteriskSCF/Helpers/PropertyHelper.h>
+#include <AsteriskSCF/Listener/ListenerManager.h>
+#include <AsteriskSCF/Component/Component.h>
+#include <AsteriskSCF/Logger/IceLogger.h>
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
+#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
+#include <AsteriskSCF/System/Component/ReplicaIf.h>
+#include <AsteriskSCF/Discovery/LocatorRegistrationWrapper.h>
+
+using namespace std;
+using namespace AsteriskSCF::System::Component::V1;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Discovery;
+using namespace AsteriskSCF::Replication;
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+static const string ServiceLocatorManagementPropertyName("LocatorServiceManagement.Proxy");
+static const string ServiceLocatorPropertyName("LocatorService.Proxy");
+
+static const string ComponentServiceProxyId("ComponentService");
+static const string ReplicaProxyId("Replica");
+
+/**
+ * This class provides an implementation of the ComponentService interface.
+ * Every Asterisk SCF component is expected to expose the ComponentService interface.
+ */
+class ComponentServiceImpl : public ComponentService
+{
+public:
+    ComponentServiceImpl(Component& component) :
+        mComponent(component)
+    {
+    }
+
+public: // Overrides of the ComponentService interface.
+    void suspend(const ::Ice::Current&)
+    {
+        mComponent.suspended();
+    }
+
+    void resume(const ::Ice::Current&)
+    {
+        mComponent.resumed();
+    }
+
+    void shutdown(const ::Ice::Current&)
+    {
+        // This should probably get the icebox admin interface and call 
+        // that shutdown() operartion. 
+        mComponent.shutdown();
+    }
+
+private:
+    AsteriskSCF::Component::Component& mComponent;
+
+}; // class ComponentServiceImpl
+
+/** 
+ * This interface exists to allow optional, additional control of a 
+ * component during testing. This interface is usually published 
+ * as an additional facet of the same object identity used to publish
+ * the Component Service interface.
+ */
+class ComponentTestImpl : public ComponentTest
+{
+public:
+    ComponentTestImpl(Component& component) :
+        mComponent(component)
+    {
+    }
+
+    void setTestMode(const std::string& mode, const ::Ice::Current&)
+    {
+        mComponent.setTestMode(mode);
+    }
+
+    void setTestModeWithArgs(const std::string& mode, 
+                             const ComponentTestParamSeq& args, 
+                             const ::Ice::Current&)
+    {
+        mComponent.setTestModeWithArgs(mode, args);
+    }
+
+    void clearTestMode(const string& mode, const ::Ice::Current&)
+    {
+        mComponent.clearTestMode(mode);
+    }
+
+    void clearTestModes(const ::Ice::Current&)
+    {
+        mComponent.clearTestModes();
+    }
+
+private:
+   AsteriskSCF::Component::Component& mComponent;
+
+}; // class ComponentTestImpl
+
+/**
+ * This class provides an implementation of the Replica interface,
+ * used to manage the component's replication state.
+ *
+ * TBD... Use ListenerManager template to notify listeners.
+ */
+class ReplicaImpl : public Replica 
+{
+public:
+    /**
+     * Constructor. 
+     *  @param app 
+     *  @param adapter The adapter is assumed to have been activated. 
+     */
+    ReplicaImpl(Component& component, 
+                const ::Ice::ObjectAdapterPtr& adapter) : 
+      mComponent(component), 
+      mAdapter(adapter), 
+      mProxyInitialized(false)
+    { 
+    }
+
+    bool isActive(const ::Ice::Current&)
+    {
+        return mComponent.isActive();
+    }
+
+    void initProxy()
+    {
+        mReplicaPrx = ReplicaPrx::uncheckedCast(mAdapter->createDirectProxy(
+                          mAdapter->getCommunicator()->stringToIdentity(ReplicaProxyId)));
+        mProxyInitialized = true;
+    }
+
+    bool activate(const ::Ice::Current&)
+    {
+        mComponent.activated();
+
+        if (!mProxyInitialized)
+        {
+            initProxy();
+        }
+
+        for (vector<ReplicaListenerPrx>::const_iterator listener = mListeners.begin(); 
+             listener != mListeners.end(); ++listener)
+        {
+            (*listener)->begin_activated(mReplicaPrx);
+        }
+
+        return true;
+    }
+
+    void standby(const ::Ice::Current&)
+    {
+        mComponent.standby();
+
+        if (!mProxyInitialized)
+        {
+            initProxy();
+        }
+
+        for (vector<ReplicaListenerPrx>::const_iterator listener = mListeners.begin(); 
+                listener != mListeners.end(); ++listener)
+        {
+            (*listener)->begin_onStandby(mReplicaPrx);
+        }
+    }
+
+    void addListener(const AsteriskSCF::System::Component::V1::ReplicaListenerPrx& listener, 
+                     const ::Ice::Current&)
+    {
+        mListeners.push_back(listener);
+    }
+
+    void removeListener(const AsteriskSCF::System::Component::V1::ReplicaListenerPrx& listener, 
+                        const ::Ice::Current&)
+    {
+        mListeners.erase(std::remove(mListeners.begin(), mListeners.end(), listener), 
+                         mListeners.end());
+    }
+
+private:
+    Component &mComponent;
+
+    /**
+     * Pointer to the object adapter we exist on.
+     */
+    ::Ice::ObjectAdapterPtr mAdapter;
+
+    ReplicaPrx mReplicaPrx;
+    bool mProxyInitialized;
+
+    /**
+     * Listeners that we need to push state change notifications out to.
+     */
+    vector<AsteriskSCF::System::Component::V1::ReplicaListenerPrx> mListeners;
+
+}; // class ReplicaImpl
+
+Component::Component(const AsteriskSCF::System::Logging::Logger& logger,
+                     const std::string& componentDiscoveryCategory) :
+      mLogger(logger),
+      mInitialized(false),
+      mRunning(false),
+      mPublishTestInterface(false),
+      mComponentDiscoveryCategory(componentDiscoveryCategory)
+{
+}
+
+std::string Component::getServiceLocatorManagementProperty() const
+{
+    return mCommunicator->getProperties()->getProperty(ServiceLocatorManagementPropertyName);
+}
+
+void Component::setTestMode(const std::string& mode)
+{
+    mTestContext->setTestMode(mode);
+}
+    
+void Component::setTestModeWithArgs(const std::string& mode, 
+                                    const ComponentTestParamSeq& params)
+{ 
+    mTestContext->setTestMode(mode, params);
+}
+
+void Component::clearTestMode(const string& mode)
+{
+    mTestContext->clearTestMode(mode);
+}
+
+void Component::clearTestModes()
+{
+    mTestContext->clearAllTestModes();
+}
+
+bool Component::isActive()
+{
+    // The Replication Context is tracking our current status. 
+    return (mReplicationContext->getState() != STANDBY_IN_REPLICA_GROUP);
+}
+
+void Component::activated()
+{
+    try
+    {
+        mReplicationContext->setState(ACTIVE_IN_REPLICA_GROUP);
+        stopListeningToStateReplicators();
+        registerPrimaryServices();
+        registerWithRemoteServices();
+
+        // Notify subclasses
+        onActivated();
+    }
+    catch(const Ice::Exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+void Component::standby()
+{
+    try
+    {
+        unregisterPrimaryServices();
+        unregisterFromRemoteServices();
+        mReplicationContext->setState(STANDBY_IN_REPLICA_GROUP);
+        listenToStateReplicators();
+
+        // Notify subclasses
+        onStandby();
+    }
+    catch(const Ice::Exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+    }
+}
+
+/**
+ * Helper function to wrap a service in a registration wrapper.
+ */
+LocatorRegistrationWrapperPtr Component::wrapServiceForRegistration(const Ice::ObjectPrx& proxy, 
+                 const string& category,
+                 const string& service,
+                 const string& id) const
+{
+    string guid = mName + "." + category;
+
+    // Configure how other components look this component up.
+    ServiceLocatorParamsPtr params = new ServiceLocatorParams;
+    params->category = category;
+    params->service = service;
+    params->id = id; 
+
+    LocatorRegistrationWrapperPtr wrapper = 
+            new LocatorRegistrationWrapper(mCommunicator, getServiceLocatorManagementProperty(), proxy, 
+                guid, params);
+
+    return wrapper;
+}
+
+/** 
+ * Overload for most common case.
+ */
+LocatorRegistrationWrapperPtr Component::wrapServiceForRegistration(const Ice::ObjectPrx& proxy, 
+                 const string& category) const
+{
+    return wrapServiceForRegistration(proxy, category, mServiceName, mName);
+}
+
+
+/**
+ * In the required override of registerPrimaryServices(), this operation should
+ * be called for each primary interface registered with the service locator.
+ */
+void Component::managePrimaryService(const LocatorRegistrationWrapperPtr& service)
+{
+    mPrimaryServices.push_back(service);
+}
+
+/**
+ * This operation should be called for each backplane interface that's to be 
+ * registered with the service locator.
+ */
+void Component::manageBackplaneService(const LocatorRegistrationWrapperPtr& service)
+{
+    mBackplaneServices.push_back(service);
+}
+
+/**
+ * Prepare this component's backplane services for registration 
+ * with the Service Locator.
+ */
+void Component::prepareBackplaneServicesForDiscovery()
+{
+    try
+    {
+        // Register the ComponentService interface with the Service Locator.
+        mComponentRegistration = wrapServiceForRegistration(mComponentServicePrx,
+                                                            mComponentDiscoveryCategory,
+                                                            mServiceName,
+                                                            mName);
+        manageBackplaneService(mComponentRegistration);
+
+        if (mPublishTestInterface)
+        {
+            // Make our test interface available as a facet of the ComponentService's object identity.
+            mComponentTestPrx = ComponentTestPrx::uncheckedCast(
+                mBackplaneAdapter->addFacet(mComponentTest, 
+                                            mComponentServicePrx->ice_getIdentity(), 
+                                            AsteriskSCF::System::Component::V1::ComponentTestFacet));
+        }
+
+
+        // Register the Replica interface with the Service Locator.
+        mReplicaRegistration = wrapServiceForRegistration(mReplicaPrx,
+                                                          mComponentDiscoveryCategory + ".Replica",
+                                                          mServiceName,
+                                                          mName);
+        manageBackplaneService(mReplicaRegistration);
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << "Exception in component " << mName << 
+            " in " << BOOST_CURRENT_FUNCTION << ". Details: " << e.what();
+        throw;
+    }
+}
+
+/**
+ * Register this component's primary service interfaces with the Service Locator.
+ */
+void Component::registerPrimaryServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mPrimaryServices.begin(); 
+        i != mPrimaryServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->registerService();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+    }
+
+    onRegisterPrimaryServices();
+}
+
+/**
+ * Unregister this component's primary service interfaces from the Service Locator.
+ */
+void Component::unregisterPrimaryServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mPrimaryServices.begin(); 
+        i != mPrimaryServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->unregister();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+        catch(...)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << "Some unknown exception.";
+        }
+    }
+
+    onUnregisterPrimaryServices();
+}
+
+/**
+ * Register this component's backplane interfaces from the Service Locator.
+ */
+void Component::registerBackplaneServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mBackplaneServices.begin(); 
+        i != mBackplaneServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->registerService();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+    }
+
+    onRegisterBackplaneServices();
+}
+
+/**
+ * Unregister this component's backplane interfaces from the Service Locator.
+ */
+void Component::unregisterBackplaneServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mBackplaneServices.begin(); 
+        i != mBackplaneServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->unregister();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+    }
+
+    onUnregisterBackplaneServices();
+}
+
+/**
+ * Suspends this component's primary public interfaces 
+ * within the Service Locator. When suspended in this manner, 
+ * the ServiceLocator will not consider the component during 
+ * lookup requests. 
+ */
+void Component::suspendPrimaryServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mPrimaryServices.begin(); 
+        i != mPrimaryServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->suspend();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+    }
+
+    onSuspendPrimaryServices();
+}
+
+/**
+ * Unsuspends this component's primary public interfaces 
+ * within the Service Locator. This allows them to be 
+ * located again via the Service Locator. 
+ */
+void Component::unsuspendPrimaryServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mPrimaryServices.begin(); 
+        i != mPrimaryServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->unsuspend();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+    }
+
+    onUnsuspendPrimaryServices();
+}
+
+/**
+ * Suspends this component's backplane interfaces 
+ * within the Service Locator. When suspended in this manner, 
+ * the ServiceLocator will not consider the component during lookup requests. 
+ */
+void Component::suspendBackplaneServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mBackplaneServices.begin(); 
+        i != mBackplaneServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->suspend();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+    }
+
+    onSuspendBackplaneServices();
+}
+
+/**
+ * Unsuspends this component's backplane interfaces 
+ * within the Service Locator. This allows them to be 
+ * located again via the Service Locator. 
+ */
+void Component::unsuspendBackplaneServices()
+{
+    for(vector<LocatorRegistrationWrapperPtr>::iterator i=mBackplaneServices.begin(); 
+        i != mBackplaneServices.end(); ++i)
+    {
+        try
+        {
+            (*i)->unsuspend();
+        }
+        catch(const std::exception& e)
+        {
+            mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        }
+    }
+
+    onUnsuspendBackplaneServices();
+}
+
+/**
+ * Create the adapters for this component.
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::createAdapters()
+{
+    try
+    {
+        // Create the adapter that our functional services are published on.
+        // If not specified in the config file at all, using "default" will choose a port 
+        // number for us, avoiding the unconfigured adapter exception. 
+        mServiceAdapter = mCommunicator->createObjectAdapterWithEndpoints(mName,
+            mCommunicator->getProperties()->getPropertyWithDefault(mName + ".Endpoints", "default"));
+
+        // Create an adapter for our backplane services. 
+        mBackplaneAdapter = mCommunicator->createObjectAdapterWithEndpoints(mName + ".Backplane",
+           mCommunicator->getProperties()->getPropertyWithDefault(mName + ".Backplane.Endpoints", "default"));
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Activate the adapters for this component.
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::activateAdapters()
+{
+    try
+    {
+        mServiceAdapter->activate();
+        mBackplaneAdapter->activate();
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/** 
+ * A factory method. 
+ * Allows subclasses to easily extend the ReplicationContext if needed. 
+ */
+ReplicationContextPtr Component::createReplicationContext(ReplicationStateType state)
+{
+     return ReplicationContextPtr(new ReplicationContext(state));
+}
+
+/**
+ * Create a ReplicationContext for this component. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::initReplicationContext()
+{
+    try
+    {
+        bool standalone = AsteriskSCF::getBooleanPropertyValueWithDefault( 
+            mCommunicator->getProperties(), mName + ".Standalone", false);
+
+        ReplicationStateType state(STANDBY_IN_REPLICA_GROUP);
+
+        if (standalone)
+        {
+            state = ACTIVE_STANDALONE;
+        }
+        else
+        {
+            // NOTE: In the near future, Standalone instances are the only 
+            // instances that will default to being active. When that is in 
+            // place, non-standalone instances will need to be made active via 
+            // the Replica interface. But for now, we default to active unless 
+            // the soon-to-be obsolete Standby property is set. 
+            if (AsteriskSCF::getBooleanPropertyValueWithDefault(mCommunicator->getProperties(),
+                     mName + ".Standby", false) == false)
+            {
+                state = ACTIVE_IN_REPLICA_GROUP;
+            }
+        }
+
+        // Create the replication context.
+        mReplicationContext = createReplicationContext(state);
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Create a TestContext for this component. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::initTestContext()
+{
+    try
+    {
+        // Create the test context.
+        mTestContext = TestContextPtr(new TestContext());
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+/**
+ * Configure the logger. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::configureLogger()
+{
+    try
+    {
+        ConfiguredIceLoggerPtr mIceLogger = createIceLogger(mBackplaneAdapter);
+        getLoggerFactory().setLogOutput(mIceLogger->getLogger());
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Create the backplane servant implementations.
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::createBackplaneServices()
+{
+    try
+    {
+        // Check to see if we're configured to publish a test interface.
+        mPublishTestInterface = AsteriskSCF::getBooleanPropertyValueWithDefault(
+                                mCommunicator->getProperties(),
+                                mName + ".ComponentTest",
+                                false);
+
+        if (mPublishTestInterface)
+        {
+            // Create and publish the ComponentTest servant. This will be exposed
+            // as a facet of ComponentService.
+            mComponentTest = new ComponentTestImpl(*this);
+        }
+
+        // Create and publish the ComponentService interface on the backplane adapter. 
+        mComponentService = new ComponentServiceImpl(*this);
+        mComponentServicePrx = ComponentServicePrx::uncheckedCast(
+            mBackplaneAdapter->add(mComponentService, 
+                                   mCommunicator->stringToIdentity(ComponentServiceProxyId)));
+
+        // Create and publish our Replica interface on the management adapter. 
+        // This interface allows this component to be activated or placed in standby mode. 
+        mReplica = new ReplicaImpl(*this, mBackplaneAdapter);
+        mReplicaPrx = ReplicaPrx::uncheckedCast(mBackplaneAdapter->add(mReplica, 
+                  mCommunicator->stringToIdentity(ReplicaProxyId)));
+
+        createReplicationStateListeners();
+    }
+    catch(const std::exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+}
+
+/**
+ * Initialize the service locator proxies. 
+ * This operation is a step in initialize()'s Template Method pattern.
+ */
+void Component::initServiceLocatorProxies()
+{
+    try
+    {
+        // Get a proxy to the management interface for the Service Locator manager.
+        mServiceLocatorManagement = 
+            ServiceLocatorManagementPrx::checkedCast(mCommunicator->stringToProxy(
+                 mCommunicator->getProperties()->getPropertyWithDefault(
+                  ServiceLocatorManagementPropertyName, "LocatorServiceManagement:tcp -p 4422")));
+
+        // Get a proxy to the interface for the Service Locator.
+        mServiceLocator = 
+            ServiceLocatorPrx::checkedCast(mCommunicator->stringToProxy(
+                 mCommunicator->getProperties()->getPropertyWithDefault(
+                  ServiceLocatorPropertyName, "LocatorService:default -p 4411")));
+    }
+    catch(const Ice::Exception& e)
+    {
+        mLogger(Error) << BOOST_CURRENT_FUNCTION << "Unable to obtain proxies to ServiceLocator. Check configuration. " << e.what();
+        throw;
+    }
+}
+
+void Component::verifyProperties()
+{
+    const int defaultSize(4);
+    string strDefaultSize = boost::lexical_cast<std::string>(defaultSize);
+
+    Ice::Int defaultPoolSize = mCommunicator->getProperties()->getPropertyAsIntWithDefault("Ice.ThreadPool.Server.Size", 0);
+    if (mCommunicator->getProperties()->getPropertyAsIntWithDefault(mName + ".ThreadPool.Size", 0) < defaultSize)
+    {
+        if (defaultPoolSize < defaultSize)
+        {
+            mLogger(Info) << "Configured thread pool size for " << mName + " is too small, defaulting to " << strDefaultSize;
+            mCommunicator->getProperties()->setProperty(mName + ".ThreadPool.Size", strDefaultSize);
+        }
+    }
+
+    if (mCommunicator->getProperties()->getPropertyAsIntWithDefault(mName + ".ThreadPool.Size", 0) < defaultSize)
+    {
+        if (defaultPoolSize < defaultSize)
+        {
+            mLogger(Info) << "Configured Internal thread pool size for " << mName + " is too small, defaulting to " << strDefaultSize;
+            mCommunicator->getProperties()->setProperty(mName + ".ThreadPool.Size", strDefaultSize);
+        }
+    }
+
+    defaultPoolSize = mCommunicator->getProperties()->getPropertyAsIntWithDefault("Ice.ThreadPool.Client.Size", 0);
+    if (defaultPoolSize < defaultSize)
+    {
+        mLogger(Warning) << "Client thread pool size is too small. It should be set to " << strDefaultSize << " or greater.";
+    }
+
+}
+
+/**
+ * This method is an instance of the Template Method pattern. Each of the
+ * operations called are virtual methods. Some are optionally overridden within a
+ * component, and others are required to be overridden. 
+ */
+void Component::initialize()
+{
+    try
+    {
+        // Notify subclasses.
+        onPreInitialize();
+
+        verifyProperties();
+
+        createAdapters();
+
+        // We activate the adapters fairly early in the process 
+        // so that components can get access to the Service Locator
+        // for their specialized behavior. 
+        activateAdapters();
+
+        initServiceLocatorProxies();
+
+        initTestContext();
+
+        initReplicationContext();
+
+        configureLogger();
+
+        createPrimaryServices();
+
+        createBackplaneServices();
+
+        mInitialized = true;
+
+        findRemoteServices();
+
+        // Notify subclasses.
+        onPostInitialize();
+    }
+    catch(const ::Ice::Exception &e)
+    {
+        mLogger(Error) << mName << ", " << BOOST_CURRENT_FUNCTION << " : " << e.what();
+        throw e;
+    }
+}
+
+/**
+ * Override of the IceBox::Service start method.
+ */
+void Component::start(const string& name, 
+                                   const ::Ice::CommunicatorPtr& communicator, 
+                                   const ::Ice::StringSeq& args)
+{
+    mLogger(Info) << "Starting...";
+
+    mCommunicator = communicator;
+    mName = name;
+    mArgs = args;   // Arguments that weren't stripped off by IceBox.
+
+    mServiceName = mCommunicator->getProperties()->getPropertyWithDefault(mName + ".ServiceName", "default");
+    
+    if (!mInitialized)
+    {
+        initialize();
+    }
+    else
+    {
+        mServiceAdapter->activate();
+        mBackplaneAdapter->activate();
+    }
+
+    try
+    {
+        // Active mode?
+        if (mReplicationContext->isActive())
+        {
+            registerWithRemoteServices();
+        }
+
+        // Prepare our services for discovery via the Service Locator.
+        prepareBackplaneServicesForDiscovery();
+        preparePrimaryServicesForDiscovery();
+    
+        // We always register backplane services with Service Locator.
+        registerBackplaneServices();
+
+        // Standby mode?
+        if (mReplicationContext->isActive() == true)
+        {
+            registerPrimaryServices();
+        }
+        else
+        {
+            listenToStateReplicators();
+        }
+
+        // Notify subclasses
+        onStart();
+    }
+    catch(const Ice::Exception& e)
+    {
+        mLogger(Error) << mName << ", " << BOOST_CURRENT_FUNCTION << e.what();
+        throw;
+    }
+
+    mRunning = true;
+    mLogger(Info) << "Started";
+}
+
+/**
+ * Things we do to resume operation after a pause().
+ */
+void Component::resumed()
+{
+    if (!mRunning)
+    {
+        // Standby mode?
+        if (mReplicationContext->getState() == STANDBY_IN_REPLICA_GROUP)
+        {
+            try
+            {
+                listenToStateReplicators();
+            }
+            catch(const std::exception& e)
+            {
+                mLogger(Error) << mName << ", " << BOOST_CURRENT_FUNCTION << e.what();
+            }
+        } 
+
+        // Allow servants on this adapter to process requests.
+        mServiceAdapter->activate();
+
+        // Re-enable lookups of our interfaces in the ServiceLocator. 
+        unsuspendPrimaryServices();
+
+        if (mReplicationContext->isActive())
+        {
+            try
+            {
+                registerWithRemoteServices();
+            }
+            catch(const std::exception& e)
+            {
+                mLogger(Error) << mName << ", " << BOOST_CURRENT_FUNCTION << e.what();
+            }
+        }
+    }
+
+    // Notify subclasses
+    onResume();
+
+    mRunning = true;
+}
+
+/** 
+ * Utility function to suspend the service for a suspend() or stop().
+ */
+void Component::suspendService(bool shuttingDown)
+{
+    if (mRunning)
+    {
+        // Suspend lookups of our interfaces in the ServiceLocator. If shutting down,
+        // we'll be deregestering our interfaces with the ServiceLocator,
+        // so we won't waste the bandwidth doing a suspend in that case. 
+        if (!shuttingDown)
+        {
+            suspendPrimaryServices();
+        }
+
+        // Standby mode?
+        if (mReplicationContext->getState() == STANDBY_IN_REPLICA_GROUP)
+        {
+             try
+             {
+                 stopListeningToStateReplicators();
+             }
+             catch(const std::exception& e)
+             {
+                 mLogger(Error) << mName << ", " << BOOST_CURRENT_FUNCTION << e.what();
+             }
+        }
+
+        if (mReplicationContext->isActive())
+        {
+             try
+             {
+                 unregisterFromRemoteServices();
+             }
+             catch(const std::exception& e)
+             {
+                 mLogger(Error) << mName << ", " << BOOST_CURRENT_FUNCTION << e.what();
+             }
+        }
+
+        // Place the service adapter in holding state.
+        // The adapter that services the ComponentService stays active. 
+        mServiceAdapter->hold();
+    }
+
+    mRunning = false;
+}
+
+/** 
+ * Handle a notice from the ComponentService. 
+ */
+void Component::suspended()
+{
+    mLogger(Info) << "Suspending...";
+
+    suspendService(false);
+
+    // Notify subclasses
+    onSuspend();
+
+    mLogger(Info) << "Suspended.";
+}
+
+/**
+ * Shutdown the Icebox component. 
+ * This is a command via ComponentService, not
+ * a notification.
+ */
+void Component::shutdown()
+{
+    // TBD. 
+}
+
+/**
+ * Override of the IceBox::Service stop method. 
+ */
+void Component::stop()
+{
+    mLogger(Info) << "Stopping...";
+
+    suspendService(true);
+
+    unregisterPrimaryServices();
+    unregisterBackplaneServices();
+
+    // Turn off our management interface. 
+    // Only a start() directly from IceBox can restart us now. 
+    mBackplaneAdapter->hold();
+
+    // Notify subclasses
+    onStop();
+
+    mLogger(Info) << "Stopped.";
+}
+
+} // end Component
+} // end AsteriskSCF
diff --git a/src/Component/TestContext.cpp b/src/Component/TestContext.cpp
new file mode 100644
index 0000000..3390ed4
--- /dev/null
+++ b/src/Component/TestContext.cpp
@@ -0,0 +1,102 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, 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.
+ */
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+
+#include <AsteriskSCF/Component/TestContext.h>
+
+using namespace std;
+using namespace AsteriskSCF::System::Component::V1;
+
+namespace AsteriskSCF
+{
+namespace Component
+{
+
+TestContext::TestContext()
+{
+}
+
+/**
+ * Indicates whether a test mode with given name
... 875 lines suppressed ...


-- 
asterisk-scf/release/ice-util-cpp.git



More information about the asterisk-scf-commits mailing list