From c6b4cab89c6da0272914a07b1f01491031df524f Mon Sep 17 00:00:00 2001 From: David Reiss Date: Wed, 6 Oct 2010 17:09:45 +0000 Subject: [PATCH] THRIFT-923. cpp: Add completion notification to async clients Add a virtual function "completed__(bool)" to xxxCobClient that is called by recv_xxx() after reception of a response (arg = true) or an exception (arg = false). This allows the TAsyncClient to intercede at that point, permitting, e.g., the load-balancing of persistent connections that would otherwise remain bound to a single server. A new "no_client_completion" flag inhibits generation of this mechanism. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@1005131 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_cpp_generator.cc | 93 +++++++++++++++++--- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 88f06efd..98edcfa3 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -62,6 +62,9 @@ class t_cpp_generator : public t_oop_generator { iter = parsed_options.find("cob_style"); gen_cob_style_ = (iter != parsed_options.end()); + iter = parsed_options.find("no_client_completion"); + gen_no_client_completion_ = (iter != parsed_options.end()); + out_dir_base_ = "gen-cpp"; } @@ -237,6 +240,11 @@ class t_cpp_generator : public t_oop_generator { */ bool gen_cob_style_; + /** + * True if we should omit calls to completion__() in CobClient class. + */ + bool gen_no_client_completion_; + /** * Strings for namespace, computed once up front then used directly */ @@ -1834,6 +1842,10 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) indent() << "boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl << indent() << " return channel_;" << endl << indent() << "}" << endl; + if (!gen_no_client_completion_) { + f_header_ << + indent() << "virtual void completed__(bool success) {}" << endl; + } } vector functions = tservice->get_functions(); @@ -1991,27 +2003,49 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) endl << indent() << "int32_t rseqid = 0;" << endl << indent() << "std::string fname;" << endl << - indent() << "::apache::thrift::protocol::TMessageType mtype;" << endl << - endl << + indent() << "::apache::thrift::protocol::TMessageType mtype;" << endl; + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << "bool completed = false;" << endl << endl << + indent() << "try {"; + indent_up(); + } + f_service_ << endl << indent() << "iprot_->readMessageBegin(fname, mtype, rseqid);" << endl << indent() << "if (mtype == ::apache::thrift::protocol::T_EXCEPTION) {" << endl << indent() << " ::apache::thrift::TApplicationException x;" << endl << indent() << " x.read(iprot_);" << endl << indent() << " iprot_->readMessageEnd();" << endl << - indent() << " iprot_->getTransport()->readEnd();" << endl << + indent() << " iprot_->getTransport()->readEnd();" << endl; + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << " completed = true;" << endl << + indent() << " completed__(true);" << endl; + } + f_service_ << indent() << " throw x;" << endl << indent() << "}" << endl << indent() << "if (mtype != ::apache::thrift::protocol::T_REPLY) {" << endl << indent() << " iprot_->skip(::apache::thrift::protocol::T_STRUCT);" << endl << indent() << " iprot_->readMessageEnd();" << endl << - indent() << " iprot_->getTransport()->readEnd();" << endl << - indent() << " throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE);" << endl << + indent() << " iprot_->getTransport()->readEnd();" << endl; + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << " completed = true;" << endl << + indent() << " completed__(false);" << endl; + } + f_service_ << indent() << "}" << endl << indent() << "if (fname.compare(\"" << (*f_iter)->get_name() << "\") != 0) {" << endl << indent() << " iprot_->skip(::apache::thrift::protocol::T_STRUCT);" << endl << indent() << " iprot_->readMessageEnd();" << endl << - indent() << " iprot_->getTransport()->readEnd();" << endl << - indent() << " throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::WRONG_METHOD_NAME);" << endl << + indent() << " iprot_->getTransport()->readEnd();" << endl; + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << " completed = true;" << endl << + indent() << " completed__(false);" << endl; + } + f_service_ << indent() << "}" << endl; if (!(*f_iter)->get_returntype()->is_void() && @@ -2040,12 +2074,24 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) if (is_complex_type((*f_iter)->get_returntype())) { f_service_ << indent() << "if (result.__isset.success) {" << endl << - indent() << " // _return pointer has now been filled" << endl << + indent() << " // _return pointer has now been filled" << endl; + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << " completed = true;" << endl << + indent() << " completed__(true);" << endl; + } + f_service_ << indent() << " return;" << endl << indent() << "}" << endl; } else { f_service_ << - indent() << "if (result.__isset.success) {" << endl << + indent() << "if (result.__isset.success) {" << endl; + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << " completed = true;" << endl << + indent() << " completed__(true);" << endl; + } + f_service_ << indent() << " return _return;" << endl << indent() << "}" << endl; } @@ -2056,20 +2102,45 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << - indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl << + indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl; + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << " completed = true;" << endl << + indent() << " completed__(true);" << endl; + } + f_service_ << indent() << " throw result." << (*x_iter)->get_name() << ";" << endl << indent() << "}" << endl; } // We only get here if we are a void function if ((*f_iter)->get_returntype()->is_void()) { + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << "completed = true;" << endl << + indent() << "completed__(true);" << endl; + } indent(f_service_) << "return;" << endl; } else { + if (style == "Cob" && !gen_no_client_completion_) { + f_service_ << + indent() << "completed = true;" << endl << + indent() << "completed__(true);" << endl; + } f_service_ << indent() << "throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; } - + if (style == "Cob" && !gen_no_client_completion_) { + indent_down(); + f_service_ << + indent() << "} catch (...) {" << endl << + indent() << " if (!completed) {" << endl << + indent() << " completed__(false);" << endl << + indent() << " }" << endl << + indent() << " throw;" << endl << + indent() << "}" << endl; + } // Close function scope_down(f_service_); f_service_ << endl; -- 2.17.1