Author: aconway
Date: Tue Oct  7 19:03:05 2008
New Revision: 702681

URL: http://svn.apache.org/viewvc?rev=702681&view=rev
Log:
SessionImpl using ExceptionHolder to generate correctly typed exceptions..

Modified:
    incubator/qpid/trunk/qpid/cpp/rubygen/framing.0-10/constants.rb
    incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/ExceptionHolder.h
    incubator/qpid/trunk/qpid/cpp/src/tests/exception_test.cpp

Modified: incubator/qpid/trunk/qpid/cpp/rubygen/framing.0-10/constants.rb
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/rubygen/framing.0-10/constants.rb?rev=702681&r1=702680&r2=702681&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/rubygen/framing.0-10/constants.rb (original)
+++ incubator/qpid/trunk/qpid/cpp/rubygen/framing.0-10/constants.rb Tue Oct  7 
19:03:05 2008
@@ -93,9 +93,9 @@
       scope("switch (code) {") {
         enum = @amqp.class_(class_name).domain(domain_name).enum
         enum.choices.each { |c|
-          genl "case #{c.value}: holder = new #{c.name.caps}Exception(text); 
break;" unless c.name == "normal"
+          assign = "holder = new #{c.name.caps}Exception(text); " unless 
c.name == "normal"
+          genl "case #{c.value}: #{assign}break;" 
         }
-        genl "default: assert(0);"
         genl "    holder = new #{invalid}(QPID_MSG(\"Bad exception code: \" << 
code << \": \" << text));"
       }
       genl "return holder;"

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.cpp?rev=702681&r1=702680&r2=702681&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.cpp Tue Oct  7 
19:03:05 2008
@@ -54,10 +54,7 @@
 SessionImpl::SessionImpl(const std::string& name,
                          shared_ptr<ConnectionImpl> conn,
                          uint16_t ch, uint64_t _maxFrameSize)
-    : error(OK),
-      code(DETACH_CODE_NORMAL),
-      text(EMPTY),
-      state(INACTIVE),
+    : state(INACTIVE),
       detachedLifetime(0),
       maxFrameSize(_maxFrameSize),
       id(conn->getNegotiatedSettings().username, name.empty() ? 
Uuid(true).str() : name),
@@ -238,17 +235,23 @@
     }    
 }
 
+void SessionImpl::setException(const sys::ExceptionHolder& ex) {
+    Lock l(state);
+    setExceptionLH(ex);
+}
+
+void SessionImpl::setExceptionLH(const sys::ExceptionHolder& ex) { // Call 
with lock held.
+    exceptionHolder = ex;
+    setState(DETACHED);
+}
+
 /**
  * Called by ConnectionImpl to notify active sessions when connection
  * is explictly closed
  */
-void SessionImpl::connectionClosed(uint16_t _code, const std::string& _text) 
-{
-    Lock l(state);
-    error = CONNECTION_CLOSE;
-    code = _code;
-    text = _text;
-    setState(DETACHED);
+void SessionImpl::connectionClosed(uint16_t code, const std::string& text)  {
+    setException(createConnectionException(code, text));
+    // FIXME aconway 2008-10-07: Should closing a connection detach or close 
its sessions?
     handleClosed();
 }
 
@@ -258,6 +261,7 @@
  */
 void SessionImpl::connectionBroke(uint16_t _code, const std::string& _text) 
 {
+    // FIXME aconway 2008-10-07: distinguish disconnect from clean close.  
     connectionClosed(_code, _text);
 }
 
@@ -411,13 +415,12 @@
                 deliver(frame);
             }
         }
-    } catch (const SessionException& e) {
-        //TODO: proper 0-10 exception handling
-        QPID_LOG(error, "Session exception:" << e.what());
-        Lock l(state);
-        error = EXCEPTION;
-        code = e.code;
-        text = e.what();
+    }
+    catch (const SessionException& e) {
+        setException(createSessionException(e.code, e.getMessage()));
+    }
+    catch (const ChannelException& e) {
+        setException(createChannelException(e.code, e.getMessage()));
     }
 }
 
@@ -478,22 +481,19 @@
     QPID_LOG(info, "Session detached by peer: " << id);
 }
 
-void SessionImpl::detached(const std::string& _name, uint8_t _code)
-{
+void SessionImpl::detached(const std::string& _name, uint8_t _code) {
     Lock l(state);
     if (id.getName() != _name) throw InternalErrorException("Incorrect session 
name");
     setState(DETACHED);
     if (_code) {
         //TODO: make sure this works with execution.exception - don't
         //want to overwrite the code from that
-        QPID_LOG(error, "Session detached by peer: " << id << " " << code);
-        error = SESSION_DETACH;
-        code = _code;
-        text = "Session detached by peer";
+        setExceptionLH(createChannelException(_code, "Session detached by 
peer"));
+        QPID_LOG(error, exceptionHolder.what());
     }
     if (detachedLifetime == 0) {
         handleClosed();
-    }
+}
 }
 
 void SessionImpl::requestTimeout(uint32_t t)
@@ -606,9 +606,7 @@
              << " [caused by " << commandId << " " << classCode << ":" << 
commandCode << "]");
 
     Lock l(state);
-    error = EXCEPTION;
-    code = errorCode;
-    text = description;
+    setExceptionLH(createSessionException(errorCode, description));
     if (detachedLifetime) 
         setTimeout(0);
 }
@@ -631,12 +629,7 @@
 
 void SessionImpl::check() const  //call with lock held.
 {
-    switch (error) {
-      case OK: break;
-      case CONNECTION_CLOSE: throw ConnectionException(code, text);
-      case SESSION_DETACH: throw ChannelException(code, text);
-      case EXCEPTION: createSessionException(code, text).raise();
-    }
+    exceptionHolder.raise();
 }
 
 void SessionImpl::checkOpen() const  //call with lock held.
@@ -657,7 +650,7 @@
 {
     // FIXME aconway 2008-06-12: needs to be set to the correct exception type.
     // 
-    demux.close(sys::ExceptionHolder(text.empty() ? new ClosedException() : 
new Exception(text)));
+    demux.close(exceptionHolder.empty() ? new ClosedException() : 
exceptionHolder);
     results.close();
 }
 
@@ -668,4 +661,5 @@
     detachedLifetime = seconds;
     return detachedLifetime;
 }
