Thrift: generate python dictionaries and STL maps for server side process function lookups

Reviewed By: aditya


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664793 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 56980e4..ce93926 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -835,20 +835,7 @@
   // Generate the header portion
   f_header_ <<
     "class " << service_name_ << "Server : " <<
-    "public facebook::thrift::TProcessor {" << endl <<
-    " public: " << endl;
-  indent_up();
-  f_header_ << 
-    indent() <<
-    service_name_ << "Server(boost::shared_ptr<" << service_name_ << "If> iface, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> prot) : " <<
-                       "_iface(iface), _iprot(prot), _oprot(prot) {}" << endl <<
-    indent() <<
-    service_name_ << "Server(boost::shared_ptr<" << service_name_ << "If> iface, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) : " <<
-                       "_iface(iface), _iprot(iprot), _oprot(oprot) {}" << endl <<
-    indent() << "bool process(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, " <<
-                             "boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl <<
-    indent() << "virtual ~" << service_name_ << "Server() {}" << endl;
-  indent_down();
+    "public facebook::thrift::TProcessor {" << endl;
 
   // Protected data members
   f_header_ <<
@@ -857,7 +844,8 @@
   f_header_ <<
     indent() << "boost::shared_ptr<" << service_name_ << "If> _iface;" << endl <<
     indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> _iprot;" << endl <<
-    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> _oprot;" << endl;
+    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> _oprot;" << endl <<
+    indent() << "std::map<std::string, void (" << service_name_ << "Server::*)(int32_t, boost::shared_ptr<facebook::thrift::transport::TTransport>, boost::shared_ptr<facebook::thrift::transport::TTransport>)> _processMap;" << endl;
   indent_down();
 
   // Process function declarations
@@ -870,9 +858,40 @@
       "(int32_t seqid, boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl;
   }
   indent_down();
+
+  indent_up();
+  string declare_map = "";
+  indent_up();
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    declare_map += indent();
+    declare_map += "_processMap[\"";
+    declare_map += (*f_iter)->get_name();
+    declare_map += "\"] = &";
+    declare_map += service_name_;
+    declare_map += "Server::process_";
+    declare_map += (*f_iter)->get_name();
+    declare_map += ";\n";
+  }
+  indent_down();
+
+  f_header_ << 
+    " public: " << endl <<
+    indent() << service_name_ << "Server(boost::shared_ptr<" << service_name_ << "If> iface, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> prot) : " <<
+    "_iface(iface), _iprot(prot), _oprot(prot) {" << endl <<
+    declare_map <<
+    indent() << "}" << endl <<
+    indent() << service_name_ << "Server(boost::shared_ptr<" << service_name_ << "If> iface, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) : " <<
+    "_iface(iface), _iprot(iprot), _oprot(oprot) {" << endl <<
+    declare_map <<
+    indent() << "}" << endl <<
+    endl <<
+    indent() << "bool process(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl <<
+    indent() << "virtual ~" << service_name_ << "Server() {}" << endl;
+  indent_down();
   f_header_ <<
     "};" << endl << endl;
 
+
   // Generate the server implementation
   f_service_ <<
     "bool " << service_name_ << "Server::" <<
@@ -891,7 +910,19 @@
     indent() << "  throw facebook::thrift::Exception(\"Unexpected message type\");" << endl <<
     indent() << "}" << endl <<
     endl;
-    
+
+  // HOT: member function pointer map
+  f_service_ <<
+    indent() << "std::map<std::string, void (" << service_name_ << "Server::*)(int32_t, boost::shared_ptr<facebook::thrift::transport::TTransport>, boost::shared_ptr<facebook::thrift::transport::TTransport>)>::iterator pfn;" << endl <<
+    indent() << "pfn = _processMap.find(fname);" << endl <<
+    indent() << "if (pfn == _processMap.end()) {" << endl <<
+    indent() << "  throw facebook::thrift::Exception(\"Unknown function name: '\"+fname+\"'\");" << endl <<
+    indent() << "} else {" << endl <<
+    indent() << "  (this->*(pfn->second))(seqid, itrans, otrans);" << endl <<
+    indent() << "}" << endl;  
+
+  // DEPRECATED: if else if bullshit
+  /*
   bool first = true;
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     if (!first) {
@@ -917,6 +948,7 @@
   indent_down();
   indent(f_service_) <<
     "}" << endl;
+  */
 
   // Read end of args field, the T_STOP, and the struct close
   f_service_ <<
@@ -931,6 +963,7 @@
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     generate_process_function(tservice, *f_iter);
   }
+
 }
 
 /**
diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc
index 522ce38..a8f66ad 100644
--- a/compiler/cpp/src/generate/t_py_generator.cc
+++ b/compiler/cpp/src/generate/t_py_generator.cc
@@ -583,7 +583,15 @@
     indent() << "if oprot == None:" << endl <<
     indent() << "  self.__oprot = iprot" << endl <<
     indent() << "else:" << endl <<
-    indent() << "  self.__oprot = oprot" << endl;
+    indent() << "  self.__oprot = oprot" << endl <<
+    indent() << "self.__processMap = {" << endl;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ <<
+      indent() << "  \"" << (*f_iter)->get_name() << "\" : Server.process_" << (*f_iter)->get_name() << "," << endl;
+  }
+  f_service_ <<
+    indent() << "}" << endl;
+  
   indent_down();
   f_service_ << endl;
  
@@ -597,6 +605,14 @@
 
   // TODO(mcslee): validate message
 
+  // HOT: dictionary lookup
+  f_service_ <<
+    indent() << "if name not in self.__processMap:" << endl <<
+    indent() << "  print 'Unknown function %s' % (name)" << endl <<
+    indent() << "else:" << endl <<
+    indent() << "  self.__processMap[name](self, seqid, itrans, otrans)" << endl;
+  // DEPRECATED: if else if bullshit
+  /*
   bool first = true;
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     if (!first) {
@@ -616,7 +632,8 @@
     indent() << "else:" << endl <<
     indent() << "  print 'Unknown function %s' % (name)" << endl;
   f_service_ << endl;
-  
+  */  
+
   // Read end of args field, the T_STOP, and the struct close
   f_service_ <<
     indent() << "return True" << endl;