[asterisk-scf-commits] asterisk-scf/release/bridging.git branch "master" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Fri Sep 30 12:44:25 CDT 2011
branch "master" has been updated
via 19496522bf61f9a2805b5e7fc895909634b9a50e (commit)
from 649687f8e6d0723c82155cf25b7f2fbe014b6517 (commit)
Summary of changes:
.../BridgeService/BridgeReplicatorIf.ice | 9 +-
src/BridgeCreationExtensionPointImpl.cpp | 141 ++++++++++++++++
src/BridgeCreationExtensionPointImpl.h | 54 ++++++
src/BridgeImpl.cpp | 55 ++++--
src/BridgeImpl.h | 8 +-
src/BridgeManagerImpl.cpp | 174 ++++++++++++++++++--
src/BridgeManagerImpl.h | 3 +-
src/CMakeLists.txt | 2 +
src/Component.cpp | 8 +-
test/BridgeListenerI.h | 1 +
test/CMakeLists.txt | 2 +-
test/TestBridging.cpp | 157 +++++++++++++++++-
12 files changed, 571 insertions(+), 43 deletions(-)
create mode 100755 src/BridgeCreationExtensionPointImpl.cpp
create mode 100755 src/BridgeCreationExtensionPointImpl.h
- Log -----------------------------------------------------------------
commit 19496522bf61f9a2805b5e7fc895909634b9a50e
Author: Brent Eagles <beagles at digium.com>
Date: Fri Sep 30 15:14:06 2011 -0230
bridge creation extension point support
diff --git a/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice b/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
index fb0b7ec..0eb53de 100644
--- a/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
+++ b/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
@@ -163,7 +163,6 @@ enum ServiceState
Destroyed
};
sequence<AsteriskSCF::SessionCommunications::V1::BridgeManagerListener*> BridgeManagerListenerSeq;
-sequence<AsteriskSCF::SessionCommunications::V1::BridgeListener*> BridgeListenerSeq;
/**
* The bridge manager state.
@@ -171,7 +170,7 @@ sequence<AsteriskSCF::SessionCommunications::V1::BridgeListener*> BridgeListener
class BridgeManagerStateItem extends ReplicatedStateItem
{
ServiceState runningState;
- BridgeListenerSeq defaultBridgeListeners;
+ AsteriskSCF::SessionCommunications::V1::BridgeListenerSeq defaultBridgeListeners;
BridgeManagerListenerSeq listeners;
};
@@ -187,6 +186,12 @@ class BridgeStateItem extends ReplicatedStateItem
string bridgeId;
/**
+ * The proxy that the bridge should "publish" through events. This
+ * provides a mechanism to supported decorated bridges.
+ */
+ AsteriskSCF::SessionCommunications::V1::Bridge* publishedBridge;
+
+ /**
* The current activation state of the bridge. NOT the same
* as the Component running state.
**/
diff --git a/src/BridgeCreationExtensionPointImpl.cpp b/src/BridgeCreationExtensionPointImpl.cpp
new file mode 100755
index 0000000..6a4ab31
--- /dev/null
+++ b/src/BridgeCreationExtensionPointImpl.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#include "BridgeCreationExtensionPointImpl.h"
+#include <boost/thread/shared_mutex.hpp>
+#include "BridgeServiceConfig.h"
+
+using namespace AsteriskSCF::BridgeService;
+using namespace AsteriskSCF::SessionCommunications::V1;
+using namespace AsteriskSCF::SessionCommunications::ExtensionPoints::V1;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::System::Hook::V1;
+
+namespace
+{
+ class BridgeExtPtImpl : public BridgeCreationExtensionPointImpl
+ {
+ public:
+ BridgeExtPtImpl(const Logger& logger) :
+ mLogger(logger)
+ {
+ }
+
+ void addHook(const BridgeCreationHookPrx& newHook, const Ice::Current& current)
+ {
+ UniqueLock lock(mLock);
+ BridgeCreationHookSeq::iterator i =
+ find_if(mHooks.begin(), mHooks.end(), IdentityComparePredicate<BridgeCreationHookPrx>(newHook));
+ if (i != mHooks.end())
+ {
+ mLogger(Debug) << "refreshing creation hook " << newHook << " on "
+ << objectIdFromCurrent(current);
+ //
+ // Refresh the proxy if it is already in the vector.
+ //
+ *i = newHook;
+ }
+ else
+ {
+ mLogger(Debug) << "adding creation hook " << newHook << " on "
+ << objectIdFromCurrent(current);
+ mHooks.push_back(newHook);
+ }
+ }
+
+ void removeHook(const BridgeCreationHookPrx& hookToRemove, const Ice::Current& current)
+ {
+ UniqueLock lock(mLock);
+ mLogger(Debug) << "removing creation hook " << hookToRemove << " on "
+ << objectIdFromCurrent(current);
+ mHooks.erase(remove_if(mHooks.begin(), mHooks.end(),
+ IdentityComparePredicate<BridgeCreationHookPrx>(hookToRemove)), mHooks.end());
+ }
+
+ void clearHooks(const Ice::Current& current)
+ {
+ UniqueLock lock(mLock);
+ mLogger(Debug) << "clearing hooks from " << objectIdFromCurrent(current);
+ mHooks.clear();
+ }
+
+ BridgeCreationHookDataPtr runHooks(const BridgeCreationHookDataPtr& originalData)
+ {
+ mLogger(Debug) << "executing hooks";
+ BridgeCreationHookSeq hooks = getHooks();
+ BridgeCreationHookSeq deadHooks;
+ BridgeCreationHookDataPtr tokenData = BridgeCreationHookDataPtr::dynamicCast(originalData->ice_clone());
+ for (BridgeCreationHookSeq::const_iterator i = hooks.begin(); i != hooks.end(); ++i)
+ {
+ try
+ {
+ BridgeCreationHookDataPtr resultData;
+ HookResult result = (*i)->execute(tokenData, resultData);
+ if (result.status == AsteriskSCF::System::Hook::V1::Succeeded)
+ {
+ tokenData = resultData;
+ }
+ }
+ catch (const Ice::ObjectNotExistException&)
+ {
+ mLogger(Debug) << "received ONE when running hook " << (*i) << ", removing from list";
+ deadHooks.push_back(*i);
+ }
+ catch (const std::exception& ex)
+ {
+ mLogger(Debug) << ex.what() << " thrown when executing bridge creation hook " << (*i) << ", skipping";
+ }
+ }
+ removeHooks(deadHooks);
+ return tokenData;
+ }
+
+ private:
+ typedef boost::shared_lock<boost::shared_mutex> SharedLock;
+ typedef boost::unique_lock<boost::shared_mutex> UniqueLock;
+ boost::shared_mutex mLock;
+
+ Logger mLogger;
+ BridgeCreationHookSeq mHooks;
+
+ void removeHooks(const BridgeCreationHookSeq& hooks)
+ {
+ if (hooks.empty())
+ {
+ return;
+ }
+
+ UniqueLock lock(mLock);
+ for (BridgeCreationHookSeq::const_iterator i = hooks.begin(); i != hooks.end(); ++i)
+ {
+ mHooks.erase(remove_if(mHooks.begin(), mHooks.end(),
+ IdentityComparePredicate<BridgeCreationHookPrx>(*i)), mHooks.end());
+ }
+ }
+
+ BridgeCreationHookSeq getHooks()
+ {
+ SharedLock lock(mLock);
+ return mHooks;
+ }
+ };
+};
+
+AsteriskSCF::BridgeService::BridgeCreationExtensionPointImplPtr
+AsteriskSCF::BridgeService::BridgeCreationExtensionPointImpl::create(const Logger& logger)
+{
+ return new BridgeExtPtImpl(logger);
+}
diff --git a/src/BridgeCreationExtensionPointImpl.h b/src/BridgeCreationExtensionPointImpl.h
new file mode 100755
index 0000000..5cc6c6a
--- /dev/null
+++ b/src/BridgeCreationExtensionPointImpl.h
@@ -0,0 +1,54 @@
+/*
+ * 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 <AsteriskSCF/SessionCommunications/SessionCommunicationsExtensionPointsIf.h>
+
+namespace AsteriskSCF
+{
+
+//
+// Forward declarations.
+//
+namespace System
+{
+namespace Logging
+{
+
+class Logger;
+
+} /* End of namespace Logging */
+} /* End of namespace System */
+
+namespace BridgeService
+{
+ /**
+ * Base class for internal methods.
+ */
+ class BridgeCreationExtensionPointImpl : public AsteriskSCF::SessionCommunications::ExtensionPoints::V1::BridgeCreationExtensionPoint
+ {
+ public:
+
+ virtual AsteriskSCF::SessionCommunications::ExtensionPoints::V1::BridgeCreationHookDataPtr runHooks(
+ const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::BridgeCreationHookDataPtr& originalData) = 0;
+
+ static IceUtil::Handle<BridgeCreationExtensionPointImpl>
+ create(const AsteriskSCF::System::Logging::Logger&);
+ };
+ typedef IceUtil::Handle<BridgeCreationExtensionPointImpl> BridgeCreationExtensionPointImplPtr;
+
+} // End of namespace Bridging.
+} // End of namespace AsteriskSCF.
diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index 5f85479..edcd46b 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -97,12 +97,17 @@ public:
BridgeCookies getCookies(const BridgeCookies& cookies, const Ice::Current&);
//
+ // Internal use variant of setCookies.
+ //
+ void setCookiesImpl(const BridgeCookies& cookies);
+
+ //
// BridgeServant methods
//
bool destroyed();
void destroyImpl();
void shutdownImpl(const Ice::Current& current);
- void activate(const BridgePrx& proxy);
+ void activate(const BridgePrx& proxy, const std::string& id);
void updateState(const BridgeStateItemPtr& state);
void addListener(const BridgeListenerStateItemPtr& update);
@@ -1040,13 +1045,7 @@ void BridgeImpl::setCookies(const BridgeCookies& cookies, const Ice::Current& cu
BridgeStateItemPtr update;
{
boost::unique_lock<boost::shared_mutex> lock(mLock);
- for (BridgeCookies::const_iterator i = cookies.begin(); i != cookies.end(); ++i)
- {
- if ((*i))
- {
- mState->cookies[(*i)->ice_id()] = (*i);
- }
- }
+ setCookiesImpl(cookies);
if (!cookies.empty())
{
update = createUpdate();
@@ -1096,6 +1095,20 @@ BridgeCookies BridgeImpl::getCookies(const BridgeCookies& cookies, const Ice::Cu
return result;
}
+void BridgeImpl::setCookiesImpl(const BridgeCookies& cookies)
+{
+ //
+ // This is only used for initial setting of cookies and will not be used after the object has been activated.
+ //
+ for (BridgeCookies::const_iterator i = cookies.begin(); i != cookies.end(); ++i)
+ {
+ if ((*i))
+ {
+ mState->cookies[(*i)->ice_id()] = (*i);
+ }
+ }
+}
+
bool BridgeImpl::destroyed()
{
boost::shared_lock<boost::shared_mutex> lock(mLock);
@@ -1111,9 +1124,9 @@ void BridgeImpl::destroyImpl()
mState->runningState = Destroyed;
mSessions = 0;
- if (mPrx)
+ if (mObjAdapter && mState)
{
- mObjAdapter->remove(mPrx->ice_getIdentity());
+ mObjAdapter->remove(mObjAdapter->getCommunicator()->stringToIdentity(mState->bridgeId));
}
}
catch (const Ice::Exception&)
@@ -1139,14 +1152,14 @@ void BridgeImpl::shutdownImpl(const Ice::Current& current)
shutdown(current);
}
-void BridgeImpl::activate(const BridgePrx& proxy)
+void BridgeImpl::activate(const BridgePrx& proxy, const std::string& bridgeId)
{
mPrx = proxy;
- string listenerId = mObjAdapter->getCommunicator()->identityToString(mPrx->ice_getIdentity());
- mLogger(Trace) << FUNLOG << " : activating with " << listenerId;
- mState->key = listenerId;
- mState->bridgeId = listenerId;
- listenerId += ".sessionListener";
+ mState->publishedBridge = proxy;
+ mState->key = bridgeId;
+ mState->bridgeId = bridgeId;
+ string listenerId = bridgeId + ".sessionListener";
+ mLogger(Debug) << FUNLOG << " : activating session listener with " << listenerId;
mActivated = true;
mSessionListenerPrx =
SessionListenerPrx::uncheckedCast(
@@ -1194,8 +1207,14 @@ void BridgeImpl::activate()
mLogger(Trace) << FUNLOG;
boost::unique_lock<boost::shared_mutex> lock(mLock);
mActivated = true;
- mPrx = BridgePrx::uncheckedCast(mObjAdapter->add(this, mObjAdapter->getCommunicator()->stringToIdentity(mState->key)));
- string listenerId = mState->key + ".sessionListener";
+ //
+ // XXX this is not correct with extension points... this could be a decorator.
+ //
+
+ mPrx = mState->publishedBridge;
+ BridgePrx actualPrx = BridgePrx::uncheckedCast(mObjAdapter->add(this, mObjAdapter->getCommunicator()->stringToIdentity(mState->key)));
+
+ string listenerId = mState->key + ".sessionListener"; // XXX this is no longer a derived thing.
mSessionListenerPrx = SessionListenerPrx::uncheckedCast(
mObjAdapter->add(mSessionListener, mObjAdapter->getCommunicator()->stringToIdentity(listenerId)));
//
diff --git a/src/BridgeImpl.h b/src/BridgeImpl.h
index 2c9ab9f..35b311f 100644
--- a/src/BridgeImpl.h
+++ b/src/BridgeImpl.h
@@ -90,7 +90,8 @@ public:
* ONCE per instance and is not thread safe.
*
**/
- virtual void activate(const AsteriskSCF::SessionCommunications::V1::BridgePrx& proxy) = 0;
+ virtual void activate(const AsteriskSCF::SessionCommunications::V1::BridgePrx& proxy,
+ const std::string& id) = 0;
/**
*
@@ -115,6 +116,11 @@ public:
virtual void forceUpdate() = 0;
/**
+ * Internal method for setting the cookies on a this servant.
+ */
+ virtual void setCookiesImpl(const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies) =0;
+
+ /**
*
* For the BridgeManager or any object managing a bridge object! Gets a list of initialized tasks that will add the
* provided sessions to the bridge object in a manner consistent with "Bridge::addSessions()".
diff --git a/src/BridgeManagerImpl.cpp b/src/BridgeManagerImpl.cpp
index 04089a2..d8a343d 100644
--- a/src/BridgeManagerImpl.cpp
+++ b/src/BridgeManagerImpl.cpp
@@ -24,6 +24,7 @@
#include "BridgeImpl.h"
#include "BridgeManagerListenerMgr.h"
#include "BridgeReplicatorIf.h"
+#include "BridgeCreationExtensionPointImpl.h"
#include <AsteriskSCF/System/ExceptionsIf.h>
#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
@@ -35,11 +36,44 @@ using namespace AsteriskSCF::SessionCommunications::V1;
using namespace AsteriskSCF::Core::Discovery::V1;
using namespace AsteriskSCF::BridgeService;
using namespace AsteriskSCF::Replication::BridgeService::V1;
+using namespace AsteriskSCF::SessionCommunications::ExtensionPoints::V1;
using namespace std;
namespace
{
+#ifndef _NDEBUG
+void dump(const Logger& logger, const BridgeCreationHookDataPtr& hookData)
+{
+ ostringstream os;
+ os << "Hook data:";
+ string indent = " ";
+ string prefix = "\n";
+ os << prefix << indent << "decorator/original proxy: " << hookData->bridge;
+ os << prefix << indent << "listeners (" << hookData->listeners.size() << ')';
+
+ for (BridgeListenerSeq::const_iterator i = hookData->listeners.begin(); i != hookData->listeners.end(); ++i)
+ {
+ os << prefix << indent << indent << *i;
+ }
+ os << prefix << indent << "cookies (" << hookData->cookies.size() << ')';
+ for (BridgeCookies::const_iterator i = hookData->cookies.begin(); i != hookData->cookies.end(); ++i)
+ {
+ os << prefix << indent << indent << (*i)->ice_id();
+ }
+ os << prefix << indent << "sessions (" << hookData->initialSessions.size() << ')';
+ for (SessionSeq::const_iterator i = hookData->initialSessions.begin(); i != hookData->initialSessions.end(); ++i)
+ {
+ os << prefix << indent << indent << (*i);
+ }
+ logger(Debug) << os.str();
+}
+#else
+void dump(const Logger&, const BridgeCreationHookDataPtr&)
+{
+}
+#endif
+
class BridgeManagerImpl : public BridgeManagerServant
{
public:
@@ -67,6 +101,7 @@ public:
{
BridgeServantPtr servant;
BridgePrx proxy;
+ BridgePrx decoratingPrx;
};
bool destroyed();
@@ -77,7 +112,7 @@ public:
vector<BridgeServantPtr> getBridges();
- void activate();
+ void activate(const ServiceLocatorManagementPrx& locator);
string getID()
{
@@ -99,6 +134,10 @@ private:
BridgeManagerListenerMgrPtr mListeners;
Logger mLogger;
+ BridgeCreationExtensionPointImplPtr mCreationExtension;
+ BridgeCreationExtensionPointPrx mCreationExtensionPrx;
+ ServiceManagementPrx mCreationExtensionPointServicePrx;
+
BridgeManagerStateItemPtr mState;
void reap();
@@ -154,6 +193,7 @@ protected:
{
mListenerMgr->bridgeCreated(mBridgeProxy);
}
+
mCallback->ice_response(mBridgeProxy);
return true;
}
@@ -182,30 +222,99 @@ void BridgeManagerImpl::createBridge_async(const AMD_BridgeManager_createBridgeP
string stringId = string("bridge.") + IceUtil::generateUUID();
Ice::Identity id(mAdapter->getCommunicator()->stringToIdentity(stringId));
BridgePrx prx(BridgePrx::uncheckedCast(mAdapter->createProxy(id)));
- BridgeListenerMgrPtr mgr(new BridgeListenerMgr(mAdapter->getCommunicator(), stringId, prx));
- vector<BridgeListenerPrx> listeners(mState->defaultBridgeListeners);
+ AsteriskSCF::SessionCommunications::V1::BridgeListenerSeq listeners(mState->defaultBridgeListeners);
if (listener)
{
listeners.push_back(listener);
}
+ //
+ // "sessions" is a const, so we need to make a local non-const copy that can be modified
+ // by the hooks if need be.
+ //
+ SessionSeq initialSessions(sessions);
+
+ //
+ // We create a local outside of the block that initializes and runs the hooks if they are
+ // present. If this is '0' later on in the code, it signifies the bridge creation extension
+ // point mechanism was not initialized.
+ //
+ BridgeCreationHookDataPtr hookData;
+ BridgeInfo info;
+ info.proxy = prx;
+ if (mCreationExtension)
+ {
+ //
+ // Set up hook data with initial values and run the hooks!
+ //
+ hookData = new BridgeCreationHookData;
+ hookData->bridge = prx;
+ hookData->listeners = listeners;
+ hookData->initialSessions = sessions;
+ hookData = mCreationExtension->runHooks(hookData);
+
+ //
+ // Update locals with the result of running the hooks.
+ //
+ listeners = hookData->listeners;
+ initialSessions = hookData->initialSessions;
+ info.decoratingPrx = hookData->bridge;
+ dump(mLogger, hookData);
+ }
+
+ //
+ // The bridge listener manager is a wrapper/helper class that manages the listeners and
+ // propogates the bridge events. We separate it's instantiation from the construction
+ // of the bridge itself as this is a natural area of refinement and extension.
+ //
+ BridgeListenerMgrPtr mgr(new BridgeListenerMgr(mAdapter->getCommunicator(), stringId, info.decoratingPrx));
+
+ //
+ // Now we can get down to the creation of the bridge servant itself. Note that the
+ // initialization is still not really complete as we need to set up and cookies,
+ // initial sessions, etc that may have been defined or added as part of the createBridge
+ // call or the bridge creation hooks.
+ //
BridgeServantPtr bridge = BridgeServant::create(stringId, mAdapter, listeners, mgr, mReplicationContext->getReplicator(), mLogger);
+
Ice::ObjectPrx obj = mAdapter->add(bridge, id);
mLogger(Info) << objectIdFromCurrent(current) << ": creating new bridge " << obj->ice_toString() << "." ;
- BridgeInfo info;
+
+ //
+ // Finish updating BridgeInfo struct.
+ //
info.servant = bridge;
- info.proxy = BridgePrx::uncheckedCast(obj);
- bridge->activate(info.proxy);
+
+ //
+ // It's very important to note that the bridge servant will not have it's own proxy!
+ // NOTE: This method is probably misnamed and misleading. The bridge servant was added to
+ // object adapter above. It might be a better idea to move adding the servant to the adapter
+ // into the activate method.
+ //
+ bridge->activate(info.decoratingPrx, stringId);
mBridges.push_back(info);
+ if (hookData)
+ {
+ bridge->setCookiesImpl(hookData->cookies);
+ }
+
+ //
+ // There are some finalization tasks that may be performed asynchronously (replication etc.)
+ //
QueuedTasks tasks;
- if (!sessions.empty())
+
+ //
+ // If there are some sessions that need to be added to the bridge immediately
+ // upon creation, create some tasks to add to the queue.
+ //
+ if (!initialSessions.empty())
{
- bridge->getAddSessionsTasks(tasks, sessions);
+ bridge->getAddSessionsTasks(tasks, initialSessions);
}
-
- tasks.push_back(new FinishUp(callback, mListeners, info.proxy));
+
+ tasks.push_back(new FinishUp(callback, mListeners, info.decoratingPrx));
ExecutorPtr runner(new Executor(tasks, mLogger));
runner->start();
}
@@ -326,6 +435,17 @@ void BridgeManagerImpl::shutdown(const Ice::Current& current)
{
mListeners->stopped();
}
+ try
+ {
+ if (mCreationExtensionPointServicePrx)
+ {
+ mCreationExtensionPointServicePrx->unregister();
+ }
+ }
+ catch (const std::exception& ex)
+ {
+ mLogger(Debug) << ex.what() << " caught while shutting down and unregistering supporting services.";
+ }
mAdapter->getCommunicator()->shutdown();
mState->runningState = AsteriskSCF::Replication::BridgeService::V1::Destroyed;
}
@@ -371,13 +491,39 @@ vector<BridgeServantPtr> BridgeManagerImpl::getBridges()
return result;
}
-void BridgeManagerImpl::activate()
+void BridgeManagerImpl::activate(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagementPrx& locator)
{
- boost::unique_lock<boost::shared_mutex> lock(mLock);
- for (BridgeManagerListenerSeq::iterator i = mState->listeners.begin(); i != mState->listeners.end(); ++i)
{
- mListeners->addListener(*i);
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ if (mCreationExtension)
+ {
+ return;
+ }
+
+ for (BridgeManagerListenerSeq::iterator i = mState->listeners.begin(); i != mState->listeners.end(); ++i)
+ {
+ mListeners->addListener(*i);
+ }
+ mCreationExtension = BridgeCreationExtensionPointImpl::create(mLogger);
}
+ Ice::Identity myId = mAdapter->getCommunicator()->stringToIdentity(mName);
+
+ //
+ // Incarnated as a facet as a convenience. Also added to the service locator though, so all is fine with our
+ // requirements vis-a-vis "good objects".
+ //
+ mCreationExtensionPrx =
+ BridgeCreationExtensionPointPrx::uncheckedCast(mAdapter->addFacet(mCreationExtension, myId, BridgeCreationExtensionPointFacet));
+
+ string extPtId = IceUtil::generateUUID();
+
+ // Configure how other components look this component up.
+ ServiceLocatorParamsPtr params = new ServiceLocatorParams;
+ params->category = BridgeCreationExtensionPointCategory;
+ params->service = extPtId;
+
+ mCreationExtensionPointServicePrx = locator->addService(mCreationExtensionPrx, extPtId);
+ mCreationExtensionPointServicePrx->addLocatorParams(params, "");
}
void BridgeManagerImpl::createBridgeReplica(const BridgeStateItemPtr& state)
diff --git a/src/BridgeManagerImpl.h b/src/BridgeManagerImpl.h
index 62090a2..163d5df 100644
--- a/src/BridgeManagerImpl.h
+++ b/src/BridgeManagerImpl.h
@@ -17,6 +17,7 @@
#include <Ice/Ice.h>
#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
#include <AsteriskSCF/logger.h>
#include <string>
#include <vector>
@@ -49,7 +50,7 @@ public:
virtual std::vector<BridgeServantPtr> getBridges() = 0;
- virtual void activate() = 0;
+ virtual void activate(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorManagementPrx&) = 0;
virtual std::string getID() = 0;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c7fbc72..839fd48 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -22,6 +22,8 @@ astscf_component_add_files(bridgeservice SessionCollection.cpp)
astscf_component_add_files(bridgeservice SessionCollection.h)
astscf_component_add_files(bridgeservice SessionOperations.cpp)
astscf_component_add_files(bridgeservice SessionOperations.h)
+astscf_component_add_files(bridgeservice BridgeCreationExtensionPointImpl.cpp)
+astscf_component_add_files(bridgeservice BridgeCreationExtensionPointImpl.h)
astscf_component_add_files(bridgeservice ServiceUtil.h)
astscf_component_add_files(bridgeservice DebugUtil.h)
astscf_component_add_files(bridgeservice MediaSplicer.h)
diff --git a/src/Component.cpp b/src/Component.cpp
index 41f7d7f..595011a 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -99,13 +99,17 @@ void Component::onPostInitialize()
{
if (getReplicationContext()->isActive())
{
- mBridgeManager->activate();
+ mBridgeManager->activate(getServiceLocatorManagement());
}
}
void Component::onActivated()
{
- mBridgeManager->activate(); // TBD...Is this really needed? Is there really no standby() correlary?
+ mBridgeManager->activate(getServiceLocatorManagement()); // TBD...Is this really needed? Is there really no standby() correlary?
+ //
+ // Response to TBD. None of the AsteriskSCF components support moving from active to standby.. the presumption
+ // being that if you are active, the only way you are going to be moved to standby is if you are restarted.
+ //
}
void Component::onPreInitialize()
diff --git a/test/BridgeListenerI.h b/test/BridgeListenerI.h
index 05f12b9..7040486 100644
--- a/test/BridgeListenerI.h
+++ b/test/BridgeListenerI.h
@@ -55,6 +55,7 @@ public:
private:
bool mShuttingDown;
bool mStopped;
+ bool mStopping;
IceUtil::Monitor<IceUtil::Mutex> mAddMonitor;
IceUtil::Monitor<IceUtil::Mutex> mRemoveMonitor;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6f2f1af..9773c64 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -26,11 +26,11 @@ target_link_libraries(bridge_component_test logging-client)
astscf_test_icebox(bridge_component_test config/test_bridging.conf)
astscf_component_init(bridge_unit_tests)
-astscf_component_add_slices(bridge_unit_tests PROJECT AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice)
astscf_component_add_files(bridge_unit_tests ../src/SessionCollection.cpp)
astscf_component_add_files(bridge_unit_tests ../src/SessionOperations.cpp)
astscf_component_add_files(bridge_unit_tests ../src/SessionWrapper.cpp)
astscf_component_add_files(bridge_unit_tests ../src/MediaSplicer.cpp)
+astscf_component_add_slices(bridge_unit_tests PROJECT AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice)
astscf_component_add_files(bridge_unit_tests UnitTests.cpp)
astscf_component_add_ice_libraries(bridge_unit_tests Ice)
astscf_component_add_boost_libraries(bridge_unit_tests unit_test_framework thread)
diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index f988c68..b7efa3f 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -20,6 +20,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/test/debug.hpp>
#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsExtensionPointsIf.h>
#include <AsteriskSCF/Media/MediaIf.h>
#include <AsteriskSCF/System/Component/ReplicaIf.h>
#include <IceUtil/UUID.h>
@@ -40,6 +41,7 @@
using namespace AsteriskSCF::BridgingTest;
using namespace AsteriskSCF::SessionCommunications::V1;
+using namespace AsteriskSCF::SessionCommunications::ExtensionPoints::V1;
using namespace AsteriskSCF::Core::Discovery::V1;
using namespace AsteriskSCF::Core::Routing::V1;
using namespace AsteriskSCFTest;
@@ -50,6 +52,48 @@ using namespace std;
namespace
{
+class TestCreationHook : public BridgeCreationHook
+{
+public:
+
+ void addCookies(const BridgeCookies& cookies)
+ {
+ mCookies = cookies;
+ }
+
+ void addListeners(const BridgeListenerSeq& listeners)
+ {
+ mListeners = listeners;
+ }
+
+ void addSessions(const SessionSeq& sessions)
+ {
+ mSessions = sessions;
+ }
+
+ void setResult(AsteriskSCF::System::Hook::V1::HookResult resultValue)
+ {
+ mResult = resultValue;
+ }
+
+ AsteriskSCF::System::Hook::V1::HookResult execute(const BridgeCreationHookDataPtr& originalData,
+ BridgeCreationHookDataPtr& newData, const Ice::Current&)
+ {
+ newData = BridgeCreationHookDataPtr::dynamicCast(originalData->ice_clone());
+ newData->cookies.insert(newData->cookies.end(), mCookies.begin(), mCookies.end());
+ newData->listeners.insert(newData->listeners.end(), mListeners.begin(), mListeners.end());
+ newData->initialSessions.insert(newData->initialSessions.end(), mSessions.begin(), mSessions.end());
+ return mResult;
+ }
+
+private:
+ BridgeCookies mCookies;
+ BridgeListenerSeq mListeners;
+ SessionSeq mSessions;
+ AsteriskSCF::System::Hook::V1::HookResult mResult;
+};
+typedef IceUtil::Handle<TestCreationHook> TestCreationHookPtr;
+
BridgeCookies bakeTestCookies()
{
BridgeCookies result;
@@ -935,7 +979,7 @@ public:
//
mgrPrx->listBridges();
- BOOST_CHECK(servant->createCalls() == 1);
+ BOOST_CHECK(servant->createCalls() == 1);
mgrPrx->removeListener(listenerPrx);
bridge = mgrPrx->createBridge(sessions, 0);
@@ -1075,13 +1119,12 @@ public:
returnedCookies = cookieMap["sessionsRemoved"];
tasteCookies(returnedCookies);
- BOOST_REQUIRE(bridgeListener->waitForStopped(5000));
+ BOOST_REQUIRE(bridgeListener->waitForStopping(5000));
cookieMap = bridgeListener->getCookieMap();
BOOST_REQUIRE(cookieMap.find("stopping") != cookieMap.end());
returnedCookies = cookieMap["stopping"];
tasteCookies(returnedCookies);
- BOOST_REQUIRE(cookieMap.find("stopped") != cookieMap.end());
- returnedCookies = cookieMap["stopped"];
+ BOOST_REQUIRE(bridgeListener->waitForStopped(5000));
BOOST_REQUIRE(!returnedCookies.empty());
tasteCookies(returnedCookies);
returnedCookies = bridge->getCookies(cookies);
@@ -1204,6 +1247,110 @@ public:
}
}
+ void extensionPointTest()
+ {
+ try
+ {
+ IceEnvironment testEnv(env()->properties());
+ try
+ {
+ Ice::ObjectAdapterPtr testAdapter = testEnv.communicator()->createObjectAdapter("TestUtilAdapter");
+ testAdapter->activate();
+ BridgeManagerListenerIPtr servant = new BridgeManagerListenerI;
+ AsteriskSCF::SessionCommunications::V1::BridgeManagerListenerPrx listenerPrx;
+ addServant(listenerPrx, testAdapter, servant, testEnv.strToIdent(IceUtil::generateUUID()));
+
+ AsteriskSCF::SessionCommunications::V1::BridgeManagerPrx mgrPrx = env()->primaryBridgeManager();
+ BOOST_CHECK(mgrPrx);
+ mgrPrx->addListener(listenerPrx);
+ BOOST_CHECK(servant->stoppingCalls() == 0);
+ BOOST_CHECK(servant->stoppedCalls() == 0);
+ BOOST_CHECK(servant->createCalls() == 0);
+
+ AsteriskSCF::SessionCommunications::ExtensionPoints::V1::BridgeCreationExtensionPointPrx
+ extPoint = AsteriskSCF::SessionCommunications::ExtensionPoints::V1::
+ BridgeCreationExtensionPointPrx::checkedCast(mgrPrx,
+ AsteriskSCF::SessionCommunications::ExtensionPoints::V1::BridgeCreationExtensionPointFacet);
+ BOOST_REQUIRE(extPoint);
+
+ TestCreationHookPtr hook(new TestCreationHook);
+ AsteriskSCF::SessionCommunications::ExtensionPoints::V1::BridgeCreationHookPrx hookPrx;
+ addServant(hookPrx, testAdapter, hook, testEnv.strToIdent(IceUtil::generateUUID()));
+ extPoint->addHook(hookPrx);
+
+ TestChannelWrapper channel(env()->properties());
+ AsteriskSCF::SessionCommunications::V1::SessionSeq sessions;
+ AsteriskSCF::SessionCommunications::V1::SessionPrx a = channel.getSession("311");
+ AsteriskSCF::SessionCommunications::V1::SessionPrx b = channel.getSession("312");
+ sessions.push_back(a);
+ sessions.push_back(b);
+ hook->addSessions(sessions);
+ sessions.clear();
+
+ AsteriskSCF::BridgingTest::BridgeListenerPtr bridgeListener = new BridgeListenerI;
+ AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx bridgeListenerPrx;
+ addServant(bridgeListenerPrx, testAdapter, bridgeListener, testEnv.strToIdent(IceUtil::generateUUID()));
+ BridgeListenerSeq listeners;
+ listeners.push_back(bridgeListenerPrx);
+ hook->addListeners(listeners);
+
+ BridgeCookies testCookies = bakeTestCookies();
+ hook->addCookies(testCookies);
+
+ AsteriskSCF::SessionCommunications::V1::BridgePrx bridge(mgrPrx->createBridge(sessions, 0));
+
+ //
+ // precondition checks for test validity.
+ //
+ std::string idA = testEnv.communicator()->identityToString(a->ice_getIdentity());
+ std::string idB = testEnv.communicator()->identityToString(b->ice_getIdentity());
+ std::vector<std::string> log;
+ channel.commands()->getlog(idA, log);
+ BOOST_CHECK(!find(log, "start"));
+ channel.commands()->getlog(idB, log);
+ BOOST_CHECK(!find(log, "start"));
+
+ AsteriskSCF::SessionCommunications::V1::SessionSeq eventSessions;
+ BridgeCookies returnedCookies = bridge->getCookies(testCookies);
+ tasteCookies(returnedCookies);
+
+ sessions.push_back(b);
+ eventSessions.clear();
+ bridge->removeSessions(sessions);
+ BOOST_REQUIRE(bridgeListener->waitForRemoved(5000, eventSessions));
+ CookieMap cookieMap = bridgeListener->getCookieMap();
+ BOOST_REQUIRE(!cookieMap.empty());
+ BOOST_REQUIRE(cookieMap.find("sessionsRemoved") != cookieMap.end());
+ returnedCookies = cookieMap["sessionsRemoved"];
+ tasteCookies(returnedCookies);
+
+ BOOST_REQUIRE(bridgeListener->waitForStopped(5000));
+ cookieMap = bridgeListener->getCookieMap();
+ BOOST_REQUIRE(cookieMap.find("stopping") != cookieMap.end());
+ returnedCookies = cookieMap["stopping"];
+ tasteCookies(returnedCookies);
+ BOOST_REQUIRE(cookieMap.find("stopped") != cookieMap.end());
+ returnedCookies = cookieMap["stopped"];
+ BOOST_REQUIRE(!returnedCookies.empty());
+ tasteCookies(returnedCookies);
+ }
+ catch (const Ice::Exception& ex)
+ {
+ std::ostringstream msg;
+ msg << "Unexpected Ice exception " << ex.what();
+ BOOST_FAIL(msg.str());
+ }
+ catch (...)
+ {
+ BOOST_FAIL("Unexpected exception");
+ }
+ }
+ catch (...)
+ {
+ BOOST_FAIL("Unexpected exception");
+ }
+ }
+
private:
TestEnvironmentPtr mTestEnvironment;
};
@@ -1231,6 +1378,8 @@ bool init_unit_test()
add(BOOST_TEST_CASE(boost::bind(&BridgeTester::simpleCookieAddTest, bridgeTester)));
framework::master_test_suite().
add(BOOST_TEST_CASE(boost::bind(&BridgeTester::cookieAddRemoveTest, bridgeTester)));
+ framework::master_test_suite().
+ add(BOOST_TEST_CASE(boost::bind(&BridgeTester::extensionPointTest, bridgeTester)));
return true;
}
-----------------------------------------------------------------------
--
asterisk-scf/release/bridging.git
More information about the asterisk-scf-commits
mailing list