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
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 88f06ef..98edcfa 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -62,6 +62,9 @@
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";
}
@@ -238,6 +241,11 @@
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 @@
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<t_function*> functions = tservice->get_functions();
@@ -1991,27 +2003,49 @@
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 @@
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 @@
vector<t_field*>::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;