You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by ro...@apache.org on 2011/09/11 09:28:54 UTC

svn commit: r1167679 - in /thrift/trunk/lib/cpp/src/async: TEvhttpClientChannel.cpp TEvhttpServer.cpp

Author: roger
Date: Sun Sep 11 07:28:54 2011
New Revision: 1167679

URL: http://svn.apache.org/viewvc?rev=1167679&view=rev
Log:
THRIFT-1243 TAsyncChannel callbacks
improved exception handling
Patch: Alexandre Parenteau

Modified:
    thrift/trunk/lib/cpp/src/async/TEvhttpClientChannel.cpp
    thrift/trunk/lib/cpp/src/async/TEvhttpServer.cpp

Modified: thrift/trunk/lib/cpp/src/async/TEvhttpClientChannel.cpp
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/cpp/src/async/TEvhttpClientChannel.cpp?rev=1167679&r1=1167678&r2=1167679&view=diff
==============================================================================
--- thrift/trunk/lib/cpp/src/async/TEvhttpClientChannel.cpp (original)
+++ thrift/trunk/lib/cpp/src/async/TEvhttpClientChannel.cpp Sun Sep 11 07:28:54 2011
@@ -20,6 +20,13 @@
 #include "TEvhttpClientChannel.h"
 #include <evhttp.h>
 #include "transport/TBufferTransports.h"
