[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
Thu May 19 20:23:08 CDT 2011


branch "master" has been updated
       via  ba502f18be3aa445072142f9bbca16efb61c4df0 (commit)
      from  41a1d26e130b1b0b00e8367bd3643eb8a0143758 (commit)

Summary of changes:
 src/BridgeImpl.cpp      |    3 +-
 src/SessionListener.cpp |   47 +++++++++++++++++++----
 src/SessionListener.h   |   21 ++++++++++-
 src/SessionWrapper.cpp  |   28 ++++++++++----
 src/SessionWrapper.h    |    2 +-
 test/TestBridging.cpp   |   94 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 176 insertions(+), 19 deletions(-)


- Log -----------------------------------------------------------------
commit ba502f18be3aa445072142f9bbca16efb61c4df0
Author: Brent Eagles <beagles at digium.com>
Date:   Thu May 19 22:50:50 2011 -0230

    - Add proxies to the session listener so it can decide to call shutdown on the
    bridge if the session count is going to drop below 2 when it receives a stopped
    indication. Added test for same.
    
    - Also modified the RemoveBridge task to "swallow" the NotBridged exception as
    it could very well have been a result of multiple shutdown/removals of a given
    session at the same time.

diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index 0ce1947..15dd93a 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -140,7 +140,7 @@ private:
     //
     // The bridge's callback implementation for the sessions that get added to it.
     //
-    SessionListenerPtr mSessionListener;
+    BridgeSessionListenerPtr mSessionListener;
     SessionListenerPrx mSessionListenerPrx;
 
     //
@@ -853,6 +853,7 @@ void BridgeImpl::activate(const BridgePrx& proxy)
         SessionListenerPrx::uncheckedCast(
             mObjAdapter->add(mSessionListener, mObjAdapter->getCommunicator()->stringToIdentity(listenerId))
             );
+    mSessionListener->onActivate(mPrx, mSessionListenerPrx);
 
     ReplicatedStateItemSeq initialUpdates;
     BridgeStateItemPtr update = createUpdate();
diff --git a/src/SessionListener.cpp b/src/SessionListener.cpp
index ec8989a..86a2fca 100644
--- a/src/SessionListener.cpp
+++ b/src/SessionListener.cpp
@@ -33,7 +33,7 @@ namespace
 // For events result in distribution to the bridge sessions, we copy the current sessions and
 // run the calls from the listener itself.
 //
-class SessionListenerImpl : public SessionListener
+class SessionListenerImpl : public BridgeSessionListener
 {
 public:
     SessionListenerImpl(const SessionCollectionPtr& b, const Logger& logger) :
@@ -43,7 +43,7 @@ public:
     }
 
     void indicated(const AsteriskSCF::SessionCommunications::V1::SessionPrx& source,
-        const AsteriskSCF::SessionCommunications::V1::IndicationPtr& indication, const Ice::Current& current)
+        const AsteriskSCF::SessionCommunications::V1::IndicationPtr& indication, const Ice::Current&)
     {
 	AsteriskSCF::SessionCommunications::V1::ConnectedIndicationPtr connected;
 	AsteriskSCF::SessionCommunications::V1::RingingIndicationPtr ringing;
@@ -111,27 +111,58 @@ public:
 		return;
 	    }
 
-	    //
-	    // We don't actually have the proxy for this object, but we can create one on the fly.
-	    //
-	    SessionListenerPrx listenerPrx = SessionListenerPrx::uncheckedCast(current.adapter->createProxy(current.id));
+            //
+            // This returns only the active sessions.
+            //
+            SessionSeq currentSessions = mSessions->getSessionSeq();
 	    
 	    //
 	    // Shutdown is handled asynchronously, so there won't be any exceptions that need to be caught here.
             // A null response code pointer will prevent the stop indication from being sent back to this session.
 	    //
-	    session->shutdown(listenerPrx, ResponseCodePtr());
+	    session->shutdown(mListenerPrx, ResponseCodePtr());
+
+            //
+            // Ideally, we'd wait for an affirmative response from the session being removed from the bridge
+            // before doing this next part. 
+            //
+            if (mBridgePrx)
+            {
+                try
+                {
+                    //
+                    // TODO: Should be determined by policy. 2 is the proper upper limit because 
+                    // the session in question will not have been removed from the bridge yet.
+                    //
+                    if (currentSessions.size() <= 2)
+                    {
+                        mBridgePrx->shutdown();
+                    }
+                }
+                catch (const Ice::Exception& ex)
+                {
+                    mLogger(Error) << "Unexpected exception when initiating auto shutdown";
+                }
+            }
 	}
     }
 
+    void onActivate(const BridgePrx& bridgePrx, const SessionListenerPrx& listenerPrx)
+    {
+        mBridgePrx = bridgePrx;
+        mListenerPrx = listenerPrx;
+    }
+
 private:
     SessionCollectionPtr mSessions;
     Logger mLogger;
+    BridgePrx mBridgePrx;
+    SessionListenerPrx mListenerPrx;
 };
 
 }
 
