[asterisk-scf-commits] asterisk-scf/integration/routing.git branch "route_replica" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Tue May 3 01:24:17 CDT 2011
branch "route_replica" has been updated
via 5371f62b5bd84e2371d8ecfbe51e429a09f5a74d (commit)
from a6984b9b7ad5b5f0ba7db843876bc90949589dfd (commit)
Summary of changes:
src/BasicRoutingServiceApp.cpp | 1 -
...nectBridgedSessionsWithDestinationOperation.cpp | 143 +++++++++-------
...onnectBridgedSessionsWithDestinationOperation.h | 6 +
src/RouteSessionOperation.cpp | 151 ++++++++++-------
src/RouteSessionOperation.h | 6 +
src/RoutingStateReplicatorListener.cpp | 46 +++++
src/SessionRouterOperation.h | 8 +-
test/MockEndpointLocator.cpp | 6 +
test/MockEndpointLocator.h | 4 +
test/SharedTestData.h | 2 +
test/TestRouting.cpp | 175 ++++++++++++++++++++
11 files changed, 425 insertions(+), 123 deletions(-)
- Log -----------------------------------------------------------------
commit 5371f62b5bd84e2371d8ecfbe51e429a09f5a74d
Author: Ken Hunt <ken.hunt at digium.com>
Date: Tue May 3 01:23:32 2011 -0500
Additional testing and bug fixes to verify the replicated operations function
as expected.
diff --git a/src/BasicRoutingServiceApp.cpp b/src/BasicRoutingServiceApp.cpp
index 4e31eaa..26e0b8b 100644
--- a/src/BasicRoutingServiceApp.cpp
+++ b/src/BasicRoutingServiceApp.cpp
@@ -80,7 +80,6 @@ public:
mWorkQueue( new AsteriskSCF::Threading::SimpleWorkQueue("SessionRouterWorkQueue")),
mListeningToReplicator(false)
{
- lg.setLevel(Error);
}
~BasicRoutingServiceApp()
diff --git a/src/ConnectBridgedSessionsWithDestinationOperation.cpp b/src/ConnectBridgedSessionsWithDestinationOperation.cpp
index 4c174f7..e985f52 100644
--- a/src/ConnectBridgedSessionsWithDestinationOperation.cpp
+++ b/src/ConnectBridgedSessionsWithDestinationOperation.cpp
@@ -68,18 +68,39 @@ public:
return;
}
- if (state == ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP)
+ switch(state)
{
- // Push this information to the state replicator.
- ConnectBridgedSessionsWithDestinationOpStartPtr
- opStart(new ConnectBridgedSessionsWithDestinationOpStart());
- opStart->operationId = mOperation->getOperationId();
- opStart->key = mOperation->getOperationId() +
- AsteriskSCF::BasicRoutingService::V1::ConnectBridgedSessionsWithDestStartKeyMod;
- opStart->sessionToReplace = mOperation->getSessionToReplace();
- opStart->destination = mOperation->getDestination();
-
- pushState(opStart);
+ case ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP:
+ {
+ // Push this information to the state replicator.
+ ConnectBridgedSessionsWithDestinationOpStartPtr
+ opStart(new ConnectBridgedSessionsWithDestinationOpStart());
+ opStart->operationId = mOperation->getOperationId();
+ opStart->key = mOperation->getOperationId() +
+ AsteriskSCF::BasicRoutingService::V1::ConnectBridgedSessionsWithDestStartKeyMod;
+ opStart->sessionToReplace = mOperation->getSessionToReplace();
+ opStart->destination = mOperation->getDestination();
+
+ pushState(opStart);
+ }
+ break;
+
+ case ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING:
+ {
+ // We've obtained a result from our AMI lookup request.
+ ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr
+ waitLookup(new ConnectBridgedSessionsWithDestinationOpWaitLookupState());
+ waitLookup->operationId = mOperation->getOperationId();
+ waitLookup->key = mOperation->getOperationId() +
+ AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
+ waitLookup->endpoints = mOperation->getLookupResult();
+
+ pushState(waitLookup);
+ }
+ break;
+
+ default:
+ break;
}
}
@@ -99,47 +120,6 @@ public:
*/
void stateExecutionComplete(ConnectBridgedSessionsWithDestinationOp::OperationState state)
{
- if (!mReplicationContext->isReplicating())
- {
- return;
- }
-
- switch(state)
- {
- case ConnectBridgedSessionsWithDestinationOp::STATE_WAIT_LOOKUP_RESULTS:
- {
- // We just completed the entire operation.
- // Push this information to the state replicator.
- ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr
- waitLookup(new ConnectBridgedSessionsWithDestinationOpWaitLookupState());
- waitLookup->operationId = mOperation->getOperationId();
- waitLookup->key = mOperation->getOperationId() +
- AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
- waitLookup->endpoints = mOperation->getLookupResult();
-
- pushState(waitLookup);
- }
- break;
-
- case ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING:
- {
- // We just completed creating a bridge.
- // Push this information to the state replicator.
- ConnectBridgedSessionsWithDestinationOpBridgingStatePtr
- bridgeOp(new ConnectBridgedSessionsWithDestinationOpBridgingState());
- bridgeOp->operationId = mOperation->getOperationId();
- bridgeOp->key = mOperation->getOperationId() +
- AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
- bridgeOp->bridge = mOperation->getBridge();
-
- pushState(bridgeOp);
- }
- break;
-
- default:
- break;
-
- } // end switch
}
/**
@@ -169,9 +149,35 @@ public:
* @param oldState The state transitioning from.
* @param newState The state transitioning to.
*/
- void stateTransition(ConnectBridgedSessionsWithDestinationOp::OperationState,
+ void stateTransition(ConnectBridgedSessionsWithDestinationOp::OperationState oldState,
ConnectBridgedSessionsWithDestinationOp::OperationState)
{
+ if (!mReplicationContext->isReplicating())
+ {
+ return;
+ }
+
+ switch(oldState)
+ {
+ case ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING:
+ {
+ // We just completed creating a bridge.
+ // Push this information to the state replicator.
+ ConnectBridgedSessionsWithDestinationOpBridgingStatePtr
+ bridgeOp(new ConnectBridgedSessionsWithDestinationOpBridgingState());
+ bridgeOp->operationId = mOperation->getOperationId();
+ bridgeOp->key = mOperation->getOperationId() +
+ AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
+ bridgeOp->bridge = mOperation->getBridge();
+
+ pushState(bridgeOp);
+ }
+ break;
+
+ default:
+ break;
+
+ } // end switch
}
private:
@@ -333,7 +339,7 @@ bool ConnectBridgedSessionsWithDestinationOperation::fastForwardReplica()
return false;
}
// Set to initial state.
- mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP);
+ mStateMachine.resetStartState(ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP);
// See if we got the results from the lookup.
i = find(mReplicatedStates.begin(), mReplicatedStates.end(), ConnectBridgedSessionsWithDestinationOp::STATE_WAIT_LOOKUP_RESULTS);
@@ -341,7 +347,9 @@ bool ConnectBridgedSessionsWithDestinationOperation::fastForwardReplica()
{
return true;
}
- mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING);
+
+ addListenerManager();
+ mStateMachine.resetStartState(ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING);
// See if we got past bridge creation.
i = find(mReplicatedStates.begin(), mReplicatedStates.end(), ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING);
@@ -351,10 +359,15 @@ bool ConnectBridgedSessionsWithDestinationOperation::fastForwardReplica()
}
// Apparently nothing left to do but reply to the AMD callback.
- mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_SEND_RESPONSE);
+ mStateMachine.resetStartState(ConnectBridgedSessionsWithDestinationOp::STATE_SEND_RESPONSE);
return true;
}
+void ConnectBridgedSessionsWithDestinationOperation::addListenerManager()
+{
+ mListenerManager.reset(new SessionListenerManager(mSessionContext->adapter, this->mSessionToReplace));
+}
+
/**
* This is a state handler for one of this operation's states.
*/
@@ -382,11 +395,7 @@ void ConnectBridgedSessionsWithDestinationOperation::lookupState()
return;
}
- // Create a listener for the sessions not being replaced to handle early termination.
- // The wrapper we're using will remove the listener and free it when
- // this method is left.
- lg(Debug) << BOOST_CURRENT_FUNCTION << ": Attaching listener";
- mListenerManager = SessionListenerManagerPtr(new SessionListenerManager(mSessionContext->adapter, mSessionToReplace));
+ addListenerManager();
// Route the destination
lg(Debug) << BOOST_CURRENT_FUNCTION << ": Routing destination " << mDestination;
@@ -482,6 +491,18 @@ void ConnectBridgedSessionsWithDestinationOperation::establishBridgeState()
return;
}
+ // Test instrumentation
+ if (mSessionContext->replicationContext->getTestContext().get() != 0)
+ {
+ if (mSessionContext->replicationContext->getTestContext()->getTestMode() == "ConnectBridgedSessWithDestFailover")
+ {
+ // We're going to just shutdown this operation right here, with no replies to the caller.
+ // This is so that an external test can verify the replica can take it the rest of the way.
+ finish();
+ return;
+ }
+ }
+
// Set the state handler to exectute once we've looked up our endpoints.
mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_SEND_RESPONSE);
diff --git a/src/ConnectBridgedSessionsWithDestinationOperation.h b/src/ConnectBridgedSessionsWithDestinationOperation.h
index 8e00ece..ce1fa63 100644
--- a/src/ConnectBridgedSessionsWithDestinationOperation.h
+++ b/src/ConnectBridgedSessionsWithDestinationOperation.h
@@ -149,6 +149,12 @@ private:
*/
void sendResponseState();
+ /**
+ * Add listener to watch fo early termination of the operation
+ * by the client.
+ */
+ void addListenerManager();
+
private:
// Operation input params.
AsteriskSCF::SessionCommunications::V1::SessionPrx mSessionToReplace;
diff --git a/src/RouteSessionOperation.cpp b/src/RouteSessionOperation.cpp
index 3710edc..d7ce95d 100644
--- a/src/RouteSessionOperation.cpp
+++ b/src/RouteSessionOperation.cpp
@@ -20,6 +20,7 @@
#include "BasicRoutingStateReplicationIf.h"
#include "RouteSessionOperation.h"
+#include "TestContext.h"
using namespace AsteriskSCF;
using namespace AsteriskSCF::Core::Routing::V1;
@@ -69,18 +70,38 @@ public:
return;
}
- if (state == RouteSessionOp::STATE_LOOKUP)
+ switch(state)
{
- // This is the initial state. All the state of interest is what's been passed in.
- // Push this information to the state replicator.
- RouteSessionOpStartPtr routeSessionOpStart(new RouteSessionOpStart());
- routeSessionOpStart->operationId = mOperation->getOperationId();
- routeSessionOpStart->key = mOperation->getOperationId() +
- AsteriskSCF::BasicRoutingService::V1::RouteSessionOpStartKeyMod;
- routeSessionOpStart->source = mOperation->getSource();
- routeSessionOpStart->destination = mOperation->getDestination();
-
- pushState(routeSessionOpStart);
+ case RouteSessionOp::STATE_LOOKUP:
+ {
+ // This is the initial state. All the state of interest is what's been passed in.
+ // Push this information to the state replicator.
+ RouteSessionOpStartPtr routeSessionOpStart(new RouteSessionOpStart());
+ routeSessionOpStart->operationId = mOperation->getOperationId();
+ routeSessionOpStart->key = mOperation->getOperationId() +
+ AsteriskSCF::BasicRoutingService::V1::RouteSessionOpStartKeyMod;
+ routeSessionOpStart->source = mOperation->getSource();
+ routeSessionOpStart->destination = mOperation->getDestination();
+
+ pushState(routeSessionOpStart);
+ }
+ break;
+
+ case RouteSessionOp::STATE_BRIDGING:
+ {
+ // We've obtained a result from our AMI lookup request.
+ RouteSessionOpWaitLookupStatePtr routeSessionOpWaitLookup(new RouteSessionOpWaitLookupState());
+ routeSessionOpWaitLookup->operationId = mOperation->getOperationId();
+ routeSessionOpWaitLookup->key = mOperation->getOperationId() +
+ AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
+ routeSessionOpWaitLookup->endpoints = mOperation->getLookupResult();
+
+ pushState(routeSessionOpWaitLookup);
+ }
+ break;
+
+ default:
+ break;
}
}
@@ -100,47 +121,7 @@ public:
*/
void stateExecutionComplete(RouteSessionOp::OperationState state)
{
- if (!mReplicationContext->isReplicating())
- {
- return;
- }
- switch(state)
- {
- case RouteSessionOp::STATE_WAIT_LOOKUP_RESULTS:
- {
- // We've obtained a result from our AMI lookup request.
- RouteSessionOpWaitLookupStatePtr routeSessionOpWaitLookup(new RouteSessionOpWaitLookupState());
- routeSessionOpWaitLookup->operationId = mOperation->getOperationId();
- routeSessionOpWaitLookup->key = mOperation->getOperationId() +
- AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
- routeSessionOpWaitLookup->endpoints = mOperation->getLookupResult();
-
- pushState(routeSessionOpWaitLookup);
- }
- break;
-
- case RouteSessionOp::STATE_BRIDGING:
- {
- // We just completed the bridge creation.
- // Push this information to the state replicator.
- RouteSessionOpBridgingStatePtr routeSessionOpBridging(new RouteSessionOpBridgingState());
- routeSessionOpBridging->operationId = mOperation->getOperationId();
- routeSessionOpBridging->key = mOperation->getOperationId() +
- AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
- routeSessionOpBridging->bridge = mOperation->getBridge();
-
- pushState(routeSessionOpBridging);
- }
- break;
-
- case RouteSessionOp::STATE_SEND_RESPONSE:
- // The AMD caller has been notified. We'll remove the replica in shutdown() handler.
- break;
-
- default:
- break;
- }
}
/**
@@ -168,9 +149,37 @@ public:
/**
* This callback is called when a state transition is occuring.
*/
- void stateTransition(RouteSessionOp::OperationState, // oldState
+ void stateTransition(RouteSessionOp::OperationState oldState, // oldState
RouteSessionOp::OperationState) // newState
{
+ if (!mReplicationContext->isReplicating())
+ {
+ return;
+ }
+
+ switch(oldState)
+ {
+ case RouteSessionOp::STATE_BRIDGING:
+ {
+ // We just completed the bridge creation.
+ // Push this information to the state replicator.
+ RouteSessionOpBridgingStatePtr routeSessionOpBridging(new RouteSessionOpBridgingState());
+ routeSessionOpBridging->operationId = mOperation->getOperationId();
+ routeSessionOpBridging->key = mOperation->getOperationId() +
+ AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
+ routeSessionOpBridging->bridge = mOperation->getBridge();
+
+ pushState(routeSessionOpBridging);
+ }
+ break;
+
+ case RouteSessionOp::STATE_SEND_RESPONSE:
+ // The AMD caller has been notified. We'll remove the replica in shutdown() handler.
+ break;
+
+ default:
+ break;
+ }
}
private:
@@ -330,7 +339,7 @@ bool RouteSessionOperation::fastForwardReplica()
return false;
}
// Set to initial state.
- mStateMachine.setNextState(RouteSessionOp::STATE_LOOKUP);
+ mStateMachine.resetStartState(RouteSessionOp::STATE_LOOKUP);
// See if we got the results from the lookup.
i = find(mReplicatedStates.begin(), mReplicatedStates.end(), RouteSessionOp::STATE_WAIT_LOOKUP_RESULTS);
@@ -338,7 +347,12 @@ bool RouteSessionOperation::fastForwardReplica()
{
return true;
}
- mStateMachine.setNextState(RouteSessionOp::STATE_BRIDGING);
+
+ addListenerManager();
+
+ lg(Debug) << "Fast-forwarded replica of RouteSessionOperation to STATE_BRIDGING for " << mOperationId;
+
+ mStateMachine.resetStartState(RouteSessionOp::STATE_BRIDGING);
// See if we got past bridge creation.
i = find(mReplicatedStates.begin(), mReplicatedStates.end(), RouteSessionOp::STATE_BRIDGING);
@@ -348,7 +362,8 @@ bool RouteSessionOperation::fastForwardReplica()
}
// Apparently nothing left to do but reply to the AMD callback.
- mStateMachine.setNextState(RouteSessionOp::STATE_SEND_RESPONSE);
+ lg(Debug) << "Fast-forwarded replica of RouteSessionOperation to STATE_SEND_RESPONSE for " << mOperationId;
+ mStateMachine.resetStartState(RouteSessionOp::STATE_SEND_RESPONSE);
return true;
}
@@ -358,6 +373,14 @@ RouteSessionOperation::~RouteSessionOperation()
}
/**
+ * Create a listener for the source to handle early termination.
+ */
+void RouteSessionOperation::addListenerManager()
+{
+ mListenerManager.reset(new SessionListenerManager(mSessionContext->adapter, mSource));
+}
+
+/**
* This is a state handler for one of this operation's states.
* This method is called via mCurrentStateHandler when doWork() is executed from the
* WorkQueue.
@@ -375,11 +398,7 @@ void RouteSessionOperation::lookupState()
return;
}
- // Create a listener for the source to handle early termination.
- // The wrapper we're using will remove the listener and free it when
- // this method is left.
- SessionListenerManagerPtr listener(new SessionListenerManager(mSessionContext->adapter, mSource));
- mListenerManager = listener;
+ addListenerManager();
// Set the state handler to exectute once we've looked up our endpoints.
mStateMachine.setNextState(RouteSessionOp::STATE_WAIT_LOOKUP_RESULTS);
@@ -422,6 +441,18 @@ void RouteSessionOperation::establishBridgeState()
return;
}
+ // Test instrumentation
+ if (mSessionContext->replicationContext->getTestContext().get() != 0)
+ {
+ if (mSessionContext->replicationContext->getTestContext()->getTestMode() == "RouteSessionFailover")
+ {
+ // We're going to just shutdown this operation right here, with no replies to the caller.
+ // This is so that an external test can verify the replica can take it the rest of the way.
+ finish();
+ return;
+ }
+ }
+
assert(mLookupResult.size() > 0); // This exception should have been handled in EndpointRegistry.
if (mLookupResult.size() < 1)
diff --git a/src/RouteSessionOperation.h b/src/RouteSessionOperation.h
index 2f8059c..39d96e9 100644
--- a/src/RouteSessionOperation.h
+++ b/src/RouteSessionOperation.h
@@ -162,6 +162,12 @@ private:
*/
void sendResponseState();
+ /**
+ * Add listener to watch fo early termination of the operation
+ * by the client.
+ */
+ void addListenerManager();
+
private:
// Operation input params.
AsteriskSCF::SessionCommunications::V1::SessionPrx mSource;
diff --git a/src/RoutingStateReplicatorListener.cpp b/src/RoutingStateReplicatorListener.cpp
index 3f0691e..f811416 100644
--- a/src/RoutingStateReplicatorListener.cpp
+++ b/src/RoutingStateReplicatorListener.cpp
@@ -131,6 +131,52 @@ public:
RoutingStateReplicatorListenerPriv *mImpl;
const Ice::Current& mCurrent;
+ // Used an intermediate class in the slice types, and the visitor didn't pick up the leaf classes to visit.
+ void visitOperationStateItem(const ::AsteriskSCF::BasicRoutingService::V1::OperationStateItemPtr& operation)
+ {
+ RouteSessionOpStartPtr routeSessinOpStart = RouteSessionOpStartPtr::dynamicCast(operation);
+ if (routeSessinOpStart != 0)
+ {
+ visitRouteSessionOpStart(routeSessinOpStart);
+ return;
+ }
+
+ RouteSessionOpWaitLookupStatePtr routeSessionWait = RouteSessionOpWaitLookupStatePtr::dynamicCast(operation);
+ if (routeSessionWait != 0)
+ {
+ visitRouteSessionOpWaitLookupState(routeSessionWait);
+ return;
+ }
+
+ RouteSessionOpBridgingStatePtr routeBridging = RouteSessionOpBridgingStatePtr::dynamicCast(operation);
+ if (routeBridging != 0)
+ {
+ visitRouteSessionOpBridgingState(routeBridging);
+ return;
+ }
+
+ ConnectBridgedSessionsWithDestinationOpStartPtr connectWithDestStart = ConnectBridgedSessionsWithDestinationOpStartPtr::dynamicCast(operation);
+ if (connectWithDestStart != 0)
+ {
+ visitConnectBridgedSessionsWithDestinationOpStart(connectWithDestStart);
+ return;
+ }
+
+ ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr connectWithDestLookup = ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr::dynamicCast(operation);
+ if (connectWithDestLookup != 0)
+ {
+ visitConnectBridgedSessionsWithDestinationOpWaitLookupState(connectWithDestLookup);
+ return;
+ }
+
+ ConnectBridgedSessionsWithDestinationOpBridgingStatePtr connectWithDestBridge = ConnectBridgedSessionsWithDestinationOpBridgingStatePtr::dynamicCast(operation);
+ if (connectWithDestBridge != 0)
+ {
+ visitConnectBridgedSessionsWithDestinationOpBridgingState(connectWithDestBridge);
+ return;
+ }
+ }
+
void visitRouteSessionOpStart(const ::AsteriskSCF::BasicRoutingService::V1::RouteSessionOpStartPtr& opState)
{
mImpl->mOperationReplicaCache->getRouteSessionCache()->cacheOperationState(opState);
diff --git a/src/SessionRouterOperation.h b/src/SessionRouterOperation.h
index 63b81cc..a02c9f9 100644
--- a/src/SessionRouterOperation.h
+++ b/src/SessionRouterOperation.h
@@ -242,9 +242,15 @@ public:
*/
void setLookupResult(const AsteriskSCF::Core::Endpoint::V1::EndpointSeq& endpoints)
{
+ if (mFinished)
+ {
+ // This operation terminated since the callback was created.
+ return;
+ }
+
mLookupResult = endpoints;
- // Reschedule this operation to complete.
+ // Reschedule this operation to continue.
try
{
// Let the operation continue on its way.
diff --git a/test/MockEndpointLocator.cpp b/test/MockEndpointLocator.cpp
index aacd0c7..32036c2 100644
--- a/test/MockEndpointLocator.cpp
+++ b/test/MockEndpointLocator.cpp
@@ -63,6 +63,8 @@ void MockEndpointLocator::lookup_async(const ::AsteriskSCF::Core::Routing::V1::A
cb->ice_exception(DestinationNotFoundException(destination));
}
cb->ice_response(endpoints);
+
+ mLookupCalled = true;
}
void MockEndpointLocator::perTestCleanup()
@@ -71,6 +73,8 @@ void MockEndpointLocator::perTestCleanup()
{
(*i)->perTestCleanup();
}
+
+ mLookupCalled = false;
}
void MockEndpointLocator::clear()
@@ -82,6 +86,8 @@ void MockEndpointLocator::clear()
mEndpointPrxList.clear();
mEndpoints.clear();
+
+ mLookupCalled = false;
}
MockSessionEndpointPtr MockEndpointLocator::addEndpoint(const string& id)
diff --git a/test/MockEndpointLocator.h b/test/MockEndpointLocator.h
index 0230cde..9eb20f3 100644
--- a/test/MockEndpointLocator.h
+++ b/test/MockEndpointLocator.h
@@ -30,6 +30,8 @@ namespace RoutingTest
class MockEndpointLocator : public AsteriskSCF::Core::Routing::V1::EndpointLocator
{
public:
+ MockEndpointLocator() : mLookupCalled(false) {}
+
// Overrides
virtual void lookup_async(const ::AsteriskSCF::Core::Routing::V1::AMD_EndpointLocator_lookupPtr& cb, const ::std::string& destination, const ::Ice::Current& = ::Ice::Current());
@@ -43,6 +45,8 @@ public:
*/
MockSessionEndpointPtr localLookup(const std::string& id);
+ bool mLookupCalled;
+
private:
AsteriskSCF::Core::Endpoint::V1::EndpointSeq mEndpointPrxList;
std::vector<MockSessionEndpointPtr> mEndpoints;
diff --git a/test/SharedTestData.h b/test/SharedTestData.h
index a82c213..8d34545 100644
--- a/test/SharedTestData.h
+++ b/test/SharedTestData.h
@@ -49,6 +49,8 @@ struct SharedTestData
AsteriskSCF::Core::Routing::V1::LocatorRegistryPrx locatorRegistry;
AsteriskSCF::SessionCommunications::V1::SessionRouterPrx sessionRouter;
AsteriskSCF::System::Component::V1::ReplicaPrx serviceReplicaMgmt;
+ AsteriskSCF::System::Component::V1::ComponentServicePrx componentService;
+ AsteriskSCF::System::Component::V1::ComponentTestPrx componentTest;
// Proxies to the backup instance's routing service interfaces.
AsteriskSCF::Core::Routing::V1::LocatorRegistryPrx backupLocatorRegistry;
diff --git a/test/TestRouting.cpp b/test/TestRouting.cpp
index ef4b05c..48abb23 100644
--- a/test/TestRouting.cpp
+++ b/test/TestRouting.cpp
@@ -91,6 +91,21 @@ struct GlobalIceFixture
SharedTestData::instance.communicatorOut = Ice::initialize(initData);
SharedTestData::instance.adapterOut = SharedTestData::instance.communicatorOut->createObjectAdapterWithEndpoints("TestRoutingAdapterOut", "default -p 10071");
+ // Get ref to Routing Service's ComponentService interface.
+ Ice::ObjectPrx componentObj = SharedTestData::instance.communicatorOut->propertyToProxy("RoutingComponent.Proxy");
+ SharedTestData::instance.componentService = ComponentServicePrx::uncheckedCast(componentObj);
+
+ if (!SharedTestData::instance.componentService)
+ {
+ throw "Invalid ComponentService";
+ }
+
+ SharedTestData::instance.componentTest = ComponentTestPrx::checkedCast(SharedTestData::instance.componentService, AsteriskSCF::System::Component::V1::ComponentTestFacet);
+ if (SharedTestData::instance.componentTest == 0)
+ {
+ BOOST_TEST_MESSAGE("No Component Test facet available. Some tests may be skipped.");
+ }
+
// Get ref to Routing Service EndpointLocator so we can test it. Getting direct for now, but
// need to test acquiring reference via ServiceLocator as well.
Ice::ObjectPrx locatorObj = SharedTestData::instance.communicatorOut->propertyToProxy("LocatorRegistry.Proxy");
@@ -697,3 +712,163 @@ BOOST_FIXTURE_TEST_CASE(SwitchActiveAndStandby, PerTestFixture)
}
+BOOST_FIXTURE_TEST_CASE(FailoverRouteSession, PerTestFixture)
+{
+ if (SharedTestData::instance.componentTest == 0)
+ {
+ BOOST_TEST_MESSAGE("Component test interface not configured. Skipping test FailoverRouteSession.");
+ return;
+ }
+
+ try
+ {
+ // Verify that both the active and standby services report the correct state.
+ BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+ BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+
+ SharedTestData::instance.componentTest->setTestMode("RouteSessionFailover");
+
+ // Get our local 101 endpoint
+ MockSessionEndpointPtr session101Endpoint = SharedTestData::instance.endpointLocator->localLookup("101");
+
+ BOOST_TEST_MESSAGE("Creating a session on our test endpoint...");
+ SessionPrx session = session101Endpoint->createSession("102", 0, Ice::Current());
+ BOOST_CHECK(session != 0);
+
+ SharedTestData::instance.mBridgeConnected = false;
+
+ BOOST_TEST_MESSAGE("Routing the session...");
+ string operationId = IceUtil::generateUUID();
+
+ // Note we're routing using AMI with no callback. The callback would never come due to the
+ // way the test mode shuts down the operation. Simulates failure.
+ SharedTestData::instance.sessionRouter->begin_routeSession(operationId, session, "102");
+
+ for (int counter=0; SharedTestData::instance.endpointLocator->mLookupCalled == false; counter++)
+ {
+ // Give the main routing service time to do the lookup.
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(500));
+
+ if (counter > 5)
+ {
+ // Must be other problems!
+ break;
+ }
+ }
+
+ // The lookup should have completed prior to the simulated failure.
+ BOOST_CHECK(SharedTestData::instance.endpointLocator->mLookupCalled);
+
+ // In test mode, the active routing service will abort the operation prior to
+ // createing the bridge.
+ BOOST_CHECK(SharedTestData::instance.mBridgeConnected == false);
+
+ // Reset the lookup flag.
+ SharedTestData::instance.endpointLocator->mLookupCalled = false;
+
+ // Switch standby component to active.
+ SharedTestData::instance.serviceReplicaMgmt->activate();
+ BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+
+ // Let the backup session router try to route using same operationId.
+ SharedTestData::instance.backupSessionRouter->routeSession(operationId, session, "102");
+
+ // The lookup should not be done again.
+ BOOST_CHECK(!SharedTestData::instance.endpointLocator->mLookupCalled);
+
+ BOOST_CHECK(SharedTestData::instance.mBridgeConnected == true);
+
+ // Set the backup back into standby mode.
+ SharedTestData::instance.backupServiceReplicaMgmt->standby();
+ BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+ }
+ catch (...)
+ {
+ BOOST_FAIL("Exception switching component between active and standby.");
+ }
+
+}
+
+BOOST_FIXTURE_TEST_CASE(FailoverConnectBridgedSessWithDest, PerTestFixture)
+{
+ if (SharedTestData::instance.componentTest == 0)
+ {
+ BOOST_TEST_MESSAGE("Component test interface not configured. Skipping test FailoverConnectBridgedSessWithDest.");
+ return;
+ }
+
+ try
+ {
+ // Verify that both the active and standby services report the correct state.
+ BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+ BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+
+ SharedTestData::instance.componentTest->setTestMode("ConnectBridgedSessWithDestFailover");
+
+ // Get our local 101 endpoint
+ MockSessionEndpointPtr session101Endpoint = SharedTestData::instance.endpointLocator->localLookup("101");
+
+ BOOST_TEST_MESSAGE("Creating a session on our test endpoint...");
+ SessionPrx session = session101Endpoint->createSession("102", 0, Ice::Current());
+ BOOST_CHECK(session != 0);
+
+ SharedTestData::instance.mBridgeConnected = false;
+ SharedTestData::instance.mSessionReplaced = false;
+
+ BOOST_TEST_MESSAGE("Routing the session...");
+ string operationId = IceUtil::generateUUID();
+ SharedTestData::instance.sessionRouter->routeSession(operationId, session, "102");
+
+ BridgePrx bridge = session->getBridge();
+ BOOST_CHECK(bridge != 0);
+ BOOST_CHECK(SharedTestData::instance.mBridgeConnected);
+
+ // Now transfer to a new extension. In our test mode, this operation will never complete.
+ SharedTestData::instance.sessionRouter->begin_connectBridgedSessionsWithDestination(IceUtil::generateUUID(), session, "103");
+
+ for (int counter=0; SharedTestData::instance.endpointLocator->mLookupCalled == false; counter++)
+ {
+ // Give the main routing service time to do the lookup.
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(500));
+
+ if (counter > 5)
+ {
+ // Must be other problems!
+ break;
+ }
+ }
+
+ // The lookup should have completed prior to the simulated failure.
+ BOOST_CHECK(SharedTestData::instance.endpointLocator->mLookupCalled);
+
+ // In this test mode, the active routing service will abort after
+ // createing the bridge.
+ BOOST_CHECK(SharedTestData::instance.mBridgeConnected == true);
+
+ // Reset the local flags.
+ SharedTestData::instance.endpointLocator->mLookupCalled = false;
+ SharedTestData::instance.mBridgeConnected = false;
+
+ // Switch standby component to active.
+ SharedTestData::instance.serviceReplicaMgmt->activate();
+ BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+
+ // Let the backup session router try to route using same operationId. Synchronous call.
+ SharedTestData::instance.backupSessionRouter->routeSession(operationId, session, "103");
+
+ // The lookup should not be done again.
+ BOOST_CHECK(SharedTestData::instance.endpointLocator->mLookupCalled == false);
+
+ // The bridge shouldn't be created again.
+ BOOST_CHECK(SharedTestData::instance.mBridgeConnected == false);
+
+ // Set the backup back into standby mode.
+ SharedTestData::instance.backupServiceReplicaMgmt->standby();
+ BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+ }
+ catch (...)
+ {
+ BOOST_FAIL("Exception switching component between active and standby.");
+ }
+
+}
-----------------------------------------------------------------------
--
asterisk-scf/integration/routing.git
More information about the asterisk-scf-commits
mailing list