+#include <protocol/TProtocolException.h>
+
+#include <iostream>
+#include <sstream>
+
+using namespace apache::thrift::protocol;
+using apache::thrift::transport::TTransportException;
 
 namespace apache { namespace thrift { namespace async {
 
@@ -37,7 +44,7 @@ TEvhttpClientChannel::TEvhttpClientChann
 {
   conn_ = evhttp_connection_new(address, port);
   if (conn_ == NULL) {
-    abort(); // XXX
+    throw TException("evhttp_connection_new failed");
   }
   evhttp_connection_set_base(conn_, eb);
 }
@@ -59,19 +66,19 @@ void TEvhttpClientChannel::sendAndRecvMe
 
   struct evhttp_request* req = evhttp_request_new(response, this);
   if (req == NULL) {
-    abort(); // XXX
+    throw TException("evhttp_request_new failed");
   }
 
   int rv;
 
   rv = evhttp_add_header(req->output_headers, "Host", host_.c_str());
   if (rv != 0) {
-    abort(); // XXX
+    throw TException("evhttp_add_header failed");
   }
 
   rv = evhttp_add_header(req->output_headers, "Content-Type", "application/x-thrift");
   if (rv != 0) {
-    abort(); // XXX
+    throw TException("evhttp_add_header failed");
   }
 
   uint8_t* obuf;
@@ -79,12 +86,12 @@ void TEvhttpClientChannel::sendAndRecvMe
   sendBuf->getBuffer(&obuf, &sz);
   rv = evbuffer_add(req->output_buffer, obuf, sz);
   if (rv != 0) {
-    abort(); // XXX
+    throw TException("evbuffer_add failed");
   }
 
   rv = evhttp_make_request(conn_, req, EVHTTP_REQ_POST, path_.c_str());
   if (rv != 0) {
-    abort(); // XXX
+    throw TException("evhttp_make_request failed");
   }
 }
 
@@ -93,7 +100,8 @@ void TEvhttpClientChannel::sendMessage(
     const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) {
   (void) cob;
   (void) message;
-  abort(); // XXX
+  throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+			   "Unexpected call to TEvhttpClientChannel::sendMessage");
 }
 
 
@@ -101,17 +109,36 @@ void TEvhttpClientChannel::recvMessage(
     const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) {
   (void) cob;
   (void) message;
-  abort(); // XXX
+  throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+			   "Unexpected call to TEvhttpClientChannel::recvMessage");
 }
 
 
 void TEvhttpClientChannel::finish(struct evhttp_request* req) {
   if (req == NULL) {
+  try {
     cob_();
-	return;
+  } catch(const TTransportException& e) {
+    if(e.getType() == TTransportException::END_OF_FILE)
+      throw TException("connect failed");
+    else
+      throw;
+  }
+  return;
   } else if (req->response_code != 200) {
+  try {
     cob_();
-	return;
+  } catch(const TTransportException& e) {
+    std::stringstream ss;
+    ss << "server returned code " << req->response_code;
+	if(req->response_code_line)
+		ss << ": " << req->response_code_line;
+    if(e.getType() == TTransportException::END_OF_FILE)
+      throw TException(ss.str());
+    else
+      throw;
+  }
+  return;
   }
   recvBuf_->resetBuffer(
       EVBUFFER_DATA(req->input_buffer),
@@ -123,7 +150,12 @@ void TEvhttpClientChannel::finish(struct
 
 /* static */ void TEvhttpClientChannel::response(struct evhttp_request* req, void* arg) {
   TEvhttpClientChannel* self = (TEvhttpClientChannel*)arg;
-  self->finish(req);
+  try {
+    self->finish(req);
+  } catch(std::exception& e) {
+    // don't propagate a C++ exception in C code (e.g. libevent)
+    std::cerr << "TEvhttpClientChannel::response exception thrown (ignored): " << e.what() << std::endl;
+  }
 }
 
 

Modified: thrift/trunk/lib/cpp/src/async/TEvhttpServer.cpp
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/cpp/src/async/TEvhttpServer.cpp?rev=1167679&r1=1167678&r2=1167679&view=diff
==============================================================================
--- thrift/trunk/lib/cpp/src/async/TEvhttpServer.cpp (original)
+++ thrift/trunk/lib/cpp/src/async/TEvhttpServer.cpp Sun Sep 11 07:28:54 2011
@@ -22,6 +22,8 @@
 #include "transport/TBufferTransports.h"
 #include <evhttp.h>
 
+#include <iostream>
+
 #ifndef HTTP_INTERNAL // libevent < 2
 #define HTTP_INTERNAL 500
 #endif
@@ -55,12 +57,12 @@ TEvhttpServer::TEvhttpServer(boost::shar
   // Create event_base and evhttp.
   eb_ = event_base_new();
   if (eb_ == NULL) {
-    abort();  // XXX
+    throw TException("event_base_new failed");
   }
   eh_ = evhttp_new(eb_);
   if (eh_ == NULL) {
     event_base_free(eb_);
-    abort();  // XXX
+    throw TException("evhttp_new failed");
   }
 
   // Bind to port.
@@ -68,6 +70,7 @@ TEvhttpServer::TEvhttpServer(boost::shar
   if (ret < 0) {
     evhttp_free(eh_);
     event_base_free(eb_);
+	throw TException("evhttp_bind_socket failed");
   }
 
   // Register a handler.  If you use the other constructor,
@@ -89,7 +92,7 @@ TEvhttpServer::~TEvhttpServer() {
 
 int TEvhttpServer::serve() {
   if (eb_ == NULL) {
-    abort();  // XXX
+    throw TException("Unexpected call to TEvhttpServer::serve");
   }
   return event_base_dispatch(eb_);
 }
@@ -127,17 +130,19 @@ void TEvhttpServer::complete(RequestCont
   (void) success;
   std::auto_ptr<RequestContext> ptr(ctx);
 
-  int code = 200;
-  const char* reason = "OK";
+  int code = success ? 200 : 400;
+  const char* reason = success ? "OK" : "Bad Request";
 
   int rv = evhttp_add_header(ctx->req->output_headers, "Content-Type", "application/x-thrift");
   if (rv != 0) {
     // TODO: Log an error.
+    std::cerr << "evhttp_add_header failed " << __FILE__ << ":" << __LINE__ << std::endl;
   }
 
   struct evbuffer* buf = evbuffer_new();
   if (buf == NULL) {
     // TODO: Log an error.
+      std::cerr << "evbuffer_new failed " << __FILE__ << ":" <<  __LINE__ << std::endl;
   } else {
     uint8_t* obuf;
     uint32_t sz;
@@ -145,6 +150,7 @@ void TEvhttpServer::complete(RequestCont
     int ret = evbuffer_add(buf, obuf, sz);
     if (ret != 0) {
       // TODO: Log an error.
+      std::cerr << "evhttp_add failed with " << ret << " " << __FILE__ << ":" <<  __LINE__ << std::endl;
     }
   }