-SessionListenerPtr AsteriskSCF::BridgeService::createSessionListener(const SessionCollectionPtr& sessions,
+BridgeSessionListenerPtr AsteriskSCF::BridgeService::createSessionListener(const SessionCollectionPtr& sessions,
         const Logger& logger)
 {
     return new SessionListenerImpl(sessions, logger);
diff --git a/src/SessionListener.h b/src/SessionListener.h
index 0d65892..04f087d 100644
--- a/src/SessionListener.h
+++ b/src/SessionListener.h
@@ -30,7 +30,26 @@ class Logger;
 namespace BridgeService
 {
 
-AsteriskSCF::SessionCommunications::V1::SessionListenerPtr createSessionListener(const SessionCollectionPtr& sessions,
+//
+// TODO: Should go in it's own header file.
+//
+class BridgeSessionListener: public virtual AsteriskSCF::SessionCommunications::V1::SessionListener
+{
+public:
+    virtual ~BridgeSessionListener() {} 
+
+    /**
+     * 
+     * Called ONCE when the servant is added to the object adapter!
+     *
+     **/
+    virtual void onActivate(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridgePrx,
+      const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listenerPrx) =0;
+};
+
+typedef IceUtil::Handle<BridgeSessionListener> BridgeSessionListenerPtr;
+
+BridgeSessionListenerPtr createSessionListener(const SessionCollectionPtr& sessions,
         const AsteriskSCF::System::Logging::Logger& logger);
         
 
diff --git a/src/SessionWrapper.cpp b/src/SessionWrapper.cpp
index ac8234b..d514e3b 100644
--- a/src/SessionWrapper.cpp
+++ b/src/SessionWrapper.cpp
@@ -122,12 +122,27 @@ protected:
         mListener->succeeded();
     }
 
-    void failed(const Ice::Exception&)
+    void failed(const Ice::Exception& ex)
     {
-        //
-        // TODO: Log exception.
-        //
-        mListener->failed();
+
+        try
+        {
+            ex.ice_throw();
+        }
+        catch (const NotBridged&)
+        {
+            //
+            // This is most likely ok, it just means removeBridge was called
+            // twice.
+            //
+        }
+        catch (...)
+        {
+            //
+            // TODO: Log exception.
+            //
+            mListener->failed();
+        }
     }
 
     void failImpl()
@@ -296,9 +311,6 @@ QueuedTasks createShutdownTasks(const SessionWrapperPtr& session, const SessionL
     QueuedTasks tasks;
     tasks.push_back(new SetStateTask(session, Disconnected));
     tasks.push_back(new RemoveBridgeTask(session, listener));
-    //
-    // TODO: this should really go through a different interface.
-    //
     if (code)
     {
         tasks.push_back(new SessionStopTask(session, code));
diff --git a/src/SessionWrapper.h b/src/SessionWrapper.h
index b955280..0c98112 100644
--- a/src/SessionWrapper.h
+++ b/src/SessionWrapper.h
@@ -122,7 +122,7 @@ public:
     void setup();
     
     void shutdown(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
-            const AsteriskSCF::SessionCommunications::V1::ResponseCodePtr& code);
+        const AsteriskSCF::SessionCommunications::V1::ResponseCodePtr& code);
 
     //
     // TODO: Refactor so these methods don't need to be exposed.
diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index 5407259..b5546db 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -451,6 +451,98 @@ public:
         }
     };
 
+    void testAutoShutdown()
+    {
+        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::V1::SessionSeq sessions;
+                AsteriskSCF::SessionCommunications::V1::BridgePrx bridge(mgrPrx->createBridge(sessions, 0));
+                TestChannelWrapper channel(env()->properties());
+
+                AsteriskSCF::SessionCommunications::V1::SessionPrx a = channel.getSession("311");
+                AsteriskSCF::SessionCommunications::V1::SessionPrx b = channel.getSession("312");
+                sessions.push_back(a);
+                sessions.push_back(b);
+                //
+                // 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"));
+
+                bridge->addSessions(sessions);
+                //
+                // Check for regression where the bridge was calling start on sessions.
+                //
+                channel.commands()->getlog(idA, log);
+                BOOST_CHECK(!find(log, "start"));
+                channel.commands()->getlog(idB, log);
+                BOOST_CHECK(!find(log, "start"));
+
+                a->start();
+                b->start();
+
+                channel.commands()->getlog(idA, log);
+                BOOST_CHECK(find(log, "start"));
+                channel.commands()->getlog(idB, log);
+                BOOST_CHECK(find(log, "start"));
+
+                //
+                // Should result in a media hookup!
+                //
+                channel.commands()->answer(idA);
+                channel.commands()->answer(idB);
+
+                IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2));
+                channel.commands()->hangup(idA);
+                IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2));
+
+                BOOST_CHECK(servant->createCalls() == 1);
+                
+                channel.commands()->getlog(idB, log);
+                bool findStop = find(log, "stop");
+                if (!findStop)
+                {
+                    dumplog(log);
+                }
+                BOOST_CHECK(findStop);
+            }
+            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");
+        }
+    };
+
     void bridgeDefaultListenerTest()
     {
         try
@@ -772,6 +864,8 @@ bool init_unit_test()
     framework::master_test_suite().
         add(BOOST_TEST_CASE(boost::bind(&BridgeTester::simpleBridgingTest, bridgeTester)));
     framework::master_test_suite().
+        add(BOOST_TEST_CASE(boost::bind(&BridgeTester::testAutoShutdown, bridgeTester)));
+    framework::master_test_suite().
         add(BOOST_TEST_CASE(boost::bind(&BridgeTester::bridgeDefaultListenerTest, bridgeTester)));
     framework::master_test_suite().
         add(BOOST_TEST_CASE(boost::bind(&BridgeTester::bridgeManagerListeners, bridgeTester)));

-----------------------------------------------------------------------


-- 
asterisk-scf/release/bridging.git



More information about the asterisk-scf-commits mailing list