+
 }}

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.h?rev=702681&r1=702680&r2=702681&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/client/SessionImpl.h Tue Oct  7 
19:03:05 2008
@@ -27,6 +27,7 @@
 #include "Results.h"
 
 #include "qpid/SessionId.h"
+#include "qpid/SessionState.h"
 #include "qpid/shared_ptr.h"
 #include "qpid/framing/FrameHandler.h"
 #include "qpid/framing/ChannelHandler.h"
@@ -35,6 +36,7 @@
 #include "qpid/framing/AMQP_ServerProxy.h"
 #include "qpid/sys/Semaphore.h"
 #include "qpid/sys/StateMonitor.h"
+#include "qpid/sys/ExceptionHolder.h"
 
 #include <boost/optional.hpp>
 
@@ -52,6 +54,7 @@
 
 class Future;
 class ConnectionImpl;
+class SessionHandler;
 
 ///@internal
 class SessionImpl : public framing::FrameHandler::InOutHandler,
@@ -91,6 +94,8 @@
     void sendCompletion();
     void sendFlush();
 
+    void setException(const sys::ExceptionHolder&);
+    
     //NOTE: these are called by the network thread when the connection is 
closed or dies
     void connectionClosed(uint16_t code, const std::string& text);
     void connectionBroke(uint16_t code, const std::string& text);
@@ -102,12 +107,6 @@
     uint32_t getTimeout() const;
 
 private:
-    enum ErrorType {
-        OK,
-        CONNECTION_CLOSE,
-        SESSION_DETACH,
-        EXCEPTION
-    };
     enum State {
         INACTIVE,
         ATTACHING,
@@ -123,6 +122,7 @@
     inline void setState(State s);
     inline void waitFor(State);
 
+    void setExceptionLH(const sys::ExceptionHolder&);      // LH = lock held 
when called.
     void detach();
     
     void check() const;
@@ -168,9 +168,7 @@
                    const std::string& description,
                    const framing::FieldTable& errorInfo);
 
-    ErrorType error;
-    int code;                   // Error code
-    std::string text;           // Error text
+    sys::ExceptionHolder exceptionHolder;
     mutable StateMonitor state;
     mutable sys::Semaphore sendLock;
     uint32_t detachedLifetime;
@@ -193,6 +191,9 @@
     framing::SequenceNumber nextIn;
     framing::SequenceNumber nextOut;
 
+    SessionState sessionState;
+
+  friend class client::SessionHandler;
 };
 
 }} // namespace qpid::client

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/ExceptionHolder.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/ExceptionHolder.h?rev=702681&r1=702680&r2=702681&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/ExceptionHolder.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/ExceptionHolder.h Tue Oct  7 
19:03:05 2008
@@ -52,7 +52,7 @@
     template <class Ex> ExceptionHolder& operator=(boost::shared_ptr<Ex> ex) { 
wrap(ex.release()); return *this; }
         
     void raise() const { if (wrapper.get()) wrapper->raise() ; }
-    std::string what() const { return wrapper->what(); }
+    std::string what() const { return wrapper.get() ? wrapper->what() : 
std::string(); }
     bool empty() const { return !wrapper.get(); }
     operator bool() const { return !empty(); }
     void reset() { wrapper.reset(); }

Modified: incubator/qpid/trunk/qpid/cpp/src/tests/exception_test.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/exception_test.cpp?rev=702681&r1=702680&r2=702681&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/exception_test.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/exception_test.cpp Tue Oct  7 
19:03:05 2008
@@ -83,7 +83,7 @@
         ScopedSuppressLogging sl; // Suppress messages for expected errors.
         f.connection.newSession(f.session.getId().getName());
         BOOST_FAIL("Expected SessionBusyException for " << 
f.session.getId().getName());
-    } catch (const Exception&) {} // FIXME aconway 2008-09-22: client is not 
throwing correct exception.
+    } catch (const SessionBusyException&) {} // FIXME aconway 2008-09-22: 
client is not throwing correct exception.
 }
 
 QPID_AUTO_TEST_CASE(DisconnectedPop) {
@@ -91,7 +91,7 @@
     ProxyConnection c(fix.broker->getPort());
     fix.session.queueDeclare(arg::queue="q");
     fix.subs.subscribe(fix.lq, "q");
-    Catcher<Exception> pop(bind(&LocalQueue::pop, boost::ref(fix.lq)));
+    Catcher<ConnectionException> pop(bind(&LocalQueue::pop, 
boost::ref(fix.lq)));
     fix.connection.proxy.close();
     BOOST_CHECK(pop.join());
 }


Reply via email to