Add multiserver generation to C++ Thrift

Summary: Autogen server that can encapsulates multiple server instances

Reviewed By: aditya


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664782 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 6c5a0d6..2cff3fc 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -838,6 +838,9 @@
     "}" << endl <<
     endl;
 
+  // Multiserver
+  generate_service_multiserver(tservice);
+
   // Generate the process subfunctions
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     generate_process_function(tservice, *f_iter);
@@ -845,6 +848,100 @@
 }
 
 /**
+ * Generates a multiserver, which is a single server that just takes a set
+ * of objects implementing the interface and calls them all, returning the
+ * value of the last one to be called.
+ *
+ * @param tservice The service to generate a multiserver for.
+ */
+void t_cpp_generator::generate_service_multiserver(t_service* tservice) {
+    // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter; 
+
+  string list_type = string("std::vector<boost::shared_ptr<") + service_name_ + "If> >";
+
+  // Generate the header portion
+  f_header_ <<
+    "class " << service_name_ << "MultiServer : " <<
+    "public " << service_name_ << "Server {" << endl <<
+    " public: " << endl;
+  indent_up();
+  f_header_ << 
+    indent() <<
+    service_name_ << "MultiServer(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> protocol, " << list_type << "& servers) : " <<
+    service_name_ << "Server(protocol), _servers(servers) {}" << endl <<
+    indent() <<
+    service_name_ << "MultiServer(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot, " << list_type << "& servers) : " <<
+    service_name_ << "Server(iprot, oprot), _servers(servers) {}" << endl <<
+    indent() << "virtual ~" << service_name_ << "MultiServer() {}" << endl;
+  indent_down();
+
+  // Protected data members
+  f_header_ <<
+    " protected:" << endl;
+  indent_up();
+  f_header_ <<
+    indent() << list_type << "& _servers;" << endl;
+  indent_down();
+
+  f_header_ <<
+    indent() << " public:" << endl;
+  indent_up();
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arglist = (*f_iter)->get_arglist();
+    const vector<t_field*>& args = arglist->get_members();
+    vector<t_field*>::const_iterator a_iter;
+
+    string call = string("_servers[i]->") + (*f_iter)->get_name() + "(";
+    bool first = true;
+    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
+      if (first) {
+        first = false;
+      } else {
+        call += ", ";
+      }
+      call += (*a_iter)->get_name();
+    }
+    call += ")";
+
+    f_header_ <<
+      indent() << function_signature(*f_iter) << " {" << endl;
+    indent_up();
+    f_header_ <<
+      indent() << "uint32_t sz = _servers.size();" << endl <<
+      indent() << "for (uint32_t i = 0; i < sz; ++i) {" << endl;
+    if (!(*f_iter)->get_returntype()->is_void()) {
+      f_header_ <<
+        indent() << "  if (i == sz - 1) {" << endl <<
+        indent() << "    return " << call << ";" << endl <<
+        indent() << "  } else {" << endl <<
+        indent() << "    " << call << ";" << endl <<
+        indent() << "  }" << endl;
+    } else {
+      f_header_ <<
+        indent() << "  " << call << ";" << endl;
+    }
+
+    f_header_ <<
+      indent() << "}" << endl;
+    
+    indent_down();
+    f_header_ <<
+      indent() << "}" << endl <<
+      endl;
+  }
+
+  indent_down();
+
+  f_header_ <<
+    indent() << "};" << endl <<
+    endl;
+}
+
+
+/**
  * Generates a struct and helpers for a function.
  *
  * @param tfunction The function
diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h
index 7923852..fd208b6 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.h
+++ b/compiler/cpp/src/generate/t_cpp_generator.h
@@ -45,6 +45,7 @@
   void generate_service_helpers   (t_service* tservice);
   void generate_service_client    (t_service* tservice);
   void generate_service_server    (t_service* tservice);
+  void generate_service_multiserver(t_service* tservice);
   void generate_process_function  (t_service* tservice, t_function* tfunction);
 
   void generate_function_helpers  (t_function* tfunction);
diff --git a/lib/cpp/src/Thrift.h b/lib/cpp/src/Thrift.h
index 9254b56..410d20e 100644
--- a/lib/cpp/src/Thrift.h
+++ b/lib/cpp/src/Thrift.h
@@ -7,6 +7,7 @@
 #include <map>
 #include <list>
 #include <set>
+#include <vector>
 #include <exception>
 
 namespace facebook { namespace thrift {