THRIFT-3496 C++: Cob style client fails when sending a consecutive request This closes #752
Project: http://git-wip-us.apache.org/repos/asf/thrift/repo Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/39e505c1 Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/39e505c1 Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/39e505c1 Branch: refs/heads/master Commit: 39e505c150486cc2a9c8aaa6ff0a39711ecad567 Parents: dd02f55 Author: Sebastian Zenker <[email protected]> Authored: Fri Dec 18 16:15:08 2015 +0100 Committer: Nobuaki Sukegawa <[email protected]> Committed: Thu Dec 24 02:11:17 2015 +0900 ---------------------------------------------------------------------- compiler/cpp/src/generate/t_cpp_generator.cc | 4 ++ .../src/thrift/async/TEvhttpClientChannel.cpp | 18 ++++---- lib/cpp/src/thrift/async/TEvhttpClientChannel.h | 7 ++- test/cpp/src/TestClient.cpp | 47 ++++++++------------ 4 files changed, 38 insertions(+), 38 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/thrift/blob/39e505c1/compiler/cpp/src/generate/t_cpp_generator.cc ---------------------------------------------------------------------- diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 8770ade..5056d87 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -2437,6 +2437,10 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) out << indent() << "::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_);" << endl; } + if (style == "Cob") { + out << + indent() << _this << "otrans_->resetBuffer();" << endl; + } out << indent() << _this << "oprot_->writeMessageBegin(\"" << (*f_iter)->get_name() << http://git-wip-us.apache.org/repos/asf/thrift/blob/39e505c1/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp ---------------------------------------------------------------------- diff --git a/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp b/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp index 1279bc6..74acfaa 100644 --- a/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp +++ b/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp @@ -39,7 +39,7 @@ TEvhttpClientChannel::TEvhttpClientChannel(const std::string& host, const char* address, int port, struct event_base* eb) - : host_(host), path_(path), recvBuf_(NULL), conn_(NULL) { + : host_(host), path_(path), conn_(NULL) { conn_ = evhttp_connection_new(address, port); if (conn_ == NULL) { throw TException("evhttp_connection_new failed"); @@ -56,9 +56,6 @@ TEvhttpClientChannel::~TEvhttpClientChannel() { void TEvhttpClientChannel::sendAndRecvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* sendBuf, apache::thrift::transport::TMemoryBuffer* recvBuf) { - cob_ = cob; - recvBuf_ = recvBuf; - struct evhttp_request* req = evhttp_request_new(response, this); if (req == NULL) { throw TException("evhttp_request_new failed"); @@ -88,6 +85,8 @@ void TEvhttpClientChannel::sendAndRecvMessage(const VoidCallback& cob, if (rv != 0) { throw TException("evhttp_make_request failed"); } + + completionQueue_.push(Completion(cob, recvBuf)); } void TEvhttpClientChannel::sendMessage(const VoidCallback& cob, @@ -107,9 +106,12 @@ void TEvhttpClientChannel::recvMessage(const VoidCallback& cob, } void TEvhttpClientChannel::finish(struct evhttp_request* req) { + assert(!completionQueue_.empty()); + Completion completion = completionQueue_.front(); + completionQueue_.pop(); if (req == NULL) { try { - cob_(); + completion.first(); } catch (const TTransportException& e) { if (e.getType() == TTransportException::END_OF_FILE) throw TException("connect failed"); @@ -119,7 +121,7 @@ void TEvhttpClientChannel::finish(struct evhttp_request* req) { return; } else if (req->response_code != 200) { try { - cob_(); + completion.first(); } catch (const TTransportException& e) { std::stringstream ss; ss << "server returned code " << req->response_code; @@ -132,9 +134,9 @@ void TEvhttpClientChannel::finish(struct evhttp_request* req) { } return; } - recvBuf_->resetBuffer(EVBUFFER_DATA(req->input_buffer), + completion.second->resetBuffer(EVBUFFER_DATA(req->input_buffer), static_cast<uint32_t>(EVBUFFER_LENGTH(req->input_buffer))); - cob_(); + completion.first(); return; } http://git-wip-us.apache.org/repos/asf/thrift/blob/39e505c1/lib/cpp/src/thrift/async/TEvhttpClientChannel.h ---------------------------------------------------------------------- diff --git a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h index 72ed40f..72eb32d 100644 --- a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h +++ b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h @@ -20,7 +20,9 @@ #ifndef _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ #define _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ 1 +#include <queue> #include <string> +#include <utility> #include <boost/shared_ptr.hpp> #include <thrift/async/TAsyncChannel.h> @@ -72,8 +74,9 @@ private: std::string host_; std::string path_; - VoidCallback cob_; - apache::thrift::transport::TMemoryBuffer* recvBuf_; + typedef std::pair<VoidCallback, apache::thrift::transport::TMemoryBuffer*> Completion; + typedef std::queue<Completion> CompletionQueue; + CompletionQueue completionQueue_; struct evhttp_connection* conn_; }; } http://git-wip-us.apache.org/repos/asf/thrift/blob/39e505c1/test/cpp/src/TestClient.cpp ---------------------------------------------------------------------- diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp index 5d06c56..6aebcdc 100644 --- a/test/cpp/src/TestClient.cpp +++ b/test/cpp/src/TestClient.cpp @@ -23,6 +23,7 @@ #include <locale> #include <ios> #include <iostream> +#include <sstream> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/protocol/TCompactProtocol.h> #include <thrift/protocol/THeaderProtocol.h> @@ -65,45 +66,38 @@ uint64_t now() { return ret; } -static void testString_clientReturn(const char* host, - int port, - event_base* base, - TProtocolFactory* protocolFactory, +static void testString_clientReturn(event_base* base, + int testNr, ThriftTestCobClient* client) { - (void)host; - (void)port; - (void)protocolFactory; try { string s; client->recv_testString(s); - cout << "testString: " << s << endl; + std::ostringstream os; + os << "test" << testNr; + const bool ok = (s == os.str()); + cout << "testString: " << s << " " << ((ok) ? "ok" : "failed") << endl; } catch (TException& exn) { cout << "Error: " << exn.what() << endl; } - event_base_loopbreak(base); // end test + if (testNr == 9) + event_base_loopbreak(base); // end test } -static void testVoid_clientReturn(const char* host, - int port, - event_base* base, - TProtocolFactory* protocolFactory, - ThriftTestCobClient* client) { +static void testVoid_clientReturn(event_base* base, ThriftTestCobClient* client) { try { client->recv_testVoid(); cout << "testVoid" << endl; - // next test - delete client; - boost::shared_ptr<TAsyncChannel> channel(new TEvhttpClientChannel(host, "/", host, port, base)); - client = new ThriftTestCobClient(channel, protocolFactory); - client->testString(tcxx::bind(testString_clientReturn, - host, - port, - base, - protocolFactory, - tcxx::placeholders::_1), - "Test"); + for (int testNr = 0; testNr < 10; ++testNr) { + std::ostringstream os; + os << "test" << testNr; + client->testString(tcxx::bind(testString_clientReturn, + base, + testNr, + tcxx::placeholders::_1), + os.str()); + } } catch (TException& exn) { cout << "Error: " << exn.what() << endl; } @@ -306,10 +300,7 @@ int main(int argc, char** argv) { new TEvhttpClientChannel(host.c_str(), "/", host.c_str(), port, base)); ThriftTestCobClient* client = new ThriftTestCobClient(channel, protocolFactory.get()); client->testVoid(tcxx::bind(testVoid_clientReturn, - host.c_str(), - port, base, - protocolFactory.get(), tcxx::placeholders::_1)); event_base_loop(base, 0);
