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());
}