[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