OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
t_cpp_generator.cc
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  *
19  * Contains some contributions under the Thrift Software License.
20  * Please see doc/old-thrift-license.txt in the Thrift distribution for
21  * details.
22  */
23 
24 #include <cassert>
25 
26 #include <fstream>
27 #include <iostream>
28 #include <sstream>
29 #include <string>
30 #include <vector>
31 #ifdef SANDESH
32 #include <algorithm>
33 #endif
34 
35 #include <sys/stat.h>
36 #include <boost/tuple/tuple.hpp>
37 #include "platform.h"
38 #include "t_oop_generator.h"
39 using namespace std;
40 using boost::tuple;
41 using boost::tuples::make_tuple;
42 
48  public:
50  t_program* program,
51  const std::map<std::string, std::string>& parsed_options,
52  const std::string& option_string)
53  : t_oop_generator(program)
54  {
55  (void) option_string;
56  std::map<std::string, std::string>::const_iterator iter;
57 
58  iter = parsed_options.find("pure_enums");
59  gen_pure_enums_ = (iter != parsed_options.end());
60 
61  iter = parsed_options.find("dense");
62  gen_dense_ = (iter != parsed_options.end());
63 
64  iter = parsed_options.find("include_prefix");
65  use_include_prefix_ = (iter != parsed_options.end());
66 
67  iter = parsed_options.find("cob_style");
68  gen_cob_style_ = (iter != parsed_options.end());
69 
70  iter = parsed_options.find("no_client_completion");
71  gen_no_client_completion_ = (iter != parsed_options.end());
72 
73  iter = parsed_options.find("templates");
74  gen_templates_ = (iter != parsed_options.end());
75 
76  out_dir_base_ = "gen-cpp";
77  }
78 
83  void init_generator();
84  void close_generator();
85 
86  void generate_consts(std::vector<t_const*> consts);
87 
92  void generate_typedef(t_typedef* ttypedef);
93  void generate_enum(t_enum* tenum);
94  void generate_struct(t_struct* tstruct) {
95  generate_cpp_struct(tstruct, false);
96  }
97  void generate_xception(t_struct* txception) {
98  generate_cpp_struct(txception, true);
99  }
100 #ifdef SANDESH
101  void generate_sandesh(t_sandesh* tsandesh) {
102  generate_cpp_sandesh(tsandesh);
103  }
104  void generate_cpp_sandesh(t_sandesh* tsandesh);
105  void generate_sandesh_definition (std::ofstream& out, t_sandesh* tsandesh);
106  void generate_sandesh_fingerprint (std::ofstream& out, t_sandesh* tsandesh, bool is_definition);
107  void generate_sandesh_http_reader (std::ofstream& out, t_sandesh* tsandesh);
108  void generate_sandesh_reader (std::ofstream& out, t_sandesh* tsandesh);
109  void generate_sandesh_writer (std::ofstream& out, t_sandesh* tsandesh);
110  void generate_sandesh_creator (std::ofstream& out, t_sandesh* tsandesh);
111  void generate_sandesh_member_init_list(std::ofstream& out, t_sandesh* tsandesh, bool init_dval = false);
112  void generate_sandesh_base_init (ofstream& out, t_sandesh* tsandesh, bool init_dval);
113  void generate_sandesh_hints (std::ofstream& out, t_sandesh* tsandesh);
114  void generate_sandesh_request (std::ofstream& out, t_sandesh* tsandesh);
115  void generate_sandesh_default_ctor (std::ofstream& out, t_sandesh* tsandesh, bool is_request);
116  void generate_sandesh_loggers (std::ofstream& out, t_sandesh* tsandesh);
117  void generate_logger_field (std::ofstream& out, t_field *tfield, string prefix, bool log_value_only, bool no_name_log, bool for_sandesh = false);
118  void generate_logger_struct (std::ofstream& out, t_struct *tstruct, string prefix, string name);
119  void generate_logger_container (std::ofstream& out, t_type* ttype, string name, bool log_value_only);
120  void generate_logger_map_element (std::ofstream& out, t_map* tmap, string iter, bool log_value_only);
121  void generate_logger_set_element (std::ofstream& out, t_set* tset, string iter, bool log_value_only);
122  void generate_logger_list_element (std::ofstream& out, t_list* tlist, string iter, bool log_value_only);
123  void generate_sandesh_get_size (std::ofstream& out, t_sandesh* tsandesh);
124  void generate_get_size_field (std::ofstream& out, t_field *tfield);
125  void generate_get_size_struct (std::ofstream& out, t_struct *tstruct, string name);
126  void generate_get_size_container (std::ofstream& out, t_type* ttype, string name);
127  void generate_get_size_map_element (std::ofstream& out, t_map* tmap, string name);
128  void generate_get_size_list_element(std::ofstream& out, t_list* ttype, string name);
129  void generate_get_size_set_element (std::ofstream& out, t_set* ttype, string name);
130  void generate_sandesh_trace (std::ofstream& out, t_sandesh* tsandesh);
131  void generate_sandesh_context (std::ofstream& out, t_sandesh* tsandesh, string val);
132  void generate_sandesh_seqnum(std::ofstream& out, t_sandesh* tsandesh);
133  void generate_sandesh_versionsig(std::ofstream& out, t_sandesh* tsandesh);
134  void generate_sandesh_static_seqnum_def(std::ofstream& out, t_sandesh* tsandesh);
135  void generate_sandesh_static_versionsig_def(std::ofstream& out, t_sandesh* tsandesh);
136  void generate_sandesh_trace_seqnum_ctor(std::ofstream& out, t_sandesh* tsandesh);
137  void generate_static_const_string_definition(std::ofstream& out, t_sandesh* tsandesh);
138  std::string generate_sandesh_no_static_const_string_function(t_sandesh *tsandesh, bool signature, bool autogen_darg, bool trace = false, bool request = false, bool ctorcall = false);
139  void generate_static_const_string_definition(std::ofstream& out, std::string name,
140  const vector<t_field*>& fields);
141  std::string generate_sandesh_async_creator(t_sandesh *tsandesh, bool signature, bool expand_autogen, bool skip_autogen,
142  std::string prefix, std::string suffix, bool category_level_file_line_first,
143  bool autogen_category_level, bool drop_log_reason, bool use_sandesh_object = false);
144  void generate_sandesh_rate_limit_fn(ofstream &out, t_sandesh *tsandesh);
145  void generate_sandesh_async_send_fn(ofstream &out, t_sandesh *tsandesh,
146  bool generate_sandesh_object, bool generate_rate_limit, bool generate_system_log);
147  void generate_sandesh_async_send_macros(ofstream &out, t_sandesh *tsandesh,
148  bool generate_sandesh_object);
149  void generate_sandesh_static_log_fn(ofstream &out, t_sandesh *tsandesh,
150  bool generate_sandesh_object);
151  void generate_sandesh_async_create_fn(ofstream &out, t_sandesh *tsandesh);
152  void generate_sandesh_async_create_macro(ofstream &out, t_sandesh *tsandesh);
153  void generate_sandesh_session_log_unrolled_fn(ofstream &out, t_sandesh *tsandesh);
154  void generate_sandesh_session_adjust_session_end_point_objects_fn(ofstream &out,
155  t_sandesh *tsandesh);
156  void generate_sandesh_flow_send_fn(ofstream &out, t_sandesh *tsandesh);
157  void generate_sandesh_systemlog_creators(ofstream &out, t_sandesh *tsandesh);
158  void generate_sandesh_objectlog_creators(ofstream &out, t_sandesh *tsandesh);
159  void generate_sandesh_flow_creators(ofstream &out, t_sandesh *tsandesh);
160  void generate_sandesh_uve_creator(std::ofstream& out, t_sandesh* tsandesh);
161  std::string generate_sandesh_trace_creator(t_sandesh *tsandesh, bool signature, bool expand_autogen, bool skip_autogen,
162  std::string prefix, std::string suffix);
163  void generate_sandesh_updater(ofstream& out, t_sandesh* tsandesh);
164  void generate_isRatelimitPass(ofstream& out, t_sandesh* tsandesh);
165  void generate_sandesh_static_rate_limit_log_def(ofstream& out, t_sandesh* tsandesh);
166  void generate_sandesh_static_rate_limit_mutex_def(ofstream& out, t_sandesh* tsandesh);
167  void generate_sandesh_static_rate_limit_buffer_def(ofstream& out, t_sandesh* tsandesh);
168 
169  typedef enum {
170  MANDATORY = 0,
171  INLINE = 1,
172  HIDDEN = 2,
173  PERIODIC = 3,
174  HIDDEN_PER = 4,
175  CA_MAX = 5
176  } CacheAttribute;
177 
178  typedef enum {
179  RM_DIAL = 0,
180  RM_AGG = 1,
181  RM_DIFF = 2,
182  RM_MAX = 3
183  } RawMetric;
184 
185  struct DSInfo {
186  DSInfo(bool is_map, size_t period, CacheAttribute cat,
187  string rawtype, RawMetric rmtype,
188  string resulttype, string algo, string annotation,
189  string compattr, string subcompattr, string prealgo) :
190  is_map_(is_map), period_(period), cat_(cat),
191  rawtype_(rawtype), rmtype_(rmtype),
192  resulttype_(resulttype), algo_(algo),
193  annotation_(annotation),
194  compattr_(compattr) , subcompattr_(subcompattr), prealgo_(prealgo) {}
195  bool is_map_;
196  size_t period_;
197  CacheAttribute cat_;
198  string rawtype_;
199  RawMetric rmtype_;
200  string resulttype_;
201  string algo_;
202  string annotation_;
203  string compattr_;
204  string subcompattr_;
205  string prealgo_;
206  };
207  void derived_stats_info(t_struct* tstruct,
208  map<string,DSInfo>& dsmap,
209  // val is set of ds attributes
210  map<string,set<string> >& rawmap);
211 
212  void cache_attr_info(t_struct* tstruct, std::map<string, CacheAttribute>& attrs);
213 
214  void freq_info(t_struct* tstruct,
215  set<string>& inl, set<string>& never, set<string>& periodic);
216 #endif
217 
218  void generate_cpp_struct(t_struct* tstruct, bool is_exception);
219 
220  void generate_service(t_service* tservice);
221 
222  void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
223  std::string render_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
224 
225  void generate_struct_definition (std::ofstream& out, t_struct* tstruct, bool is_exception=false, bool pointers=false, bool read=true, bool write=true);
226  void generate_struct_fingerprint (std::ofstream& out, t_struct* tstruct, bool is_definition);
227  void generate_struct_reader (std::ofstream& out, t_struct* tstruct, bool pointers=false);
228  void generate_struct_writer (std::ofstream& out, t_struct* tstruct, bool pointers=false);
229  void generate_struct_result_writer (std::ofstream& out, t_struct* tstruct, bool pointers=false);
230 #ifdef SANDESH
231  void generate_static_const_string_definition(std::ofstream& out, t_struct* tstruct);
232  void generate_struct_logger (ofstream& out, const string& name,
233  const vector<t_field*>& fields);
234  void generate_struct_get_size (ofstream& out, const string& name,
235  const vector<t_field*>& fields);
236 #endif
237 
242  void generate_service_interface (t_service* tservice, string style);
243  void generate_service_interface_factory (t_service* tservice, string style);
244  void generate_service_null (t_service* tservice, string style);
245  void generate_service_multiface (t_service* tservice);
246  void generate_service_helpers (t_service* tservice);
247  void generate_service_client (t_service* tservice, string style);
248  void generate_service_processor (t_service* tservice, string style);
249  void generate_service_skeleton (t_service* tservice);
250  void generate_process_function (t_service* tservice, t_function* tfunction,
251  string style, bool specialized=false);
252  void generate_function_helpers (t_service* tservice, t_function* tfunction);
253  void generate_service_async_skeleton (t_service* tservice);
254 
259  void generate_deserialize_field (std::ofstream& out,
260  t_field* tfield,
261  std::string prefix="",
262  std::string suffix="");
263 
264  void generate_deserialize_struct (std::ofstream& out,
265  t_struct* tstruct,
266  std::string prefix="");
267 
268  void generate_deserialize_container (std::ofstream& out,
269  t_type* ttype,
270  std::string prefix="");
271 
272  void generate_deserialize_set_element (std::ofstream& out,
273  t_set* tset,
274  std::string prefix="");
275 
276  void generate_deserialize_map_element (std::ofstream& out,
277  t_map* tmap,
278  std::string prefix="");
279 
280  void generate_deserialize_list_element (std::ofstream& out,
281  t_list* tlist,
282  std::string prefix,
283  bool push_back,
284  std::string index);
285 
286  void generate_serialize_field (std::ofstream& out,
287  t_field* tfield,
288  std::string prefix="",
289  std::string suffix="");
290 
291  void generate_serialize_struct (std::ofstream& out,
292  t_struct* tstruct,
293  std::string prefix="");
294 
295  void generate_serialize_container (std::ofstream& out,
296  t_type* ttype,
297  std::string prefix="");
298 
299  void generate_serialize_map_element (std::ofstream& out,
300  t_map* tmap,
301  std::string iter);
302 
303  void generate_serialize_set_element (std::ofstream& out,
304  t_set* tmap,
305  std::string iter);
306 
307  void generate_serialize_list_element (std::ofstream& out,
308  t_list* tlist,
309  std::string iter);
310 
311  void generate_function_call (ostream& out,
312  t_function* tfunction,
313  string target,
314  string iface,
315  string arg_prefix);
316 
317 #ifdef SANDESH
318  void generate_serialize_sandesh (std::ofstream& out,
319  t_sandesh* tsandesh,
320  std::string prefix="");
321 #endif
322 
323  /*
324  * Helper rendering functions
325  */
326 
327  std::string namespace_prefix(std::string ns);
328  std::string namespace_open(std::string ns);
329  std::string namespace_close(std::string ns);
330  std::string type_name(t_type* ttype, bool in_typedef=false, bool arg=false);
331  std::string base_type_name(t_base_type::t_base tbase);
332 #ifdef SANDESH
333  std::string declare_field(t_field* tfield, bool init=false, bool pointer=false, bool constant=false, bool reference=false, bool constructor=false);
334 #else
335  std::string declare_field(t_field* tfield, bool init=false, bool pointer=false, bool constant=false, bool reference=false);
336 #endif
337  std::string function_signature(t_function* tfunction, std::string style, std::string prefix="", bool name_params=true);
338  std::string cob_function_signature(t_function* tfunction, std::string prefix="", bool name_params=true);
339  std::string argument_list(t_struct* tstruct, bool name_params=true, bool start_comma=false);
340  std::string type_to_enum(t_type* ttype);
341  std::string local_reflection_name(const char*, t_type* ttype, bool external=false);
342 
343  void generate_enum_constant_list(std::ofstream& f,
344  const vector<t_enum_value*>& constants,
345  const char* prefix,
346  const char* suffix,
347  bool include_values);
348 
349  // These handles checking gen_dense_ and checking for duplicates.
350  void generate_local_reflection(std::ofstream& out, t_type* ttype, bool is_definition);
351  void generate_local_reflection_pointer(std::ofstream& out, t_type* ttype);
352 
353  bool is_complex_type(t_type* ttype) {
354  ttype = get_true_type(ttype);
355 
356  return
357  ttype->is_container() ||
358  ttype->is_struct() ||
359  ttype->is_xception() ||
360 #ifdef SANDESH
361  ttype->is_sandesh() ||
362  (ttype->is_base_type() && (((t_base_type *)ttype)->get_base() == t_base_type::TYPE_XML)) ||
363 #endif
364  (ttype->is_base_type() && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING));
365  }
366 
367  void set_use_include_prefix(bool use_include_prefix) {
368  use_include_prefix_ = use_include_prefix;
369  }
370 
371  private:
376  std::string get_include_prefix(const t_program& program) const;
377 
382  void generate_common_struct_reader_body(std::ofstream& out,
383  t_struct_common* tstruct,
384  bool pointers = false);
385 
390  void generate_common_struct_writer_body(std::ofstream& out,
391  t_struct_common* tstruct,
392  bool pointers = false);
393 
398 
403 
408 
414 
419 
424 
429  std::string ns_open_;
430  std::string ns_close_;
431 
437  std::ofstream f_types_;
438  std::ofstream f_types_impl_;
439  std::ofstream f_types_tcc_;
440  std::ofstream f_header_;
441  std::ofstream f_service_;
442  std::ofstream f_service_tcc_;
443 #ifdef SANDESH
444  std::ofstream f_request_impl_;
445  std::ofstream f_html_template_;
446  struct sandesh_logger {
447  enum type {
448  BUFFER,
449  LOG,
450  FORCED_LOG,
451  };
452  };
453  void generate_sandesh_logger(std::ofstream& out, t_sandesh* tsandesh,
454  sandesh_logger::type ltype);
455  void generate_sandesh_static_logger(ofstream &out, t_sandesh *tsandesh,
456  bool generate_sandesh_object);
457  void generate_sandesh_static_drop_logger(ofstream &out, t_sandesh *tsandesh,
458  bool generate_sandesh_object);
459 #endif
460 
464  std::set<std::string> reflected_fingerprints_;
465 
466  // The ProcessorGenerator is used to generate parts of the code,
467  // so it needs access to many of our protected members and methods.
468  //
469  // TODO: The code really should be cleaned up so that helper methods for
470  // writing to the output files are separate from the generator classes
471  // themselves.
472  friend class ProcessorGenerator;
473 };
474 
480  // Make output directory
481  MKDIR(get_out_dir().c_str());
482 
483  // Make output file
484  string f_types_name = get_out_dir()+program_name_+"_types.h";
485  f_types_.open(f_types_name.c_str());
486 
487  string f_types_impl_name = get_out_dir()+program_name_+"_types.cpp";
488  f_types_impl_.open(f_types_impl_name.c_str());
489 
490 #ifdef SANDESH
491  string f_request_impl_name = get_out_dir()+program_name_+"_request_skeleton.cpp";
492  f_request_impl_.open(f_request_impl_name.c_str());
493 
494  string f_html_template_name = get_out_dir()+program_name_+"_html_template.cpp";
495  f_html_template_.open(f_html_template_name.c_str());
496 #endif
497 
498  if (gen_templates_) {
499  // If we don't open the stream, it appears to just discard data,
500  // which is fine.
501  string f_types_tcc_name = get_out_dir()+program_name_+"_types.tcc";
502  f_types_tcc_.open(f_types_tcc_name.c_str());
503  }
504 
505  // Print header
506  f_types_ <<
507  autogen_comment();
508  f_types_impl_ <<
509  autogen_comment();
510  f_types_tcc_ <<
511  autogen_comment();
512 #ifdef SANDESH
513  f_request_impl_ <<
514  autogen_comment();
515  f_html_template_ <<
516  autogen_comment();
517 #endif
518 
519  // Start ifndef
520  f_types_ <<
521  "#ifndef " << program_name_ << "_TYPES_H" << endl <<
522  "#define " << program_name_ << "_TYPES_H" << endl <<
523  endl;
524  f_types_tcc_ <<
525  "#ifndef " << program_name_ << "_TYPES_TCC" << endl <<
526  "#define " << program_name_ << "_TYPES_TCC" << endl <<
527  endl;
528 
529  // Include base types
530  f_types_ <<
531  "#include <sandesh/Thrift.h>" << endl <<
532 #ifndef SANDESH
533  "#include <TApplicationException.h>" << endl <<
534 #else
535  "#include <tbb/atomic.h>" << endl <<
536  "#include <boost/shared_ptr.hpp>" << endl <<
537  "#include <sandesh/derived_stats.h>" << endl <<
538  "#include <sandesh/derived_stats_algo.h>" << endl <<
539  "#include <boost/pointer_cast.hpp>" << endl <<
540 #endif
541  "#include <base/trace.h>" << endl;
542  if (program_name_ != "sandesh") {
543  f_types_ << "#include <sandesh/sandesh_types.h>" << endl;
544  f_types_ << "#include <sandesh/sandesh_constants.h>" << endl;
545  if (program_name_ != "derived_stats_results" && program_name_ != "vns") {
546  f_types_ << "#include <sandesh/sandesh.h>" << endl;
547  }
548  }
549  f_types_ <<
550  "#include <sandesh/protocol/TProtocol.h>" << endl <<
551  "#include <sandesh/transport/TTransport.h>" << endl <<
552  endl;
553 
554  // Include other Thrift includes
555  const vector<t_program*>& includes = program_->get_includes();
556  for (size_t i = 0; i < includes.size(); ++i) {
557  f_types_ <<
558  "#include \"" << get_include_prefix(*(includes[i])) <<
559  includes[i]->get_name() << "_types.h\"" << endl;
560 
561  // XXX(simpkins): If gen_templates_ is enabled, we currently assume all
562  // included files were also generated with templates enabled.
563  f_types_tcc_ <<
564  "#include \"" << get_include_prefix(*(includes[i])) <<
565  includes[i]->get_name() << "_types.tcc\"" << endl;
566  }
567  f_types_ << endl;
568 
569  // Include custom headers
570  const vector<string>& cpp_includes = program_->get_cpp_includes();
571  for (size_t i = 0; i < cpp_includes.size(); ++i) {
572  if (cpp_includes[i][0] == '<') {
573  f_types_ <<
574  "#include " << cpp_includes[i] << endl;
575  } else {
576  f_types_ <<
577  "#include \"" << cpp_includes[i] << "\"" << endl;
578  }
579  }
580  f_types_ <<
581  endl;
582 
583  // Include the types file
584 #ifdef SANDESH
585  f_types_impl_ <<
586  "#include <boost/date_time/posix_time/posix_time.hpp>" << endl << endl <<
587  "#include <base/logging.h>" << endl << endl <<
588  "#include <sandesh/sandesh_uve.h>" << endl <<
589  "#include <sandesh/sandesh_http.h>" << endl <<
590  "#include <sandesh/sandesh_trace.h>" << endl <<
591  "#include <curl/curl.h>" << endl <<
592  "#include <boost/foreach.hpp>" << endl <<
593  "#include <boost/assign/list_of.hpp>" << endl <<
594  "#include <boost/make_shared.hpp>" << endl << endl;
595 #endif
596  f_types_impl_ <<
597  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
598  "_types.h\"" << endl <<
599  endl;
600  f_types_tcc_ <<
601  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
602  "_types.h\"" << endl <<
603  endl;
604 #ifdef SANDESH
605  f_request_impl_ <<
606  "#include <sandesh/sandesh_types.h>" << endl <<
607  "#include <sandesh/sandesh_constants.h>" << endl <<
608  "#include <sandesh/sandesh.h>" << endl <<
609  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
610  "_types.h\"" << endl <<
611  endl;
612  f_html_template_ <<
613  "#include <sandesh/sandesh_http.h>" << endl;
614  f_html_template_ <<
615  "static SandeshHttp::HtmlInfo h_info(" <<
616  program_name_ << "_xml," << program_name_ << "_xml_len);" << endl;
617  f_html_template_ <<
618  "static SandeshHttp sh(\"" << program_name_ << ".xml\", h_info);" << endl;
619  f_html_template_ << "int " << program_name_ << "_marker = 0;" << endl;
620 
621 #endif
622 
623 
624  // If we are generating local reflection metadata, we need to include
625  // the definition of TypeSpec.
626  if (gen_dense_) {
627  f_types_impl_ <<
628  "#include <TReflectionLocal.h>" << endl <<
629  endl;
630  }
631 
632  // Open namespace
633  ns_open_ = namespace_open(program_->get_namespace("cpp"));
634  ns_close_ = namespace_close(program_->get_namespace("cpp"));
635 
636  f_types_ <<
637  ns_open_ << endl <<
638  endl;
639 
640  f_types_impl_ <<
641  ns_open_ << endl <<
642  endl;
643 
644  f_types_tcc_ <<
645  ns_open_ << endl <<
646  endl;
647 
648 #ifdef SANDESH
649  f_request_impl_ <<
650  ns_open_ << endl <<
651  endl;
652 #endif
653 }
654 
659  // Close namespace
660  f_types_ <<
661  ns_close_ << endl <<
662  endl;
663  f_types_impl_ <<
664  ns_close_ << endl;
665  f_types_tcc_ <<
666  ns_close_ << endl <<
667  endl;
668 #ifdef SANDESH
669  f_request_impl_ <<
670  ns_close_ << endl;
671 #endif
672 
673  // Include the types.tcc file from the types header file,
674  // so clients don't have to explicitly include the tcc file.
675  // TODO(simpkins): Make this a separate option.
676  if (gen_templates_) {
677  f_types_ <<
678  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
679  "_types.tcc\"" << endl <<
680  endl;
681  }
682 
683  // Close ifndef
684  f_types_ <<
685  "#endif" << endl;
686  f_types_tcc_ <<
687  "#endif" << endl;
688 
689  // Close output file
690  f_types_.close();
691  f_types_impl_.close();
692  f_types_tcc_.close();
693 #ifdef SANDESH
694  f_request_impl_.close();
695  f_html_template_.close();
696 #endif
697 }
698 
705  f_types_ <<
706  indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << ttypedef->get_symbolic() << ";" << endl <<
707  endl;
708 }
709 
710 
712  const vector<t_enum_value*>& constants,
713  const char* prefix,
714  const char* suffix,
715  bool include_values) {
716  f << " {" << endl;
717  indent_up();
718 
719  vector<t_enum_value*>::const_iterator c_iter;
720  bool first = true;
721  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
722  if (first) {
723  first = false;
724  } else {
725  f << "," << endl;
726  }
727  indent(f)
728  << prefix << (*c_iter)->get_name() << suffix;
729  if (include_values && (*c_iter)->has_value()) {
730  f << " = " << (*c_iter)->get_value();
731  }
732  }
733 
734  f << endl;
735  indent_down();
736  indent(f) << "};" << endl;
737 }
738 
746  vector<t_enum_value*> constants = tenum->get_constants();
747 
748  std::string enum_name = tenum->get_name();
749  if (!gen_pure_enums_) {
750  enum_name = "type";
751  f_types_ <<
752  indent() << "struct " << tenum->get_name() << " {" << endl;
753  indent_up();
754  }
755  f_types_ <<
756  indent() << "enum " << enum_name;
757 
758  generate_enum_constant_list(f_types_, constants, "", "", true);
759 
760  if (!gen_pure_enums_) {
761  indent_down();
762  f_types_ << "};" << endl;
763  }
764 
765  f_types_ << endl;
766 
770  std::string prefix = "";
771  if (!gen_pure_enums_) {
772  prefix = tenum->get_name() + "::";
773  }
774 
775  f_types_impl_ <<
776  indent() << "int _k" << tenum->get_name() << "Values[] =";
777  generate_enum_constant_list(f_types_impl_, constants, prefix.c_str(), "", false);
778 
779  f_types_impl_ <<
780  indent() << "const char* _k" << tenum->get_name() << "Names[] =";
781  generate_enum_constant_list(f_types_impl_, constants, "\"", "\"", false);
782 
783  f_types_ <<
784  indent() << "extern const std::map<int, const char*> _" <<
785  tenum->get_name() << "_VALUES_TO_NAMES;" << endl << endl;
786 
787  f_types_impl_ <<
788  indent() << "const std::map<int, const char*> _" << tenum->get_name() <<
789  "_VALUES_TO_NAMES(::contrail::sandesh::TEnumIterator(" << constants.size() <<
790  ", _k" << tenum->get_name() << "Values" <<
791  ", _k" << tenum->get_name() << "Names), " <<
792  "::contrail::sandesh::TEnumIterator(-1, NULL, NULL));" << endl << endl;
793 
794  generate_local_reflection(f_types_, tenum, false);
795  generate_local_reflection(f_types_impl_, tenum, true);
796 }
797 
801 void t_cpp_generator::generate_consts(std::vector<t_const*> consts) {
802  string f_consts_name = get_out_dir()+program_name_+"_constants.h";
803  ofstream f_consts;
804  f_consts.open(f_consts_name.c_str());
805 
806  string f_consts_impl_name = get_out_dir()+program_name_+"_constants.cpp";
807  ofstream f_consts_impl;
808  f_consts_impl.open(f_consts_impl_name.c_str());
809 
810  // Print header
811  f_consts <<
812  autogen_comment();
813  f_consts_impl <<
814  autogen_comment();
815 
816  // Start ifndef
817  f_consts <<
818  "#ifndef " << program_name_ << "_CONSTANTS_H" << endl <<
819  "#define " << program_name_ << "_CONSTANTS_H" << endl <<
820  endl <<
821  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
822  "_types.h\"" << endl <<
823  endl <<
824  ns_open_ << endl <<
825  endl;
826 
827 #ifdef SANDESH
828  f_consts_impl <<
829  "#include <base/trace.h>" << endl <<
830  "#include <sandesh/sandesh_types.h>" << endl <<
831  "#include <sandesh/sandesh_constants.h>" << endl <<
832  "#include <sandesh/sandesh.h>" << endl <<
833  "#include <sandesh/sandesh_trace.h>" << endl << endl;
834 #endif
835  f_consts_impl <<
836  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
837  "_constants.h\"" << endl <<
838  endl <<
839  ns_open_ << endl <<
840  endl;
841 
842  f_consts <<
843  "class " << program_name_ << "Constants {" << endl <<
844  " public:" << endl <<
845  " " << program_name_ << "Constants();" << endl <<
846  endl;
847  indent_up();
848  vector<t_const*>::iterator c_iter;
849  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
850  string name = (*c_iter)->get_name();
851  t_type* type = (*c_iter)->get_type();
852  f_consts <<
853  indent() << type_name(type) << " " << name << ";" << endl;
854  }
855  indent_down();
856  f_consts <<
857  "};" << endl;
858 
859  f_consts_impl <<
860  "const " << program_name_ << "Constants g_" << program_name_ << "_constants;" << endl <<
861  endl <<
862  program_name_ << "Constants::" << program_name_ << "Constants() {" << endl;
863  indent_up();
864  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
865  print_const_value(f_consts_impl,
866  (*c_iter)->get_name(),
867  (*c_iter)->get_type(),
868  (*c_iter)->get_value());
869  }
870  indent_down();
871  indent(f_consts_impl) <<
872  "}" << endl;
873 
874  f_consts <<
875  endl <<
876  "extern const " << program_name_ << "Constants g_" << program_name_ << "_constants;" << endl <<
877  endl <<
878  ns_close_ << endl <<
879  endl <<
880  "#endif" << endl;
881  f_consts.close();
882 
883  f_consts_impl <<
884  endl <<
885  ns_close_ << endl <<
886  endl;
887 }
888 
894 void t_cpp_generator::print_const_value(ofstream& out, string name, t_type* type, t_const_value* value) {
895  type = get_true_type(type);
896  if (type->is_base_type()) {
897  string v2 = render_const_value(out, name, type, value);
898  indent(out) << name << " = " << v2 << ";" << endl <<
899  endl;
900  } else if (type->is_enum()) {
901  indent(out) << name << " = (" << type_name(type) << ")" << value->get_integer() << ";" << endl <<
902  endl;
903  } else if (type->is_struct() || type->is_xception()) {
904  const vector<t_field*>& fields = ((t_struct*)type)->get_members();
905  vector<t_field*>::const_iterator f_iter;
906  const map<t_const_value*, t_const_value*>& val = value->get_map();
907  map<t_const_value*, t_const_value*>::const_iterator v_iter;
908  for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
909  t_type* field_type = NULL;
910  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
911  if ((*f_iter)->get_name() == v_iter->first->get_string()) {
912  field_type = (*f_iter)->get_type();
913  }
914  }
915  if (field_type == NULL) {
916  throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
917  }
918  string val = render_const_value(out, name, field_type, v_iter->second);
919  indent(out) << name << "." << v_iter->first->get_string() << " = " << val << ";" << endl;
920  indent(out) << name << ".__isset." << v_iter->first->get_string() << " = true;" << endl;
921  }
922  out << endl;
923  } else if (type->is_map()) {
924  t_type* ktype = ((t_map*)type)->get_key_type();
925  t_type* vtype = ((t_map*)type)->get_val_type();
926  const map<t_const_value*, t_const_value*>& val = value->get_map();
927  map<t_const_value*, t_const_value*>::const_iterator v_iter;
928  for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
929  string key = render_const_value(out, name, ktype, v_iter->first);
930  string val = render_const_value(out, name, vtype, v_iter->second);
931  indent(out) << name << ".insert(std::make_pair(" << key << ", " << val << "));" << endl;
932  }
933  out << endl;
934  } else if (type->is_list()) {
935  t_type* etype = ((t_list*)type)->get_elem_type();
936  const vector<t_const_value*>& val = value->get_list();
937  vector<t_const_value*>::const_iterator v_iter;
938  for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
939  string val = render_const_value(out, name, etype, *v_iter);
940  indent(out) << name << ".push_back(" << val << ");" << endl;
941  }
942  out << endl;
943  } else if (type->is_set()) {
944  t_type* etype = ((t_set*)type)->get_elem_type();
945  const vector<t_const_value*>& val = value->get_list();
946  vector<t_const_value*>::const_iterator v_iter;
947  for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
948  string val = render_const_value(out, name, etype, *v_iter);
949  indent(out) << name << ".insert(" << val << ");" << endl;
950  }
951  out << endl;
952  } else {
953  throw "INVALID TYPE IN print_const_value: " + type->get_name();
954  }
955 }
956 
960 string t_cpp_generator::render_const_value(ofstream& out, string name, t_type* type, t_const_value* value) {
961  (void) name;
962  std::ostringstream render;
963 
964  if (type->is_base_type()) {
965  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
966  switch (tbase) {
968 #ifdef SANDESH
969  case t_base_type::TYPE_STATIC_CONST_STRING:
970  case t_base_type::TYPE_XML:
971 #endif
972  render << '"' << get_escaped_string(value) << '"';
973  break;
975  render << ((value->get_integer() > 0) ? "true" : "false");
976  break;
980 #ifdef SANDESH
981  case t_base_type::TYPE_U16:
982  case t_base_type::TYPE_U32:
983 #endif
984  render << value->get_integer();
985  break;
987  render << value->get_integer() << "LL";
988  break;
989 #ifdef SANDESH
990  case t_base_type::TYPE_U64:
991  render << value->get_integer() << "ULL";
992  break;
993  case t_base_type::TYPE_UUID:
994  render << "boost::uuids::string_generator()(\"" << value->get_uuid() << "\")";
995  break;
996 #endif
998  if (value->get_type() == t_const_value::CV_INTEGER) {
999  render << value->get_integer();
1000  } else {
1001  render << value->get_double();
1002  }
1003  break;
1004 #ifdef SANDESH
1005  case t_base_type::TYPE_IPV4:
1006  render << value->get_integer();
1007  break;
1008  case t_base_type::TYPE_IPADDR:
1009  render << "boost::asio::ip::address::from_string(\"" <<
1010  value->get_string() << "\")";
1011  break;
1012 #endif
1013  default:
1014  throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
1015  }
1016  } else if (type->is_enum()) {
1017  render << "(" << type_name(type) << ")" << value->get_integer();
1018  } else {
1019  string t = tmp("tmp");
1020  indent(out) << type_name(type) << " " << t << ";" << endl;
1021  print_const_value(out, t, type, value);
1022  render << t;
1023  }
1024 
1025  return render.str();
1026 }
1027 
1035 void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) {
1036  generate_struct_definition(f_types_, tstruct, is_exception);
1037  generate_struct_fingerprint(f_types_impl_, tstruct, true);
1038  generate_local_reflection(f_types_, tstruct, false);
1039  generate_local_reflection(f_types_impl_, tstruct, true);
1040  generate_local_reflection_pointer(f_types_impl_, tstruct);
1041 #ifdef SANDESH
1042  generate_static_const_string_definition(f_types_impl_, tstruct);
1043 #endif
1044 
1045  std::ofstream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_);
1046  generate_struct_reader(out, tstruct);
1047  generate_struct_writer(out, tstruct);
1048 #ifdef SANDESH
1049  generate_struct_logger(out, tstruct->get_name(), tstruct->get_members());
1050  generate_struct_get_size(out, tstruct->get_name(), tstruct->get_members());
1051 #endif
1052 }
1053 
1054 #ifdef SANDESH
1055 
1062 void t_cpp_generator::generate_cpp_sandesh(t_sandesh* tsandesh) {
1063  bool is_request =
1064  ((t_base_type *)tsandesh->get_type())->is_sandesh_request();
1065  bool is_trace =
1066  ((t_base_type *)tsandesh->get_type())->is_sandesh_trace() ||
1067  ((t_base_type *)tsandesh->get_type())->is_sandesh_trace_object();
1068  bool is_uve =
1069  ((t_base_type *)tsandesh->get_type())->is_sandesh_uve();
1070  bool is_alarm =
1071  ((t_base_type *)tsandesh->get_type())->is_sandesh_alarm();
1072  bool is_system =
1073  ((t_base_type *)tsandesh->get_type())->is_sandesh_system();
1074 
1075  generate_sandesh_definition(f_types_, tsandesh);
1076  generate_sandesh_fingerprint(f_types_impl_, tsandesh, true);
1077  std::ofstream& out = f_types_impl_;
1078  generate_static_const_string_definition(out, tsandesh);
1079  generate_sandesh_static_versionsig_def(out, tsandesh);
1080  generate_sandesh_creator(out, tsandesh);
1081  generate_sandesh_reader(out, tsandesh);
1082  generate_sandesh_writer(out, tsandesh);
1083  generate_sandesh_loggers(out, tsandesh);
1084  generate_sandesh_get_size(out, tsandesh);
1085 
1086  if (!is_trace) {
1087  generate_sandesh_static_seqnum_def(out, tsandesh);
1088  }
1089  if (is_request) {
1090  generate_sandesh_http_reader(out, tsandesh);
1091  // Generate a skeleton impl file
1092  generate_sandesh_request(f_request_impl_, tsandesh);
1093  }
1094  if (is_uve || is_alarm) {
1095  generate_sandesh_updater(out,tsandesh);
1096  }
1097  if (is_system) {
1098  generate_sandesh_static_rate_limit_log_def(out, tsandesh);
1099  generate_sandesh_static_rate_limit_mutex_def(out, tsandesh);
1100  generate_sandesh_static_rate_limit_buffer_def(out, tsandesh);
1101  }
1102 
1103 }
1104 
1111 void t_cpp_generator::generate_sandesh_request(ofstream& out,
1112  t_sandesh* tsandesh) {
1113  out << "void " << tsandesh->get_name() << "::" <<
1114  "HandleRequest() const {" << endl;
1115  indent_up();
1116 
1117  indent(out) << "// This autogenerated skeleton file illustrates the " <<
1118  "function needed to" << endl;
1119  indent(out) << "// implement " << tsandesh->get_name() << "." << endl;
1120  indent(out) << "// You should copy it to another filename to avoid " <<
1121  "overwriting it. Add the" << endl;
1122  indent(out) << "// HandleRequest() implementation to it, and include it " <<
1123  "in your module's" << endl;
1124  indent(out) << "// SConscript. Alternatively, add the implementation of " <<
1125  "HandleRequest()" << endl;
1126  indent(out) << "// in your module's sources." << endl;
1127  scope_down(out);
1128 }
1129 
1136 std::string t_cpp_generator::generate_sandesh_no_static_const_string_function(
1137  t_sandesh* tsandesh, bool signature, bool autogen_darg,
1138  bool trace, bool request, bool ctorcall) {
1139  string result = "";
1140 
1141  // Get members
1142  vector<t_field*>::const_iterator m_iter;
1143  const vector<t_field*>& members = tsandesh->get_members();
1144 
1145  bool init_function = false;
1146 
1147  if (trace) {
1148  result += "(";
1149  init_function = true;
1150  if (signature) {
1151  result += "SandeshTraceBufferPtr trace_buf, std::string file, int32_t line";
1152  } else {
1153  result += "trace_buf, file, line";
1154  }
1155  } else {
1156  if (signature) {
1157  if (!ctorcall) {
1158  result += "(";
1159  init_function = true;
1160  result += "uint32_t seqno";
1161  }
1162  } else {
1163  result += "(";
1164  init_function = true;
1165  if (ctorcall)
1166  result += "0";
1167  else
1168  result += "lseqnum_++";
1169  }
1170  }
1171 
1172  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1173  t_type* t = get_true_type((*m_iter)->get_type());
1174  if (t->is_static_const_string()) {
1175  continue;
1176  }
1177  if ((*m_iter)->get_auto_generated() && trace) {
1178  continue;
1179  }
1180  if (((t_base_type *)tsandesh->get_type())->is_sandesh_object() &&
1181  ((*m_iter)->get_req() == t_field::T_OPTIONAL)) {
1182  continue;
1183  }
1184  if (!init_function) {
1185  result += "(";
1186  init_function = true;
1187  } else {
1188  result += ", ";
1189  }
1190 
1191  if (signature) {
1192  // Special handling for auto-generated members
1193  if (autogen_darg && (*m_iter)->get_auto_generated()) {
1194  result += declare_field(*m_iter, true, false, false, false, true);
1195  } else {
1196  bool use_const = !(t->is_base_type() || t->is_enum()) || t->is_string();
1197  result += declare_field(*m_iter, false, false, use_const, !t->is_base_type() || t->is_string(), true);
1198  }
1199  } else {
1200  result += (*m_iter)->get_name();
1201  }
1202  }
1203  if (!init_function) {
1204  result += "(";
1205  }
1206 
1207  if (request) {
1208  if (signature) {
1209  if (init_function) {
1210  result += ", ";
1211  }
1212  result += "const std::string& context, SandeshConnection * sconn = NULL";
1213  } else {
1214  if (init_function) {
1215  result += ", ";
1216  }
1217  result += "context, sconn";
1218  }
1219  }
1220 
1221  result += ")";
1222  return result;
1223 }
1224 
1225 std::string t_cpp_generator::generate_sandesh_async_creator(t_sandesh* tsandesh, bool signature,
1226  bool expand_autogen, bool skip_autogen, std::string prefix, std::string suffix,
1227  bool category_level_file_line_first, bool autogen_category_level, bool
1228  drop_log_reason, bool use_sandesh_object)
1229  {
1230  string result = "";
1231  string temp = "";
1232  string category_def = prefix + "category" + suffix;
1233  string level_def = prefix + "level" + suffix;
1234  string category_dec = "std::string " + category_def;
1235  string level_dec = "SandeshLevel::type " + level_def;
1236  string module_name = "\"\"";
1237  string drop_reason_dec;
1238  string drop_reason_def;
1239  bool is_flow = ((t_base_type *)tsandesh->get_type())->is_sandesh_flow();
1240  // Get members
1241  vector<t_field*>::const_iterator m_iter;
1242  const vector<t_field*>& members = tsandesh->get_members();
1243  bool init_function = false;
1244  if (drop_log_reason) {
1245  drop_reason_def = prefix + "drop_reason" + suffix + ", ";
1246  drop_reason_dec = "const std::string& " + drop_reason_def;
1247  }
1248 
1249  if (category_level_file_line_first) {
1250  if (signature) {
1251  result += "(" + drop_reason_dec + category_dec + ", " + level_dec;
1252  if (!is_flow) result += ", std::string file, int32_t line";
1253  } else {
1254  if (!autogen_category_level) {
1255  result += "(" + drop_reason_dec + category_def + ", " + level_def;
1256  if (!is_flow) result += ", __FILE__, __LINE__";
1257  } else {
1258  result += "(" + drop_reason_dec + module_name + ", SandeshLevel::SYS_INFO";
1259  if (!is_flow) result += ", __FILE__, __LINE__";
1260  }
1261  }
1262  init_function = true;
1263  } else {
1264  if (signature) {
1265  if (!autogen_category_level) {
1266  result += "(" + drop_reason_dec + category_dec + ", " + level_dec;
1267  init_function = true;
1268  }
1269  } else {
1270  if (!autogen_category_level) {
1271  result += "(" + drop_reason_def + category_def + ", " + level_def;
1272  init_function = true;
1273  }
1274  }
1275  }
1276  if(use_sandesh_object) {
1277  if (!init_function) {
1278  result += "(snh";
1279  init_function = true;
1280  } else {
1281  if(signature) {
1282  result += ", " + tsandesh->get_name() + " *snh";
1283  } else {
1284  result += ", snh";
1285  }
1286  }
1287  } else {
1288  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1289  temp = "";
1290  t_type* t = get_true_type((*m_iter)->get_type());
1291  if (t->is_static_const_string()) {
1292  continue;
1293  }
1294  bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
1295  if(is_optional) {
1296  continue;
1297  }
1298  bool skip = (*m_iter)->get_auto_generated() &&
1299  ((*m_iter)->get_name() == "file" || (*m_iter)->get_name() == "line") &&
1300  category_level_file_line_first;
1301  if (!init_function) {
1302  result += "(";
1303  init_function = true;
1304  } else {
1305  if (!skip) {
1306  temp += ", ";
1307  }
1308  }
1309  if (signature) {
1310  result += temp;
1311  // Special signature processing for autogen members
1312  if ((*m_iter)->get_auto_generated()) {
1313  if (!skip) {
1314  result += declare_field(*m_iter, true, false, false, !t->is_base_type(), true);
1315  }
1316  } else {
1317  bool use_const = !(t->is_base_type() || t->is_enum()) || t->is_string();
1318  result += declare_field(*m_iter, false, false, use_const,
1319  !t->is_base_type() || t->is_string(), true);
1320  }
1321  } else {
1322  if (skip) {
1323  continue;
1324  }
1325  // Special processing for autogen members
1326  if ((*m_iter)->get_auto_generated()) {
1327  // Skip
1328  if (skip_autogen) {
1329  continue;
1330  }
1331  // Map to preprocessor macros
1332  if (expand_autogen) {
1333  if ((*m_iter)->get_name() == "file") {
1334  result += temp;
1335  result += "__FILE__";
1336  } else if ((*m_iter)->get_name() == "line") {
1337  result += temp;
1338  result += "__LINE__";
1339  }
1340  } else {
1341  result += temp;
1342  result += prefix + (*m_iter)->get_name() + suffix;
1343  }
1344  } else {
1345  result += temp;
1346  result += prefix + (*m_iter)->get_name() + suffix;
1347  }
1348  }
1349  }
1350  }
1351  if (!init_function) {
1352  result += "(";
1353  }
1354  result += ")";
1355  return result;
1356 }
1357 
1358 void t_cpp_generator::generate_sandesh_async_create_fn(ofstream &out,
1359  t_sandesh *tsandesh) {
1360  std::string creator_func_name = "Create";
1361  out << indent() << "static " << tsandesh->get_name() << "* "
1362  << creator_func_name << "(std::string file = \"\", int32_t line = 0) {"
1363  << endl;
1364  indent_up();
1365  out << indent() << tsandesh->get_name() <<
1366  " * snh = new " << tsandesh->get_name() << "(lseqnum_++, file, line);"
1367  << endl;
1368  out << indent() << "return snh;" << endl;
1369  indent_down();
1370  indent(out) << "}" << endl << endl;
1371 }
1372 
1373 void t_cpp_generator::generate_sandesh_async_create_macro(ofstream &out,
1374  t_sandesh *tsandesh) {
1375  std::string creator_func_name = "Create";
1376  // Generate creator macro
1377  string creator_name = tsandesh->get_name() + creator_func_name;
1378  string creator_name_usc = underscore(creator_name);
1379  string creator_name_uc = uppercase(creator_name_usc);
1380  out << indent() << "#define " << creator_name_uc <<
1381  "() \\" << endl;
1382  indent_up();
1383  out << indent() << tsandesh->get_name() << "::" << creator_func_name <<
1384  "(__FILE__, __LINE__)" << endl;
1385  indent_down();
1386  indent(out) << endl << endl;
1387 }
1388 
1389 void t_cpp_generator::generate_sandesh_async_send_fn(
1390  ofstream &out, t_sandesh *tsandesh, bool generate_sandesh_object,
1391  bool generate_rate_limit, bool generate_system_log) {
1392  std::string sender_func_name = "Send";
1393  // Generate sender
1394  out << indent() << "static void " << sender_func_name;
1395  out << generate_sandesh_async_creator(tsandesh, true, false, false, "", "",
1396  true, false, false, generate_sandesh_object);
1397  out << " {" << endl;
1398  indent_up();
1399  if (generate_sandesh_object) {
1400  out << indent() << "snh->set_level(level);" << endl;
1401  out << indent() << "snh->set_category(category);" << endl;
1402  }
1403  out << indent() << "if (HandleTest(level, category)) {" << endl;
1404  indent_up();
1405  out << indent() << "Log";
1406  if (generate_sandesh_object) {
1407  out << "(category, level, snh);" << endl;
1408  out << indent() << "snh->Release();" << endl;
1409  } else {
1410  out << generate_sandesh_async_creator(tsandesh, false, false, false, "",
1411  "", false, false, false) << "; " << endl;
1412  }
1413  out << indent() << "return;" << endl;
1414  scope_down(out);
1415  if (generate_system_log) {
1416  out << indent() << "if (IsSendingAllMessagesDisabled() || " <<
1417  "IsSendingSystemLogsDisabled()) {" << endl;
1418  } else {
1419  out << indent() << "if (IsSendingAllMessagesDisabled() || " <<
1420  "IsSendingObjectLogsDisabled()) {" << endl;
1421  }
1422  indent_up();
1423  out << indent() << "UpdateTxMsgFailStats(\"" << tsandesh->get_name() <<
1424  "\", 0, SandeshTxDropReason::SendingDisabled);" << endl;
1425  out << indent() << "Log";
1426  if (generate_sandesh_object) {
1427  out << "(category, level, snh);" << endl;
1428  out << indent() << "snh->Release();" << endl;
1429  } else {
1430  out << generate_sandesh_async_creator(tsandesh, false, false, false, "",
1431  "", false, false, false) << "; " << endl;
1432  }
1433  out << indent() << "return;" << endl;
1434  scope_down(out);
1435  if (generate_rate_limit) {
1436  out << indent() << "if (!IsRatelimitPass()) {" << endl;
1437  indent_up();
1438  out << indent() << "UpdateTxMsgFailStats(\"" << tsandesh->get_name() <<
1439  "\", 0, SandeshTxDropReason::RatelimitDrop);" << endl;
1440  out << indent() << "if (do_rate_limit_drop_log_) {" << endl;
1441  indent_up();
1442  out << indent() << "std::stringstream ratelimit_val;" << endl;
1443  out << indent() << " ratelimit_val << Sandesh::get_send_rate_limit();"
1444  << endl;
1445  out << indent() << "std::string drop_reason = \"SANDESH: Ratelimit"
1446  " Drop (\" + ratelimit_val.str() + std::string(\" messages"
1447  "/second): \") ;" << endl;
1448  out << indent() << "DropLog";
1449  if (generate_sandesh_object) {
1450  out << "(drop_reason, category, level, snh);" << endl;
1451  out << indent() << "snh->Release();" << endl;
1452  } else {
1453  out << generate_sandesh_async_creator(tsandesh, false, false,
1454  false, "", "", false, false, true) << "; " << endl;
1455  }
1456  out << indent() << "do_rate_limit_drop_log_ = false;" << endl;
1457  scope_down(out);
1458  out << indent() << "return;" << endl;
1459  scope_down(out);
1460  }
1461  out << indent() << "if (level >= SendingLevel()) {" << endl;
1462  indent_up();
1463  out << indent() << "UpdateTxMsgFailStats(\"" << tsandesh->get_name() <<
1464  "\", 0, SandeshTxDropReason::QueueLevel);" << endl;
1465  out << indent() << "std::string drop_reason = \"SANDESH: Queue Drop:"
1466  " \";" << endl;
1467  out << indent() << "DropLog";
1468  if (generate_sandesh_object) {
1469  out << "(drop_reason, category, level, snh);" << endl;
1470  out << indent() << "snh->Release();" << endl;
1471  } else {
1472  out << generate_sandesh_async_creator(tsandesh, false, false, false, "",
1473  "", false, false, true) << "; " << endl;
1474  }
1475  out << indent() << "return;" << endl;
1476  scope_down(out);
1477  if (!generate_sandesh_object) {
1478  out << indent() << tsandesh->get_name() <<
1479  " * snh = new " << tsandesh->get_name() <<
1480  generate_sandesh_no_static_const_string_function(tsandesh,
1481  false, false, false, false) << ";" << endl;
1482  out << indent() << "snh->set_level(level);" << endl;
1483  out << indent() << "snh->set_category(category);" << endl;
1484  }
1485  out << indent() << "snh->Dispatch();" << endl;
1486  indent_down();
1487  indent(out) << "}" << endl << endl;
1488 }
1489 
1490 void t_cpp_generator::generate_sandesh_async_send_macros(ofstream &out,
1491  t_sandesh *tsandesh, bool generate_sandesh_object) {
1492  std::string sender_func_name = "Send";
1493  std::string logger_func_name = "Log";
1494  // Generate creator macro
1495  string creator_name = tsandesh->get_name() + logger_func_name;
1496  if (generate_sandesh_object) {
1497  creator_name += "Sandesh";
1498  }
1499  string creator_name_usc = underscore(creator_name);
1500  string creator_name_uc = uppercase(creator_name_usc);
1501  out << indent() << "#define " << creator_name_uc;
1502  out << generate_sandesh_async_creator(tsandesh, false, false, true, "_",
1503  "", false, false, false, generate_sandesh_object);
1504  out << "\\" << endl;
1505  indent_up();
1506  out << indent() << tsandesh->get_name() << "::" << sender_func_name;
1507  out << generate_sandesh_async_creator(tsandesh, false, true, false,
1508  "(_", ")", true, false, false, generate_sandesh_object) << endl;
1509  indent_down();
1510  indent(out) << endl << endl;
1511 
1512  // Generate creator macro (legacy)
1513  creator_name = tsandesh->get_name() + sender_func_name;
1514  if (generate_sandesh_object) {
1515  creator_name += "Sandesh";
1516  }
1517  creator_name_usc = underscore(creator_name);
1518  creator_name_uc = uppercase(creator_name_usc);
1519  out << indent() << "#define " << creator_name_uc;
1520  out << generate_sandesh_async_creator(tsandesh, false, false, true, "_",
1521  "", false, true, false, generate_sandesh_object);
1522  out << "\\" << endl;
1523  indent_up();
1524  out << indent() << tsandesh->get_name() << "::" << sender_func_name;
1525  out << generate_sandesh_async_creator(tsandesh, false, true, false,
1526  "(_", ")", true, true, false, generate_sandesh_object) << endl;
1527  indent_down();
1528  indent(out) << endl << endl;
1529 }
1530 
1531 void t_cpp_generator::generate_sandesh_rate_limit_fn(ofstream &out,
1532  t_sandesh *tsandesh) {
1533  out << indent() << "static bool IsRatelimitPass() {" << endl;
1534  indent_up();
1535  generate_isRatelimitPass(out, tsandesh);
1536  indent_down();
1537  indent(out) << "}" << endl << endl;
1538 }
1539 
1540 void t_cpp_generator::generate_sandesh_systemlog_creators(ofstream &out,
1541  t_sandesh *tsandesh) {
1542  bool generate_sandesh_object = false;
1543  bool generate_rate_limit = true;
1544  bool generate_system_log = true;
1545  // Generate send function and macros
1546  generate_sandesh_async_send_fn(out, tsandesh, generate_sandesh_object,
1547  generate_rate_limit, generate_system_log);
1548  generate_sandesh_async_send_macros(out, tsandesh, generate_sandesh_object);
1549  // Generate DropLog
1550  generate_sandesh_static_drop_logger(out, tsandesh,
1551  generate_sandesh_object);
1552  // Generate Log
1553  generate_sandesh_static_logger(out, tsandesh, generate_sandesh_object);
1554  // Generate rate limit
1555  generate_sandesh_rate_limit_fn(out, tsandesh);
1556 }
1557 
1558 void t_cpp_generator::generate_sandesh_objectlog_creators(ofstream &out,
1559  t_sandesh *tsandesh) {
1560  // First generate without sandesh object semantics
1561  bool generate_sandesh_object = false;
1562  bool generate_rate_limit = false;
1563  bool generate_system_log = false;
1564  // Generate send function and macros
1565  generate_sandesh_async_send_fn(out, tsandesh, generate_sandesh_object,
1566  generate_rate_limit, generate_system_log);
1567  generate_sandesh_async_send_macros(out, tsandesh, generate_sandesh_object);
1568  // Generate DropLog
1569  generate_sandesh_static_drop_logger(out, tsandesh,
1570  generate_sandesh_object);
1571  // Generate Log
1572  generate_sandesh_static_logger(out, tsandesh, generate_sandesh_object);
1573  // Next generate with sandesh object semantics
1574  generate_sandesh_object = true;
1575  // Generate create function and macros
1576  generate_sandesh_async_create_fn(out, tsandesh);
1577  generate_sandesh_async_create_macro(out, tsandesh);
1578  // Generate send function and macros
1579  generate_sandesh_async_send_fn(out, tsandesh, generate_sandesh_object,
1580  generate_rate_limit, generate_system_log);
1581  generate_sandesh_async_send_macros(out, tsandesh, generate_sandesh_object);
1582  // Generate DropLog
1583  generate_sandesh_static_drop_logger(out, tsandesh,
1584  generate_sandesh_object);
1585  // Generate Log
1586  generate_sandesh_static_logger(out, tsandesh, generate_sandesh_object);
1587 }
1588 
1589 void t_cpp_generator::generate_sandesh_session_log_unrolled_fn(ofstream &out,
1590  t_sandesh *tsandesh) {
1591  //To be removed
1592  out << indent() << "static void LogUnrolled";
1593  out << generate_sandesh_async_creator(tsandesh, true, false, false, "", "",
1594  true, false, false, false);
1595  out << ";" << endl;
1596 }
1597 
1598 void t_cpp_generator::generate_sandesh_session_adjust_session_end_point_objects_fn(ofstream &out,
1599  t_sandesh *tsandesh) {
1600  out << "static void adjust_session_end_point_objects(std::vector"
1601  " <SessionEndpoint> & session_data);" << endl;
1602  out << endl;
1603 }
1604 
1605 void t_cpp_generator::generate_sandesh_flow_send_fn(ofstream &out,
1606  t_sandesh *tsandesh) {
1607  std::string sender_func_name = "Send";
1608  std::string logger_func_name = "Log";
1609  // Generate sender
1610  out << indent() << "static void " << sender_func_name;
1611  out << generate_sandesh_async_creator(tsandesh, true, false, false, "", "",
1612  true, false, false, false);
1613  out << " {" << endl;
1614  indent_up();
1615  out << indent() << "if (HandleTest(level, category)) {" << endl;
1616  indent_up();
1617  out << indent() << "return;" << endl;
1618  scope_down(out);
1619  out << indent() << "if (IsSendingAllMessagesDisabled() ||" <<
1620  " IsSendingFlowsDisabled()) {" << endl;
1621  indent_up();
1622  out << indent() << "UpdateTxMsgFailStats(\"" << tsandesh->get_name() <<
1623  "\", 0, SandeshTxDropReason::SendingDisabled);" << endl;
1624  out << indent() << "if (IsLoggingDroppedAllowed(SandeshType::FLOW))" <<
1625  " {" << endl;
1626  indent_up();
1627  out << indent() << "Log" <<
1628  generate_sandesh_async_creator(tsandesh, false,
1629  false, false, "", "", false, false, false) << ";" << endl;
1630  scope_down(out);
1631  out << indent() << "return;" << endl;
1632  scope_down(out);
1633 
1634  out << indent() <<
1635  "if (is_send_slo_to_logger_enabled() || is_send_sampled_to_logger_enabled()) { " <<
1636  endl;
1637  indent_up();
1638  const t_type *t = tsandesh->get_type();
1639  if (((t_base_type *)t)->is_sandesh_session()) {
1640  out << indent() << "LogUnrolled(category, level, session_data);" << endl;
1641  }
1642  scope_down(out);
1643  out << indent() << "if (level >= SendingLevel()) {" << endl;
1644  indent_up();
1645  out << indent() << "UpdateTxMsgFailStats(\"" << tsandesh->get_name() <<
1646  "\", 0, SandeshTxDropReason::QueueLevel);" << endl;
1647  out << indent() << "if (IsLoggingDroppedAllowed(SandeshType::FLOW))" <<
1648  " {" << endl;
1649  indent_up();
1650  out << indent() << "std::string drop_reason = \"SANDESH: Queue Drop:"
1651  " \";" << endl;
1652  out << indent() << "DropLog" <<
1653  generate_sandesh_async_creator(tsandesh, false,
1654  false, false, "", "", false, false, true) << ";" << endl;
1655  scope_down(out);
1656  out << indent() << "return;" << endl;
1657  scope_down(out);
1658  out << indent() << tsandesh->get_name() <<
1659  " * snh = new " << tsandesh->get_name() <<
1660  generate_sandesh_no_static_const_string_function(tsandesh,
1661  false, false, false, false) << ";" << endl;
1662  if (((t_base_type *)t)->is_sandesh_session()) {
1663  out << indent() << "if (!is_send_sampled_to_collector_enabled() && !is_send_slo_to_collector_enabled()) {" << endl;
1664  indent_up();
1665  out << indent() << "return;" << endl;
1666  scope_down(out);
1667  out << indent() << " if (is_send_sampled_to_collector_enabled() != is_send_slo_to_collector_enabled()) {" << endl;
1668  indent_up();
1669  out << indent() << "adjust_session_end_point_objects(snh->session_data);";
1670  scope_down(out);
1671  }
1672  out << endl;
1673  out << indent() << "snh->set_level(level);" << endl;
1674  out << indent() << "snh->set_category(category);" << endl;
1675  out << indent() << "snh->Dispatch();" << endl;
1676  indent_down();
1677  indent(out) << "}" << endl << endl;
1678 }
1679 
1680 void t_cpp_generator::generate_sandesh_flow_creators(ofstream &out,
1681  t_sandesh *tsandesh) {
1682  bool generate_sandesh_object = false;
1683  const t_type *t = tsandesh->get_type();
1684  // Generate LogUnrolled declaration only for Session message
1685  if (((t_base_type *)t)->is_sandesh_session()) {
1686  generate_sandesh_session_log_unrolled_fn(out, tsandesh);
1687  generate_sandesh_session_adjust_session_end_point_objects_fn(out, tsandesh);
1688  }
1689  // Generate send function and macros
1690  generate_sandesh_flow_send_fn(out, tsandesh);
1691  generate_sandesh_async_send_macros(out, tsandesh, generate_sandesh_object);
1692  // Generate DropLog
1693  generate_sandesh_static_drop_logger(out, tsandesh,
1694  generate_sandesh_object);
1695  // Generate Log
1696  generate_sandesh_static_logger(out, tsandesh, generate_sandesh_object);
1697 }
1698 
1699 std::string t_cpp_generator::generate_sandesh_trace_creator(t_sandesh *tsandesh,
1700  bool signature, bool expand_autogen, bool skip_autogen,
1701  std::string prefix, std::string suffix) {
1702  string result = "";
1703  string temp = "";
1704  // Get members
1705  vector<t_field*>::const_iterator m_iter;
1706  const vector<t_field*>& members = tsandesh->get_members();
1707 
1708  result += "(";
1709  if (signature) {
1710  result += "SandeshTraceBufferPtr tracebuf";
1711  if (!skip_autogen) {
1712  result += ", std::string file, int32_t line";
1713  }
1714  } else {
1715  result += prefix + "trace_buf" + suffix;
1716  if (!skip_autogen) {
1717  if (expand_autogen) {
1718  result += ", __FILE__, __LINE__";
1719  } else {
1720  result += ", " + prefix + "file" + suffix + ", " +
1721  prefix + "line" + suffix;
1722  }
1723  }
1724  }
1725 
1726  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1727  temp = "";
1728  t_type* t = get_true_type((*m_iter)->get_type());
1729  if (t->is_static_const_string()) {
1730  continue;
1731  }
1732  if ((*m_iter)->get_auto_generated()) {
1733  continue;
1734  }
1735  temp += ", ";
1736  if (signature) {
1737  result += temp;
1738  bool use_const = !(t->is_base_type() || t->is_enum()) || t->is_string();
1739  result += declare_field(*m_iter, false, false, use_const,
1740  !t->is_base_type() || t->is_string(), true);
1741  } else {
1742  result += temp;
1743  result += prefix + (*m_iter)->get_name() + suffix;
1744  }
1745  }
1746  result += ")";
1747  return result;
1748 }
1749 
1757 void t_cpp_generator::generate_sandesh_member_init_list(ofstream& out,
1758  t_sandesh *tsandesh, bool init_dval) {
1759  // Get members
1760  vector<t_field*>::const_iterator m_iter;
1761  const vector<t_field*>& members = tsandesh->get_members();
1762 
1763  out << " : ";
1764  generate_sandesh_base_init(out, tsandesh, init_dval);
1765 
1766  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1767  t_type* t = get_true_type((*m_iter)->get_type());
1768  // If initializing with default values ignore complex types
1769  if (init_dval && (!t->is_base_type() && !t->is_enum())) {
1770  continue;
1771  }
1772  if (t->is_static_const_string()) {
1773  continue;
1774  }
1775  if (((t_base_type *)tsandesh->get_type())->is_sandesh_object() &&
1776  ((*m_iter)->get_req() == t_field::T_OPTIONAL)) {
1777  continue;
1778  }
1779  string dval;
1780  if (t->is_enum()) {
1781  dval += "(" + type_name(t) + ")";
1782  }
1783  if (t->is_string() || t->is_xml()) {
1784  dval += "\"\"";
1785  } else if (t->is_uuid()) {
1786  dval += "boost::uuids::nil_uuid()";
1787  } else if (t->is_ipaddr()) {
1788  dval += "";
1789  } else {
1790  dval += "0";
1791  }
1792  t_const_value* cv = (*m_iter)->get_value();
1793  if (cv != NULL) {
1794  dval = render_const_value(out, (*m_iter)->get_name(), t, cv);
1795  } else {
1796  if (!init_dval) {
1797  dval = (*m_iter)->get_name();
1798  }
1799  }
1800  out << ", " << (*m_iter)->get_name() << "(" << dval << ")";
1801  }
1802 
1803 }
1804 
1811 void t_cpp_generator::generate_sandesh_seqnum(ofstream& out,
1812  t_sandesh* tsandesh) {
1813  if (((t_base_type *)tsandesh->get_type())->is_sandesh_uve() ||
1814  ((t_base_type *)tsandesh->get_type())->is_sandesh_alarm()) {
1815  indent(out) << "static tbb::atomic<uint32_t> lseqnum_;" << endl;
1816  } else {
1817  indent(out) << "static uint32_t lseqnum_;" << endl;
1818  }
1819 }
1820 
1821 
1822 string generate_sandesh_base_name(t_sandesh* tsandesh, bool type) {
1823  const t_type *t = tsandesh->get_type();
1824  if (((t_base_type *)t)->is_sandesh_request()) {
1825  if (type) {
1826  return "SandeshType::REQUEST";
1827  } else {
1828  return "SandeshRequest";
1829  }
1830  } else if (((t_base_type *)t)->is_sandesh_response()) {
1831  if (type) {
1832  return "SandeshType::RESPONSE";
1833  } else {
1834  return "SandeshResponse";
1835  }
1836  } else if (((t_base_type *)t)->is_sandesh_uve()) {
1837  if (type) {
1838  return "SandeshType::UVE";
1839  } else {
1840  return "SandeshUVE";
1841  }
1842  } else if (((t_base_type *)t)->is_sandesh_alarm()) {
1843  if (type) {
1844  return "SandeshType::ALARM";
1845  } else {
1846  return "SandeshAlarm";
1847  }
1848  } else if (((t_base_type *)t)->is_sandesh_system()) {
1849  if (type) {
1850  return "SandeshType::SYSTEM";
1851  } else {
1852  return "SandeshSystem";
1853  }
1854  } else if (((t_base_type *)t)->is_sandesh_buffer()) {
1855  if (type) {
1856  return "SandeshType::BUFFER";
1857  } else {
1858  return "SandeshBuffer";
1859  }
1860  } else if (((t_base_type *)t)->is_sandesh_trace() ||
1861  ((t_base_type *)t)->is_sandesh_trace_object()) {
1862  if (type) {
1863  return "SandeshType::TRACE";
1864  } else {
1865  return "SandeshTrace";
1866  }
1867  } else if (((t_base_type *)t)->is_sandesh_object()) {
1868  if (type) {
1869  return "SandeshType::OBJECT";
1870  } else {
1871  return "SandeshObject";
1872  }
1873  } else if (((t_base_type *)t)->is_sandesh_flow()) {
1874  if (((t_base_type *)t)->is_sandesh_session()) {
1875  if (type) {
1876  return "SandeshType::SESSION";
1877  } else {
1878  return "SandeshFlowSession";
1879  }
1880  }
1881  else {
1882  if (type) {
1883  return "SandeshType::FLOW";
1884  } else {
1885  return "SandeshFlow";
1886  }
1887  }
1888  } else {
1889  return "";
1890  }
1891 }
1892 
1899 void t_cpp_generator::generate_sandesh_versionsig(ofstream& out,
1900  t_sandesh* tsandesh) {
1901  indent(out) << "static uint32_t versionsig_;" << endl;
1902 }
1903 
1904 void t_cpp_generator::generate_sandesh_base_init(
1905  ofstream& out, t_sandesh* tsandesh, bool init_dval) {
1906  out << generate_sandesh_base_name(tsandesh, false);
1907 
1908  if (init_dval) {
1909  out << "(\"" << tsandesh->get_name() << "\",lseqnum_++)";
1910  } else {
1911  out << "(\"" << tsandesh->get_name() << "\",seqno)";
1912  }
1913 }
1914 
1915 void t_cpp_generator::generate_sandesh_trace_seqnum_ctor(ofstream& out,
1916  t_sandesh* tsandesh) {
1917  indent(out) << "set_seqnum(0);" << endl;
1918 }
1919 
1926 void t_cpp_generator::generate_sandesh_context(ofstream& out,
1927  t_sandesh* tsandesh,
1928  string val) {
1929  indent(out) << "set_context(" << val << ");" << endl;
1930 }
1931 
1932 
1939 void t_cpp_generator::generate_sandesh_hints(ofstream& out,
1940  t_sandesh* tsandesh) {
1941  bool has_key_annotation = tsandesh->has_key_annotation();
1942  string shints = "0";
1943 
1944  if (has_key_annotation) {
1945  shints += " | g_sandesh_constants.SANDESH_KEY_HINT";
1946  }
1947  indent(out) << "set_hints(" << shints << ");" << endl;
1948 }
1949 
1956 void t_cpp_generator::generate_sandesh_default_ctor(ofstream& out,
1957  t_sandesh* tsandesh, bool is_request) {
1958  // Get members
1959  vector<t_field*>::const_iterator m_iter;
1960  const vector<t_field*>& members = tsandesh->get_members();
1961  // Generate default constructor
1962  indent(out) << tsandesh->get_name() << "()";
1963  generate_sandesh_member_init_list(out, tsandesh, true);
1964  out << " {" << endl;
1965  indent_up();
1966  // TODO(dreiss): When everything else in Thrift is perfect,
1967  // do more of these in the initializer list.
1968  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1969  t_type* t = get_true_type((*m_iter)->get_type());
1970  if (!t->is_base_type()) {
1971  t_const_value* cv = (*m_iter)->get_value();
1972  if (cv != NULL) {
1973  print_const_value(out, (*m_iter)->get_name(), t, cv);
1974  }
1975  }
1976  }
1977  generate_sandesh_hints(out, tsandesh);
1978  if (is_request) {
1979  generate_sandesh_context(out, tsandesh, "\"\"");
1980  }
1981  scope_down(out);
1982 }
1983 
1984 
1991 void t_cpp_generator::generate_sandesh_definition(ofstream& out,
1992  t_sandesh* tsandesh) {
1993  const t_type *t = tsandesh->get_type();
1994  assert(t->is_base_type());
1995  bool is_trace = ((t_base_type *)t)->is_sandesh_trace() ||
1996  ((t_base_type *)t)->is_sandesh_trace_object();
1997  bool is_request = ((t_base_type *)t)->is_sandesh_request();
1998  bool is_response = ((t_base_type *)t)->is_sandesh_response();
1999  bool is_uve = ((t_base_type *)t)->is_sandesh_uve();
2000  bool is_alarm = ((t_base_type *)t)->is_sandesh_alarm();
2001  bool is_buffer = ((t_base_type *)t)->is_sandesh_buffer();
2002  bool is_system = ((t_base_type *)t)->is_sandesh_system();
2003  bool is_object = ((t_base_type *)t)->is_sandesh_object();
2004  bool is_flow = ((t_base_type *)t)->is_sandesh_flow();
2005  bool is_session = ((t_base_type *)t)->is_sandesh_session();
2006  string extends;
2007  if (is_request) {
2008  extends = " : public SandeshRequest";
2009  } else if (is_response) {
2010  extends = " : public SandeshResponse";
2011  } else if (is_uve) {
2012  extends = " : public SandeshUVE";
2013  } else if (is_alarm) {
2014  extends = " : public SandeshAlarm";
2015  } else if (is_system) {
2016  extends = " : public SandeshSystem";
2017  } else if (is_buffer) {
2018  extends = " : public SandeshBuffer";
2019  } else if (is_trace) {
2020  extends = " : public SandeshTrace";
2021  } else if (is_object) {
2022  extends = " : public SandeshObject";
2023  } else if (is_flow) {
2024  if (is_session) {
2025  extends = " : public SandeshFlowSession";
2026  } else {
2027  extends = " : public SandeshFlow";
2028  }
2029  }
2030 
2031  // Get members
2032  vector<t_field*>::const_iterator m_iter;
2033  const vector<t_field*>& members = tsandesh->get_members();
2034 
2035  // Write the isset structure declaration outside the class. This makes
2036  // the generated code amenable to processing by SWIG.
2037  // We only declare the struct if it gets used in the class.
2038 
2039  // Isset struct has boolean fields, but only for non-required fields.
2040  bool has_nonrequired_fields = false;
2041  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2042  if ((*m_iter)->get_req() != t_field::T_REQUIRED)
2043  has_nonrequired_fields = true;
2044  }
2045 
2046  if (has_nonrequired_fields) {
2047 
2048  out <<
2049  indent() << "typedef struct _" << tsandesh->get_name() << "__isset {" << endl;
2050  indent_up();
2051 
2052  indent(out) <<
2053  "_" << tsandesh->get_name() << "__isset() ";
2054  bool first = true;
2055  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2056  if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
2057  continue;
2058  }
2059  if (first) {
2060  first = false;
2061  out <<
2062  ": " << (*m_iter)->get_name() << "(false)";
2063  } else {
2064  out <<
2065  ", " << (*m_iter)->get_name() << "(false)";
2066  }
2067  }
2068  out << " {}" << endl;
2069 
2070  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2071  if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
2072  indent(out) <<
2073  "bool " << (*m_iter)->get_name() << ";" << endl;
2074  }
2075  }
2076 
2077  indent_down();
2078  indent(out) <<
2079  "} _" << tsandesh->get_name() << "__isset;" << endl;
2080  }
2081 
2082  out << endl;
2083 
2084  // Open sandesh def
2085  out << indent() << "class " << tsandesh->get_name() << extends << " {" << endl;
2086 
2087  // Public members
2088  out << indent() << " public:" << endl;
2089  indent_up();
2090  generate_sandesh_fingerprint(out, tsandesh, false);
2091 
2092  // Create a getter and setter function for all fields except
2093  // static const string
2094  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2095  if (((*m_iter)->get_type())->is_static_const_string()) {
2096  continue;
2097  }
2098  out << endl << indent() <<
2099  "void set_" << (*m_iter)->get_name() <<
2100  "(" << type_name((*m_iter)->get_type(), false, true);
2101  out << " val) {" << endl << indent() <<
2102  indent() << (*m_iter)->get_name() << " = val;" << endl;
2103 
2104  // assume all fields are required except optional fields.
2105  // for optional fields change __isset.name to true
2106  bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
2107  if (is_optional) {
2108  out << indent() << indent() << "__isset." <<
2109  (*m_iter)->get_name() << " = true;" << endl;
2110  }
2111  out << indent() << "}" << endl;
2112 
2113  out << endl << indent() <<
2114  type_name((*m_iter)->get_type(), false, true)
2115  << " get_" << (*m_iter)->get_name() <<
2116  "() const {" << endl;
2117  out << indent() << indent() << "return " <<
2118  (*m_iter)->get_name() << ";" << endl;
2119  out << indent() << "}" << endl;
2120  }
2121  out << endl;
2122 
2123  // Generate an equality testing operator. Make it inline since the compiler
2124  // will do a better job than we would when deciding whether to inline it.
2125  out <<
2126  indent() << "bool operator == (const " << tsandesh->get_name() << " & " <<
2127  (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl;
2128  scope_up(out);
2129  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2130  // Most existing Thrift code does not use isset or optional/required,
2131  // so we treat "default" fields as required.
2132  if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
2133  out <<
2134  indent() << "if (!(" << (*m_iter)->get_name()
2135  << " == rhs." << (*m_iter)->get_name() << "))" << endl <<
2136  indent() << " return false;" << endl;
2137  } else {
2138  out <<
2139  indent() << "if (__isset." << (*m_iter)->get_name()
2140  << " != rhs.__isset." << (*m_iter)->get_name() << ")" << endl <<
2141  indent() << " return false;" << endl <<
2142  indent() << "else if (__isset." << (*m_iter)->get_name() << " && !("
2143  << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name()
2144  << "))" << endl <<
2145  indent() << " return false;" << endl;
2146  }
2147  }
2148  indent(out) << "return true;" << endl;
2149  scope_down(out);
2150  out <<
2151  indent() << "bool operator != (const " << tsandesh->get_name() << " &rhs) const {" << endl <<
2152  indent() << " return !(*this == rhs);" << endl <<
2153  indent() << "}" << endl << endl;
2154 
2155  // Destructor
2156  if (tsandesh->annotations_.find("final") == tsandesh->annotations_.end()) {
2157  out << endl << indent() << "virtual ~" <<
2158  tsandesh->get_name() << "() {}" << endl << endl;
2159  }
2160 
2161  // Add the __isset data member if we need it, using the definition from above
2162  if (has_nonrequired_fields) {
2163  out << endl << indent() << "_" << tsandesh->get_name() <<
2164  "__isset __isset;" << endl;
2165  }
2166 
2167  out << indent() << "virtual std::string ModuleName() const { " <<
2168  "return \"" << program_name_ << "\"; }" << endl << endl;
2169 
2170  // Is this a Sandesh Request ?
2171  if (is_request) {
2172  // Generate default constructor
2173  generate_sandesh_default_ctor(out, tsandesh, true);
2174  // Request registration
2175  indent(out) << "SANDESH_REGISTER_DEC_TYPE(" << tsandesh->get_name() <<
2176  ");" << endl;
2177  out << indent() << "virtual void HandleRequest() const;" << endl;
2178  indent(out) << "virtual bool RequestFromHttp(" <<
2179  "const std::string& ctx, const std::string& snh_query);" << endl;
2180 
2181  // Generate creator
2182  out << indent() << "static void Request" <<
2183  generate_sandesh_no_static_const_string_function(tsandesh, true, true, false, is_request, true) <<
2184  " {" << endl;
2185  indent_up();
2186  out << indent() << tsandesh->get_name() <<
2187  " * snh = new " << tsandesh->get_name() <<
2188  generate_sandesh_no_static_const_string_function(tsandesh, false, false, false, is_request) <<
2189  ";" << endl;
2190  out << indent() << "snh->Dispatch(sconn);" << endl;
2191  indent_down();
2192  indent(out) << "}" << endl << endl;
2193  } else if (is_response) {
2194  // Sandesh response
2195  // Generate default constructor
2196  generate_sandesh_default_ctor(out, tsandesh, false);
2197  // Generate creator
2198  string creator_func_name = "Response";
2199  out << indent() << "void " << creator_func_name <<
2200  "() { Dispatch(); }" << endl;
2201  } else if (is_uve || is_alarm) {
2202  const vector<t_field*>& fields = tsandesh->get_members();
2203  vector<t_field*>::const_iterator f_iter = fields.begin();
2204  assert((*f_iter)->get_name() == "data");
2205 
2206  bool is_proxy = false;
2207  std::map<std::string, std::string>::iterator ait;
2208  ait = ((*f_iter)->get_type())->annotations_.find("timeout");
2209  if (ait != ((*f_iter)->get_type())->annotations_.end()) {
2210  is_proxy = true;
2211  }
2212 
2213  if (is_proxy) {
2214  indent(out) << "static void Send(const " << type_name((*f_iter)->get_type()) <<
2215  "& data, std::string table = \"\", uint64_t mono_usec=0, int partition=-1);" << endl;
2216  indent(out) << "static void Send(const " << type_name((*f_iter)->get_type()) <<
2217  "& data, SandeshLevel::type Xlevel = SandeshLevel::SYS_NOTICE, " <<
2218  "std::string table = \"\", uint64_t mono_usec=0, int partition=-1);" << endl;
2219  std::map<std::string, std::string>::iterator pit;
2220  pit = ((*f_iter)->get_type())->annotations_.find("period");
2221  indent(out) << "static const uint64_t kProxyPeriod_us = " <<
2222  pit->second.c_str() << "000000;" << endl;
2223 
2224  } else {
2225  indent(out) << "static void Send(const " << type_name((*f_iter)->get_type()) <<
2226  "& data, std::string table = \"\", uint64_t mono_usec=0);" << endl;
2227  indent(out) << "static void Send(const " << type_name((*f_iter)->get_type()) <<
2228  "& data, SandeshLevel::type Xlevel, " <<
2229  "std::string table = \"\", uint64_t mono_usec=0);" << endl;
2230  }
2231 
2232  indent(out) << "static void Send(const " << type_name((*f_iter)->get_type()) <<
2233  "& cdata, SandeshUVE::SendType stype, uint32_t seqno," <<
2234  " uint32_t cycle, std::string ctx = \"\");" << endl;
2235  indent(out) << "static void Send(const " << type_name((*f_iter)->get_type()) <<
2236  "& cdata, SandeshLevel::type Xlevel, SandeshUVE::SendType stype, " <<
2237  "uint32_t seqno, uint32_t cycle, std::string ctx = \"\");" << endl;
2238  } else if (is_system) {
2239  generate_sandesh_systemlog_creators(out, tsandesh);
2240  } else if (is_flow) {
2241  generate_sandesh_flow_creators(out, tsandesh);
2242  } else if (is_object) {
2243  generate_sandesh_objectlog_creators(out, tsandesh);
2244  } else if (is_trace) {
2245  // Sandesh trace
2246  out << indent() << "virtual void SendTrace(" <<
2247  "const std::string& tcontext, bool more) {" << endl;
2248  indent_up();
2249  indent(out) << "set_context(tcontext);" << endl;
2250  indent(out) << "set_more(more);" << endl;
2251  out << indent() << tsandesh->get_name() <<
2252  " * snh = new " << tsandesh->get_name() << "(*this);" << endl;
2253  indent(out) << "snh->Dispatch();" << endl;
2254  indent_down();
2255  indent(out) << "}" << endl << endl;
2256  // Generate Trace function and Macro
2257  string creator_func_name = "TraceMsg";
2258  out << endl << indent() << "static void " << creator_func_name <<
2259  generate_sandesh_trace_creator(tsandesh, true, false, false, "", "") <<
2260  ";" << endl << endl;
2261  string creator_macro_name = tsandesh->get_name() + "Trace";
2262  string creator_name_usc = underscore(creator_macro_name);
2263  string creator_name_uc = uppercase(creator_name_usc);
2264  out << indent() << "#define " << creator_name_uc <<
2265  generate_sandesh_trace_creator(tsandesh, false, false, true, "_", "") <<
2266  "\\" << endl;
2267  indent_up();
2268  out << indent() << tsandesh->get_name() << "::" << creator_func_name <<
2269  generate_sandesh_trace_creator(tsandesh, false, true, false, "(_", ")") <<
2270  endl;
2271  indent_down();
2272  } else if (is_buffer) {
2273  // Sandesh kernel
2274  // Generate default constructor
2275  generate_sandesh_default_ctor(out, tsandesh, false);
2276  // Request registration
2277  indent(out) << "SANDESH_REGISTER_DEC_TYPE(" << tsandesh->get_name() <<
2278  ");" << endl << endl;
2279  }
2280 
2281  //Generate versionsig return function
2282  out << indent() << "virtual const int32_t versionsig() const { return versionsig_;}" << endl;
2283  out << indent() << "static const int32_t sversionsig() { return versionsig_;}" << endl;
2284 
2285  if (!is_trace) {
2286  out << indent() << "static int32_t lseqnum() { return lseqnum_;}" << endl;
2287  }
2288 
2289  if (is_uve || is_alarm) {
2290  const vector<t_field*>& fields = tsandesh->get_members();
2291  vector<t_field*>::const_iterator f_iter = fields.begin();
2292  assert((*f_iter)->get_name() == "data");
2293  string dtype = type_name((*f_iter)->get_type());
2294  out << indent() <<
2295  "static std::map<std::string, std::string> _DSConf(void);" << endl;
2296  out << indent() << "static void _InitDerivedStats(" << dtype <<
2297  " & _data, const map<string,string> & _dsconf);" << endl;
2298  out << indent() << "static bool UpdateUVE(" << dtype <<
2299  " & _data, " << dtype <<
2300  " & tdata, uint64_t mono_usec, SandeshLevel::type Xlevel);" << endl;
2301  out << indent() << "bool LoadUVE(SendType stype, uint32_t cycle);" << endl;
2302  }
2303 
2304  out << indent() << "std::string ToString() const;" << endl;
2305 
2306  out << indent() << "size_t GetSize() const;" << endl;
2307 
2308  // Private members
2309  out << endl;
2310  out << "private:" << endl << endl;
2311  if (((t_base_type *)t)->is_sandesh_buffer()) {
2312  indent(out) << "virtual void Process(SandeshContext *context);" << endl << endl;
2313  } else if (!((t_base_type *)t)->is_sandesh_response()) {
2314  // Explicit constructor
2315  indent(out) << "explicit " << tsandesh->get_name();
2316  out << generate_sandesh_no_static_const_string_function(tsandesh, true, false, false, is_request);
2317  generate_sandesh_member_init_list(out, tsandesh, false);
2318  out << " {" << endl;
2319  indent_up();
2320  // TODO(dreiss): When everything else in Thrift is perfect,
2321  // do more of these in the initializer list.
2322  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2323  t_type* t = get_true_type((*m_iter)->get_type());
2324  if (!t->is_base_type()) {
2325  t_const_value* cv = (*m_iter)->get_value();
2326  if (cv != NULL) {
2327  print_const_value(out, (*m_iter)->get_name(), t, cv);
2328  }
2329  }
2330  }
2331  if (is_trace) {
2332  generate_sandesh_trace_seqnum_ctor(out, tsandesh);
2333  }
2334  if (is_request) {
2335  generate_sandesh_context(out, tsandesh, "context");
2336  out << indent() << "if (context == \"ctrl\") " <<
2337  "set_hints(g_sandesh_constants.SANDESH_CONTROL_HINT);" << endl;
2338  out << indent() << "else set_hints(0);" << endl;
2339  out << indent() << "(void)sconn;" << endl;
2340 
2341  } else {
2342  generate_sandesh_hints(out, tsandesh);
2343  }
2344  scope_down(out);
2345  }
2346 
2347  // Create emplty constructor since objectlogs can have optional fields
2348  if (((t_base_type *)t)->is_sandesh_object()) {
2349  out << endl << indent() << "explicit " << tsandesh->get_name()
2350  << "(uint32_t seqno," " std::string file, int32_t line) : ";
2351  generate_sandesh_base_init(out, tsandesh, false);
2352  out << ", file(file), line(line) {" << endl;
2353  indent_up();
2354  generate_sandesh_hints(out, tsandesh);
2355  scope_down(out);
2356  }
2357 
2358  // Declare all fields
2359  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2360  indent(out) << declare_field(*m_iter, false, false, false) << endl;
2361  }
2362 
2363  if (!is_trace) {
2364  generate_sandesh_seqnum(out, tsandesh);
2365  }
2366 
2367  generate_sandesh_versionsig(out, tsandesh);
2368 
2369  out << indent() << "static const char *name_;" << endl;
2370 
2371  out << indent() << "void Log() const;" << endl;
2372 
2373  out << indent() << "void ForcedLog() const;" << endl;
2374 
2375  out << indent() << "int32_t Read(" <<
2376  "boost::shared_ptr<contrail::sandesh::protocol::TProtocol> iprot);" << endl;
2377 
2378  out << indent() << "int32_t Write(" <<
2379  "boost::shared_ptr<contrail::sandesh::protocol::TProtocol> oprot) const;" << endl;
2380 
2381  if (((t_base_type *)t)->is_sandesh_system()) {
2382  out << indent() << "static bool do_rate_limit_drop_log_;" << endl;
2383 
2384  out << indent() << "static boost::circular_buffer<time_t>"
2385  " rate_limit_buffer_;" << endl;
2386 
2387  out << indent() << "static tbb::mutex rate_limit_mutex_;" << endl;
2388  }
2389 
2390  out << endl;
2391  indent_down();
2392  indent(out) << "};" << endl << endl;
2393 }
2394 
2395 void t_cpp_generator::generate_sandesh_fingerprint(ofstream& out,
2396  t_sandesh* tsandesh,
2397  bool is_definition) {
2398  string stat, nspace, comment;
2399  if (is_definition) {
2400  stat = "";
2401  nspace = tsandesh->get_name() + "::";
2402  comment = " ";
2403  } else {
2404  stat = "static ";
2405  nspace = "";
2406  comment = "; // ";
2407  }
2408 
2409  if (tsandesh->has_fingerprint()) {
2410  out <<
2411  indent() << stat << "const char* " << nspace
2412  << "ascii_fingerprint" << comment << "= \"" <<
2413  tsandesh->get_ascii_fingerprint() << "\";" << endl <<
2414  indent() << stat << "const uint8_t " << nspace <<
2415  "binary_fingerprint[" << t_type::fingerprint_len << "]" << comment << "= {";
2416  const char* comma = "";
2417  for (int i = 0; i < t_type::fingerprint_len; i++) {
2418  out << comma << "0x" << t_struct::byte_to_hex(tsandesh->get_binary_fingerprint()[i]);
2419  comma = ",";
2420  }
2421  out << "};" << endl << endl;
2422  }
2423 }
2424 
2425 void t_cpp_generator::cache_attr_info(t_struct* tstruct,
2426  std::map<string, CacheAttribute> &attrs) {
2427  attrs.clear();
2428  const vector<t_field*>& members = tstruct->get_members();
2429  vector<t_field*>::const_iterator m_iter;
2430  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2431  std::map<std::string, std::string>::iterator jt;
2432  jt = (*m_iter)->annotations_.find("hidden");
2433  if ((*m_iter)->get_req()!=t_field::T_OPTIONAL) {
2434  // Mandatory fields cannot have DerivedStats,
2435  // or be of hidden/periodic type
2436  assert(jt == (*m_iter)->annotations_.end());
2437  assert((*m_iter)->annotations_.find("stats") == (*m_iter)->annotations_.end());
2438  assert((*m_iter)->annotations_.find("mstats") == (*m_iter)->annotations_.end());
2439  attrs.insert(std::make_pair((*m_iter)->get_name(),
2440  MANDATORY));
2441  continue;
2442  }
2443  // DervivedStats attributes are not handled here
2444  if (((*m_iter)->annotations_.find("stats") != (*m_iter)->annotations_.end()) ||
2445  ((*m_iter)->annotations_.find("mstats") != (*m_iter)->annotations_.end())) {
2446  continue;
2447  }
2448  // All raw attributes are Non-periodic
2449  if (jt!=(*m_iter)->annotations_.end()) {
2450  attrs.insert(std::make_pair((*m_iter)->get_name(), HIDDEN));
2451  } else {
2452  attrs.insert(std::make_pair((*m_iter)->get_name(), INLINE));
2453  }
2454  }
2455 }
2456 
2457 void t_cpp_generator::derived_stats_info(t_struct* tstruct,
2458  // val is rawtype,resulttype,algo,annotation,compattr,subcompattr
2459  map<string,DSInfo> & dsmap,
2460  // val is set of ds attributes
2461  map<string,set<string> >& rawmap) {
2462  const vector<t_field*>& members = tstruct->get_members();
2463  vector<t_field*>::const_iterator m_iter;
2464  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2465  std::map<std::string, std::string>::iterator jt,mt;
2466  jt = (*m_iter)->annotations_.find("stats");
2467  mt = (*m_iter)->annotations_.find("mstats");
2468  if ((jt != (*m_iter)->annotations_.end()) ||
2469  (mt != (*m_iter)->annotations_.end())) {
2470  assert((*m_iter)->get_req() == t_field::T_OPTIONAL);
2471 
2472  t_type* retype = get_true_type((*m_iter)->get_type());
2473  string restype;
2474 
2475  bool is_ds_map = false;
2476  // for map derived-stats
2477  if (mt!= (*m_iter)->annotations_.end()) {
2478  // out of mstats and stats, only one should be specified
2479  assert(jt == (*m_iter)->annotations_.end());
2480  is_ds_map = true;
2481  assert(retype->is_map());
2482  t_type* vtype = ((t_map*)retype)->get_val_type();
2483  restype = type_name(get_true_type(vtype));
2484  } else {
2485  restype = type_name(get_true_type((*m_iter)->get_type()));
2486  }
2487 
2488  const string &tstr = ((jt == (*m_iter)->annotations_.end()) ?
2489  mt->second : jt->second);
2490  size_t pos = tstr.find(':');
2491 
2492  string residual = tstr.substr(pos+1, string::npos);
2493  size_t rpos = residual.find(':');
2494  string algo, anno;
2495  if (rpos == string::npos) {
2496  // No Derived Stats arguments are present
2497  algo = residual;
2498  anno = string();
2499  } else {
2500  algo = residual.substr(0,rpos);
2501  anno = residual.substr(rpos+1, string::npos);
2502  }
2503 
2504  string rawfullattr;
2505  string rawperiodattr = tstr.substr(0,pos);
2506  size_t ppos = rawperiodattr.find("-");
2507  int period = -1;
2508  string prealgo;
2509  if (ppos != string::npos) {
2510  string periodpre = rawperiodattr.substr(0,ppos);
2511  size_t prepos = periodpre.find(".");
2512  if (prepos != string::npos) {
2513  period = atoi(periodpre.substr(0,prepos).c_str());
2514  prealgo = periodpre.substr(prepos+1, string::npos);
2515  } else {
2516  period = atoi(rawperiodattr.substr(0,ppos).c_str());
2517  }
2518 
2519  rawfullattr = rawperiodattr.substr(ppos+1, string::npos);
2520  } else {
2521  rawfullattr = rawperiodattr;
2522  }
2523 
2524  size_t cpos = rawfullattr.find('.');
2525  string rawattr;
2526  string compattr("");
2527  string subcompattr("");
2528 
2529  // Does the raw attribute have a composite underneath it?
2530  if (cpos != string::npos) {
2531  rawattr = rawfullattr.substr(0,cpos);
2532  string rescomp = rawfullattr.substr(cpos+1, string::npos);
2533  size_t upos = rescomp.find('.');
2534  if (upos != string::npos) {
2535  compattr = rescomp.substr(0,upos);
2536  subcompattr = rescomp.substr(upos+1, string::npos);
2537  } else {
2538  compattr = rescomp;
2539  }
2540  } else {
2541  rawattr = rawfullattr;
2542  }
2543 
2544  string rawtype;
2545  RawMetric rmt = RM_DIAL;
2546  vector<t_field*>::const_iterator s_iter;
2547  for (s_iter = members.begin(); s_iter != members.end(); ++s_iter) {
2548  if (rawattr.compare((*s_iter)->get_name())==0) {
2549  map<string,string>::const_iterator cit =
2550  (*s_iter)->annotations_.find("metric");
2551  if (cit != (*s_iter)->annotations_.end()) {
2552  if (cit->second.compare("agg") == 0) rmt = RM_AGG;
2553  else if (cit->second.compare("diff") == 0) rmt = RM_DIFF;
2554  }
2555  t_type* ratype = get_true_type((*s_iter)->get_type());
2556  t_type* vtype = ratype;
2557  if (is_ds_map) {
2558  assert(ratype->is_map());
2559  vtype = ((t_map*)ratype)->get_val_type();
2560  }
2561  rawtype = type_name(vtype);
2562  if (!compattr.empty()) {
2563  // The raw attribute is a composite/subcomposite
2564  // Find info for the composite attribute.
2565  assert(vtype->is_struct());
2566  rawtype = string("");
2567  const vector<t_field*>& cmembers = ((t_struct*)vtype)->get_members();
2568  vector<t_field*>::const_iterator c_iter;
2569  for (c_iter = cmembers.begin(); c_iter != cmembers.end(); ++c_iter) {
2570  if (compattr.compare((*c_iter)->get_name())==0) {
2571  t_type* catype = get_true_type((*c_iter)->get_type());
2572  if (!subcompattr.empty()) {
2573  // The raw attribute is a subcomposite
2574  assert(catype->is_struct());
2575  const vector<t_field*>& umem =
2576  ((t_struct*)catype)->get_members();
2577  vector<t_field*>::const_iterator u_iter;
2578  for (u_iter = umem.begin(); u_iter != umem.end(); ++u_iter) {
2579  if (subcompattr.compare((*u_iter)->get_name())==0) {
2580  t_type* uatype = get_true_type((*u_iter)->get_type());
2581  rawtype = type_name(uatype);
2582  break;
2583  }
2584  }
2585 
2586  } else {
2587  rawtype = type_name(catype);
2588  }
2589  break;
2590  }
2591  }
2592  }
2593  break;
2594  }
2595  }
2596  assert(!rawtype.empty());
2597 
2598  bool is_hidden =
2599  (*m_iter)->annotations_.find("hidden") != (*m_iter)->annotations_.end();
2600 
2601  CacheAttribute cat = INLINE;
2602  if (tstruct->annotations_.find("period") != tstruct->annotations_.end()) {
2603  // By default, DS attributes in periodic structs have period 1
2604  if (period==-1) period=1;
2605  if (is_hidden) {
2606  if (period!=0) cat = HIDDEN_PER;
2607  else cat = HIDDEN;
2608  } else {
2609  if (period!=0) cat = PERIODIC;
2610  // else this DS stays INLINE
2611  }
2612  } else {
2613  // DS attributes in non-periodic structs must have period 0
2614  if (period==-1) period=0;
2615  if (is_hidden) {
2616  cat = HIDDEN;
2617  }
2618  // else this DS stays INLINE
2619  assert(period==0);
2620  }
2621 
2622  DSInfo dsi(is_ds_map, period, cat, rawtype, rmt,
2623  restype, algo, anno, compattr, subcompattr, prealgo);
2624 
2625  // map of derived stats
2626  dsmap.insert(make_pair((*m_iter)->get_name(), dsi));
2627 
2628  // map of raw attributes
2629  map<string,set<string> >::iterator r_iter = rawmap.find(rawattr);
2630  if (r_iter != rawmap.end()) {
2631  r_iter->second.insert((*m_iter)->get_name());
2632  } else {
2633  set<string> dss;
2634  dss.insert((*m_iter)->get_name());
2635  rawmap.insert(make_pair(rawattr,dss));
2636  }
2637  }
2638  }
2639 }
2640 #endif
2641 
2648  t_struct* tstruct,
2649  bool is_exception,
2650  bool pointers,
2651  bool read,
2652  bool write) {
2653  string extends = "";
2654  if (is_exception) {
2655  extends = " : public ::contrail::sandesh::TException";
2656  }
2657 
2658  // Get members
2659  vector<t_field*>::const_iterator m_iter;
2660  const vector<t_field*>& members = tstruct->get_members();
2661 
2662  // Write the isset structure declaration outside the class. This makes
2663  // the generated code amenable to processing by SWIG.
2664  // We only declare the struct if it gets used in the class.
2665 
2666  // Isset struct has boolean fields, but only for non-required fields.
2667  bool has_nonrequired_fields = false;
2668  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2669  if ((*m_iter)->get_req() != t_field::T_REQUIRED)
2670  has_nonrequired_fields = true;
2671  }
2672 
2673  bool del_support = false;
2674  bool proxy_support = false;
2675  if (has_nonrequired_fields && (!pointers || read)) {
2676 
2677  out <<
2678  indent() << "typedef struct _" << tstruct->get_name() << "__isset {" << endl;
2679  indent_up();
2680 
2681  indent(out) <<
2682  "_" << tstruct->get_name() << "__isset() ";
2683  bool first = true;
2684  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2685  if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
2686  continue;
2687  }
2688  t_type* t = get_true_type((*m_iter)->get_type());
2689  if (t->is_base_type() &&
2690  ((*m_iter)->get_name().compare("deleted") == 0)) {
2691  t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
2692  if (tbase == t_base_type::TYPE_BOOL) del_support = true;
2693  }
2694  if (t->is_base_type() &&
2695  ((*m_iter)->get_name().compare("proxy") == 0)) {
2696  t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
2697  if (tbase == t_base_type::TYPE_STRING) proxy_support = true;
2698  }
2699 
2700  if (first) {
2701  first = false;
2702  out <<
2703  ": " << (*m_iter)->get_name() << "(false)";
2704  } else {
2705  out <<
2706  ", " << (*m_iter)->get_name() << "(false)";
2707  }
2708  }
2709  out << " {}" << endl;
2710 
2711  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2712  if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
2713  indent(out) <<
2714  "bool " << (*m_iter)->get_name() << ";" << endl;
2715  }
2716  }
2717 
2718  indent_down();
2719  indent(out) <<
2720  "} _" << tstruct->get_name() << "__isset;" << endl << endl;
2721 
2722  }
2723 
2724  out << endl;
2725 
2726  // Open struct def
2727  out <<
2728  indent() << "class " << tstruct->get_name() << extends << " {" << endl <<
2729  indent() << " public:" << endl <<
2730  endl;
2731  indent_up();
2732 
2733  // Put the fingerprint up top for all to see.
2734  generate_struct_fingerprint(out, tstruct, false);
2735 
2736 #ifdef SANDESH
2737  bool is_table = false;
2738 
2739  std::map<string, CacheAttribute> cache_attrs;
2740  cache_attr_info(tstruct, cache_attrs);
2741 
2742  map<string,DSInfo> dsinfo;
2743  map<string,set<string> > rawmap;
2744  derived_stats_info(tstruct, dsinfo, rawmap);
2745  map<string,DSInfo >::iterator ds_iter;
2746 #endif
2747 
2748  if (!pointers) {
2749  // Default constructor
2750 #ifdef SANDESH
2751  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2752  if ((*m_iter)->get_name() == "name") {
2753  std::map<std::string, std::string>::iterator it;
2754  it = (*m_iter)->annotations_.find("key");
2755  if (it != (*m_iter)->annotations_.end()) {
2756  is_table = true;
2757  indent(out) << tstruct->get_name() << "(std::string __tbl = \"" <<
2758  it->second << "\")";
2759  break;
2760  }
2761  }
2762  }
2763  if (!is_table) {
2764  indent(out) <<
2765  tstruct->get_name() << "()";
2766  }
2767 #else
2768  indent(out) <<
2769  tstruct->get_name() << "()";
2770 #endif
2771 
2772  bool init_ctor = false;
2773 
2774  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2775  t_type* t = get_true_type((*m_iter)->get_type());
2776 #ifdef SANDESH
2777  if (t->is_static_const_string()) {
2778  continue;
2779  }
2780 #endif
2781  if (t->is_base_type() || t->is_enum()) {
2782  string dval;
2783  if (t->is_enum()) {
2784  dval += "(" + type_name(t) + ")";
2785  }
2786  if (t->is_string() || t->is_xml()) {
2787  dval += "\"\"";
2788  } else if (t->is_uuid()) {
2789  dval += "boost::uuids::nil_uuid()";
2790  } else if (t->is_ipaddr()) {
2791  dval += "";
2792  } else {
2793  dval += "0";
2794  }
2795  t_const_value* cv = (*m_iter)->get_value();
2796  if (cv != NULL) {
2797  dval = render_const_value(out, (*m_iter)->get_name(), t, cv);
2798  }
2799  if (!init_ctor) {
2800  init_ctor = true;
2801  out << " : ";
2802  out << (*m_iter)->get_name() << "(" << dval << ")";
2803  } else {
2804  out << ", " << (*m_iter)->get_name() << "(" << dval << ")";
2805  }
2806  }
2807  }
2808 
2809 #ifdef SANDESH
2810  if (is_table) {
2811  out << ", table_(__tbl)";
2812  }
2813 #endif
2814  out << " {" << endl;
2815  indent_up();
2816  // TODO(dreiss): When everything else in Thrift is perfect,
2817  // do more of these in the initializer list.
2818  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2819  t_type* t = get_true_type((*m_iter)->get_type());
2820 
2821  if (!t->is_base_type()) {
2822  t_const_value* cv = (*m_iter)->get_value();
2823  if (cv != NULL) {
2824  print_const_value(out, (*m_iter)->get_name(), t, cv);
2825  }
2826  }
2827  }
2828  scope_down(out);
2829  }
2830 
2831  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
2832  out <<
2833  endl <<
2834  indent() << "virtual ~" << tstruct->get_name() << "() throw() {}" << endl << endl;
2835  }
2836 
2837  // Pointer to this structure's reflection local typespec.
2838  if (gen_dense_) {
2839  indent(out) <<
2840  "static ::contrail::sandesh::reflection::local::TypeSpec* local_reflection;" <<
2841  endl << endl;
2842  }
2843 
2844  // Declare all fields
2845  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2846  indent(out) <<
2847  declare_field(*m_iter, false, pointers && !(*m_iter)->get_type()->is_xception(), !read) << endl;
2848  }
2849 #ifdef SANDESH
2850  for (ds_iter = dsinfo.begin(); ds_iter != dsinfo.end(); ++ds_iter) {
2851 
2852  // val is rawtype,resulttype,algo,annotation,compattr,subcompattr
2853  if ((ds_iter->second.cat_ == PERIODIC) ||
2854  (ds_iter->second.cat_ == HIDDEN_PER)) {
2855  if (ds_iter->second.prealgo_.empty()) {
2856  indent(out) << "boost::shared_ptr< ::contrail::sandesh::DerivedStatsPeriodicIf< ::contrail::sandesh::" <<
2857  ds_iter->second.algo_ << ", " <<
2858  ds_iter->second.rawtype_ << ", " <<
2859  ds_iter->second.resulttype_.substr(0, ds_iter->second.resulttype_.size() - 3) << ", " <<
2860  ds_iter->second.resulttype_ <<
2861  "> > __dsobj_" << ds_iter->first << ";" << endl;
2862  } else {
2863  indent(out) << "boost::shared_ptr< ::contrail::sandesh::DerivedStatsPeriodicAnomalyIf< ::contrail::sandesh::" <<
2864  ds_iter->second.algo_ << ", " <<
2865  ds_iter->second.rawtype_ << ", ::contrail::sandesh::" <<
2866  ds_iter->second.prealgo_ << ", " <<
2867  ds_iter->second.resulttype_ <<
2868  "> > __dsobj_" << ds_iter->first << ";" << endl;
2869  }
2870  } else {
2871  indent(out) << "boost::shared_ptr< ::contrail::sandesh::DerivedStatsIf< ::contrail::sandesh::" <<
2872  ds_iter->second.algo_ << ", " <<
2873  ds_iter->second.rawtype_ << ", " << ds_iter->second.resulttype_ <<
2874  "> > __dsobj_" << ds_iter->first << ";" << endl;
2875  }
2876 
2877  }
2878  if (is_table) {
2879  indent(out) << "std::string table_;" << endl;
2880  }
2881 
2882 #endif
2883 
2884  // Add the __isset data member if we need it, using the definition from above
2885  if (has_nonrequired_fields && (!pointers || read)) {
2886  out <<
2887  endl <<
2888  indent() << "_" << tstruct->get_name() << "__isset __isset;" << endl;
2889  }
2890 
2891  // Create a setter and getter function for each field except static const
2892  // string
2893  vector<string> dskeys;
2894  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2895  if (pointers) {
2896  continue;
2897  }
2898 #ifdef SANDESH
2899  if (((*m_iter)->get_type())->is_static_const_string()) {
2900  continue;
2901  }
2902  std::map<std::string, std::string>::iterator jt;
2903  jt = (*m_iter)->annotations_.find("aggtype");
2904  if (jt != (*m_iter)->annotations_.end()) {
2905  if (jt->second.compare("listkey")==0) {
2906  dskeys.push_back((*m_iter)->get_name());
2907  }
2908  }
2909 #endif
2910  out <<
2911  endl <<
2912 #ifdef SANDESH
2913  indent() << (dsinfo.find((*m_iter)->get_name()) == dsinfo.end() ?
2914  "void set_" : "void __set_") << (*m_iter)->get_name() <<
2915 #else
2916  indent() << "void __set_" << (*m_iter)->get_name() <<
2917 #endif
2918  "(" << type_name((*m_iter)->get_type(), false, true);
2919  out << " val) {" << endl << indent() <<
2920  indent() << (*m_iter)->get_name() << " = val;" << endl;
2921 
2922  // assume all fields are required except optional fields.
2923  // for optional fields change __isset.name to true
2924  bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
2925  if (is_optional) {
2926  out <<
2927  indent() <<
2928  indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl;
2929  }
2930  out <<
2931  indent()<< "}" << endl;
2932 
2933 #ifdef SANDESH
2934  out << endl << indent() << type_name((*m_iter)->get_type(), false, true)
2935  << " get_";
2936  out << (*m_iter)->get_name() << "() const {" << endl;
2937  out << indent() << indent() << "return " << (*m_iter)->get_name() << ";" << endl;
2938  out << indent() << "}" << endl;
2939 #endif
2940  }
2941  out << endl;
2942 
2943  if (!pointers) {
2944  out <<
2945  indent() << "bool operator == (long " <<
2946  (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl;
2947  scope_up(out);
2948  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2949  // Most existing Thrift code does not use isset or optional/required,
2950  // so we treat "default" fields as required.
2951  t_type* type = get_true_type((*m_iter)->get_type());
2952  if (type->is_base_type()) {
2953  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2954  switch (tbase) {
2956  case t_base_type::TYPE_I16:
2957  case t_base_type::TYPE_I32:
2958  case t_base_type::TYPE_I64:
2959  case t_base_type::TYPE_U16:
2960  case t_base_type::TYPE_U32:
2961  case t_base_type::TYPE_U64:
2963  if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
2964  out <<
2965  indent() << "if (!((long)" << (*m_iter)->get_name()
2966  << " == rhs))" << endl <<
2967  indent() << " return false;" << endl;
2968  } else {
2969  out <<
2970  indent() << "if (__isset." << (*m_iter)->get_name()
2971  << " && !((long)"
2972  << (*m_iter)->get_name() << " == rhs))" << endl <<
2973  indent() << " return false;" << endl;
2974  }
2975  break;
2976  default:
2977  out << indent() << "return false;" << endl;
2978  continue;
2979  }
2980  }
2981  }
2982  indent(out) << "return true;" << endl;
2983  scope_down(out);
2984  // Generate an equality testing operator. Make it inline since the compiler
2985  // will do a better job than we would when deciding whether to inline it.
2986  out <<
2987  indent() << "bool operator == (const " << tstruct->get_name() << " & " <<
2988  (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl;
2989  scope_up(out);
2990  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2991  // Most existing Thrift code does not use isset or optional/required,
2992  // so we treat "default" fields as required.
2993  if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
2994  out <<
2995  indent() << "if (!(" << (*m_iter)->get_name()
2996  << " == rhs." << (*m_iter)->get_name() << "))" << endl <<
2997  indent() << " return false;" << endl;
2998  } else {
2999  out <<
3000  indent() << "if (__isset." << (*m_iter)->get_name()
3001  << " != rhs.__isset." << (*m_iter)->get_name() << ")" << endl <<
3002  indent() << " return false;" << endl <<
3003  indent() << "else if (__isset." << (*m_iter)->get_name() << " && !("
3004  << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name()
3005  << "))" << endl <<
3006  indent() << " return false;" << endl;
3007  }
3008  }
3009  indent(out) << "return true;" << endl;
3010  scope_down(out);
3011  out <<
3012  indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {" << endl <<
3013  indent() << " return !(*this == rhs);" << endl <<
3014  indent() << "}" << endl << endl;
3015 
3016  // Generate the declaration of a less-than operator. This must be
3017  // implemented by the application developer if they wish to use it. (They
3018  // will get a link error if they try to use it without an implementation.)
3019  out <<
3020  indent() << "bool operator < (const "
3021  << tstruct->get_name() << " & ) const;" << endl << endl;
3022  }
3023 
3024  if (read) {
3025  if (gen_templates_) {
3026  out <<
3027  indent() << "template <class Protocol_>" << endl <<
3028  indent() << "uint32_t read(Protocol_* iprot);" << endl;
3029  } else {
3030  out <<
3031  indent() << "int32_t read(" <<
3032  "boost::shared_ptr<contrail::sandesh::protocol::TProtocol> iprot);" << endl;
3033  }
3034  }
3035  if (write) {
3036  if (gen_templates_) {
3037  out <<
3038  indent() << "template <class Protocol_>" << endl <<
3039  indent() << "uint32_t write(Protocol_* oprot) const;" << endl;
3040  } else {
3041  out <<
3042  indent() << "int32_t write(" <<
3043  "boost::shared_ptr<contrail::sandesh::protocol::TProtocol> oprot) const;" << endl;
3044  }
3045  }
3046 #ifdef SANDESH
3047  out << indent() << "std::string log() const;" << endl;
3048  if (!pointers) {
3049  out << indent() <<
3050  tstruct->get_name() << " operator+(const " << tstruct->get_name() <<
3051  "& right) const" << endl;
3052  scope_up(out);
3053  out << indent() << tstruct->get_name() << " result;" << endl;
3054  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3055  std::string nn = (*m_iter)->get_name();
3056  ds_iter = dsinfo.find((*m_iter)->get_name());
3057  std::string sn;
3058  if (ds_iter == dsinfo.end()) sn = std::string("set_");
3059  else sn = std::string("__set_");
3060 
3061  t_type* type = get_true_type((*m_iter)->get_type());
3062  if (type->is_base_type()) {
3063  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3064  switch (tbase) {
3066  case t_base_type::TYPE_I16:
3067  case t_base_type::TYPE_I32:
3068  case t_base_type::TYPE_I64:
3070  case t_base_type::TYPE_U16:
3071  case t_base_type::TYPE_U32:
3072  case t_base_type::TYPE_U64:
3073  if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
3074  out <<
3075  indent() << "result." << sn << nn << "(get_" << nn <<
3076  "() + right.get_" << nn << "());" << endl << endl;
3077  } else {
3078  out <<
3079  indent() << "if ((__isset." << nn << ") && (right.__isset." <<
3080  nn << ")) result." << sn << nn << "(get_" << nn <<
3081  "() + right.get_" << nn << "());" << endl <<
3082  indent() << "else if (__isset." << nn << ") result." << sn <<
3083  nn << "(get_" << nn << "());" << endl <<
3084  indent() << "else if (right.__isset." << nn << ") result." << sn <<
3085  nn << "(right.get_" << nn << "());" << endl << endl;
3086  }
3087  default:
3088  continue;
3089  }
3090  }
3091  }
3092  indent(out) << "return result;" << endl;
3093  scope_down(out);
3094 
3095  out << indent() <<
3096  tstruct->get_name() << " operator/(int div) const" << endl;
3097  scope_up(out);
3098  out << indent() << tstruct->get_name() << " result;" << endl;
3099  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3100  std::string nn = (*m_iter)->get_name();
3101  ds_iter = dsinfo.find((*m_iter)->get_name());
3102  std::string sn;
3103  if (ds_iter == dsinfo.end()) sn = std::string("set_");
3104  else sn = std::string("__set_");
3105 
3106  t_type* type = get_true_type((*m_iter)->get_type());
3107  if (type->is_base_type()) {
3108  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3109  switch (tbase) {
3111  case t_base_type::TYPE_I16:
3112  case t_base_type::TYPE_I32:
3113  case t_base_type::TYPE_I64:
3115  case t_base_type::TYPE_U16:
3116  case t_base_type::TYPE_U32:
3117  case t_base_type::TYPE_U64:
3118  if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
3119  out <<
3120  indent() << "result." << sn << nn << "(get_" << nn <<
3121  "() / div);" << endl << endl;
3122  } else {
3123  out <<
3124  indent() << "if (__isset." << nn << ") result." << sn << nn << "(get_" <<
3125  nn << "() / div);" << endl << endl;
3126  }
3127  default:
3128  continue;
3129  }
3130  }
3131  }
3132  indent(out) << "return result;" << endl;
3133  scope_down(out);
3134 
3135  out << indent() <<
3136  tstruct->get_name() << " operator-(const " << tstruct->get_name() <<
3137  "& right) const" << endl;
3138  scope_up(out);
3139  out << indent() << tstruct->get_name() << " result;" << endl;
3140  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3141  std::string nn = (*m_iter)->get_name();
3142  ds_iter = dsinfo.find((*m_iter)->get_name());
3143  std::string sn;
3144  if (ds_iter == dsinfo.end()) sn = std::string("set_");
3145  else sn = std::string("__set_");
3146  t_type* type = get_true_type((*m_iter)->get_type());
3147  if (type->is_base_type()) {
3148  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3149  switch (tbase) {
3151  case t_base_type::TYPE_I16:
3152  case t_base_type::TYPE_I32:
3153  case t_base_type::TYPE_I64:
3155  case t_base_type::TYPE_U16:
3156  case t_base_type::TYPE_U32:
3157  case t_base_type::TYPE_U64:
3158  if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
3159  out <<
3160  indent() << "result." << sn << nn << "(get_" << nn <<
3161  "() - right.get_" << nn << "());" << endl << endl;
3162  } else {
3163  out <<
3164  indent() << "if ((__isset." << nn << ") && (right.__isset." <<
3165  nn << ")) {" << endl <<
3166  indent() << " result." << sn << nn << "(get_" << nn <<
3167  "() - right.get_" << nn << "()); }" << endl <<
3168  indent() << "else if (__isset." << nn << ") result." << sn <<
3169  nn << "(get_" << nn << "());" << endl;
3170  }
3171  default:
3172  continue;
3173  }
3174  }
3175  }
3176  indent(out) << "return result;" << endl;
3177  scope_down(out);
3178  }
3179  out << indent() << "size_t GetSize() const;" << endl;
3180  out << indent() << "std::string __listkey(void) {" << endl;
3181  out << indent() << " std::string __result;" << endl;
3182  bool first = true;
3183  vector<string>::iterator kit;
3184  for (kit = dskeys.begin(); kit != dskeys.end(); kit++) {
3185  if (!first) {
3186  out << indent() << " __result.append(\":\");" << endl;
3187  }
3188  out << indent() << " __result += " << *kit << ";" << endl;
3189  first = false;
3190  }
3191  out << indent() << " return __result;" << endl;
3192  out << indent() << "}" << endl;
3193 #endif
3194  out << endl;
3195 
3196  indent_down();
3197  indent(out) <<
3198  "};" << endl <<
3199  endl;
3200 
3201  if (del_support) {
3202  out <<
3203  indent() << "template <>" << endl <<
3204  indent() << "struct SandeshStructDeleteTrait<" <<
3205  tstruct->get_name() << "> {" << endl <<
3206  indent() << " static bool get(const " <<
3207  tstruct->get_name() << "& s) { return s.get_deleted(); }" <<
3208  endl <<
3209  indent() << "};" << endl;
3210  }
3211  if (proxy_support) {
3212  out <<
3213  indent() << "template <>" << endl <<
3214  indent() << "struct SandeshStructProxyTrait<" <<
3215  tstruct->get_name() << "> {" << endl <<
3216  indent() << " static std::string get(const " <<
3217  tstruct->get_name() << "& s) { return s.get_proxy(); }" <<
3218  endl <<
3219  indent() << "};" << endl;
3220  }
3221 }
3222 
3230  t_struct* tstruct,
3231  bool is_definition) {
3232  string stat, nspace, comment;
3233  if (is_definition) {
3234  stat = "";
3235  nspace = tstruct->get_name() + "::";
3236  comment = " ";
3237  } else {
3238  stat = "static ";
3239  nspace = "";
3240  comment = "; // ";
3241  }
3242 
3243  if (tstruct->has_fingerprint()) {
3244  out <<
3245  indent() << stat << "const char* " << nspace
3246  << "ascii_fingerprint" << comment << "= \"" <<
3247  tstruct->get_ascii_fingerprint() << "\";" << endl <<
3248  indent() << stat << "const uint8_t " << nspace <<
3249  "binary_fingerprint[" << t_type::fingerprint_len << "]" << comment << "= {";
3250  const char* comma = "";
3251  for (int i = 0; i < t_type::fingerprint_len; i++) {
3252  out << comma << "0x" << t_struct::byte_to_hex(tstruct->get_binary_fingerprint()[i]);
3253  comma = ",";
3254  }
3255  out << "};" << endl << endl;
3256  }
3257 }
3258 
3263  t_type* ttype,
3264  bool is_definition) {
3265  if (!gen_dense_) {
3266  return;
3267  }
3268  ttype = get_true_type(ttype);
3269  assert(ttype->has_fingerprint());
3270  string key = ttype->get_ascii_fingerprint() + (is_definition ? "-defn" : "-decl");
3271  // Note that we have generated this fingerprint. If we already did, bail out.
3272  if (!reflected_fingerprints_.insert(key).second) {
3273  return;
3274  }
3275  // Let each program handle its own structures.
3276  if (ttype->get_program() != NULL && ttype->get_program() != program_) {
3277  return;
3278  }
3279 
3280  // Do dependencies.
3281  if (ttype->is_list()) {
3282  generate_local_reflection(out, ((t_list*)ttype)->get_elem_type(), is_definition);
3283  } else if (ttype->is_set()) {
3284  generate_local_reflection(out, ((t_set*)ttype)->get_elem_type(), is_definition);
3285  } else if (ttype->is_map()) {
3286  generate_local_reflection(out, ((t_map*)ttype)->get_key_type(), is_definition);
3287  generate_local_reflection(out, ((t_map*)ttype)->get_val_type(), is_definition);
3288  } else if (ttype->is_struct() || ttype->is_xception()) {
3289  // Hacky hacky. For efficiency and convenience, we need a dummy "T_STOP"
3290  // type at the end of our typespec array. Unfortunately, there is no
3291  // T_STOP type, so we use the global void type, and special case it when
3292  // generating its typespec.
3293 
3294  const vector<t_field*>& members = ((t_struct*)ttype)->get_sorted_members();
3295  vector<t_field*>::const_iterator m_iter;
3296  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3297  generate_local_reflection(out, (**m_iter).get_type(), is_definition);
3298  }
3299  generate_local_reflection(out, g_type_void, is_definition);
3300 
3301  // For definitions of structures, do the arrays of metas and field specs also.
3302  if (is_definition) {
3303  out <<
3304  indent() << "::contrail::sandesh::reflection::local::FieldMeta" << endl <<
3305  indent() << local_reflection_name("metas", ttype) <<"[] = {" << endl;
3306  indent_up();
3307  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3308  indent(out) << "{ " << (*m_iter)->get_key() << ", " <<
3309  (((*m_iter)->get_req() == t_field::T_OPTIONAL) ? "true" : "false") <<
3310  " }," << endl;
3311  }
3312  // Zero for the T_STOP marker.
3313  indent(out) << "{ 0, false }" << endl << "};" << endl;
3314  indent_down();
3315 
3316  out <<
3317  indent() << "::contrail::sandesh::reflection::local::TypeSpec*" << endl <<
3318  indent() << local_reflection_name("specs", ttype) <<"[] = {" << endl;
3319  indent_up();
3320  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3321  indent(out) << "&" <<
3322  local_reflection_name("typespec", (*m_iter)->get_type(), true) << "," << endl;
3323  }
3324  indent(out) << "&" <<
3325  local_reflection_name("typespec", g_type_void) << "," << endl;
3326  indent_down();
3327  indent(out) << "};" << endl;
3328  }
3329  }
3330 
3331  out <<
3332  indent() << "// " << ttype->get_fingerprint_material() << endl <<
3333  indent() << (is_definition ? "" : "extern ") <<
3334  "::contrail::sandesh::reflection::local::TypeSpec" << endl <<
3335  local_reflection_name("typespec", ttype) <<
3336  (is_definition ? "(" : ";") << endl;
3337 
3338  if (!is_definition) {
3339  out << endl;
3340  return;
3341  }
3342 
3343  indent_up();
3344 
3345  if (ttype->is_void()) {
3346  indent(out) << "::contrail::sandesh::protocol::T_STOP";
3347  } else {
3348  indent(out) << type_to_enum(ttype);
3349  }
3350 
3351  if (ttype->is_struct()) {
3352  out << "," << endl <<
3353  indent() << type_name(ttype) << "::binary_fingerprint," << endl <<
3354  indent() << local_reflection_name("metas", ttype) << "," << endl <<
3355  indent() << local_reflection_name("specs", ttype);
3356  } else if (ttype->is_list()) {
3357  out << "," << endl <<
3358  indent() << "&" << local_reflection_name("typespec", ((t_list*)ttype)->get_elem_type(), true) << "," << endl <<
3359  indent() << "NULL";
3360  } else if (ttype->is_set()) {
3361  out << "," << endl <<
3362  indent() << "&" << local_reflection_name("typespec", ((t_set*)ttype)->get_elem_type(), true) << "," << endl <<
3363  indent() << "NULL";
3364  } else if (ttype->is_map()) {
3365  out << "," << endl <<
3366  indent() << "&" << local_reflection_name("typespec", ((t_map*)ttype)->get_key_type(), true) << "," << endl <<
3367  indent() << "&" << local_reflection_name("typespec", ((t_map*)ttype)->get_val_type(), true);
3368  }
3369 
3370  out << ");" << endl << endl;
3371 
3372  indent_down();
3373 }
3374 
3380  t_type* ttype) {
3381  if (!gen_dense_) {
3382  return;
3383  }
3384  indent(out) <<
3385  "::contrail::sandesh::reflection::local::TypeSpec* " <<
3386  ttype->get_name() << "::local_reflection = " << endl <<
3387  indent() << " &" << local_reflection_name("typespec", ttype) << ";" <<
3388  endl << endl;
3389 }
3390 
3398  t_struct* tstruct,
3399  bool pointers) {
3400  if (gen_templates_) {
3401  out <<
3402  indent() << "template <class Protocol_>" << endl <<
3403  indent() << "int32_t " << tstruct->get_name() <<
3404  "::read(Protocol_* iprot) {" << endl;
3405  } else {
3406  indent(out) <<
3407  "int32_t " << tstruct->get_name() <<
3408  "::read(boost::shared_ptr<contrail::sandesh::protocol::TProtocol> iprot) {" << endl;
3409  }
3410 
3411  generate_common_struct_reader_body(out, tstruct, pointers);
3412 
3413  indent(out) <<
3414  "}" << endl << endl;
3415 }
3416 
3424  t_struct* tstruct,
3425  bool pointers) {
3426  if (gen_templates_) {
3427  out <<
3428  indent() << "template <class Protocol_>" << endl <<
3429  indent() << "int32_t " << tstruct->get_name() <<
3430  "::write(Protocol_* oprot) const {" << endl;
3431  } else {
3432  indent(out) <<
3433  "int32_t " << tstruct->get_name() <<
3434  "::write(boost::shared_ptr<contrail::sandesh::protocol::TProtocol> oprot) const {" << endl;
3435  }
3436 
3437  generate_common_struct_writer_body(out, tstruct, pointers);
3438 
3439  indent(out) <<
3440  "}" << endl <<
3441  endl;
3442 }
3443 
3444 #ifdef SANDESH
3445 
3451 void t_cpp_generator::generate_struct_get_size(ofstream& out, const string& name,
3452  const vector<t_field*>& fields) {
3453  //Generate GetSize function to return size of sandesh
3454  indent(out) << "size_t " << name <<
3455  "::GetSize() const {" << endl;
3456  indent_up();
3457  indent(out) << "size_t size = 0;" << endl;
3458  vector<t_field*>::const_iterator f_iter;
3459  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3460  generate_get_size_field(out, *f_iter);
3461  }
3462  indent(out) << "return size;" << endl;
3463  indent_down();
3464  indent(out) << "}" << endl << endl;
3465 }
3466 
3473 void t_cpp_generator::generate_struct_logger(ofstream& out, const string& name,
3474  const vector<t_field*>& fields) {
3475  indent(out) << "std::string " << name <<
3476  "::log() const {" << endl;
3477  indent_up();
3478  out << indent() << "std::stringstream Xbuf;" << endl;
3479  vector<t_field*>::const_iterator f_iter;
3480  bool init = false;
3481  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3482  string prefix = "\" \" << ";
3483  if (!init) {
3484  init = true;
3485  prefix = "";
3486  }
3487  generate_logger_field(out, *f_iter, prefix, false, false);
3488  }
3489  if (!init) {
3490  out << indent() << "return std::string();" << endl;
3491  } else {
3492  out << indent() << "return Xbuf.str();" << endl;
3493  }
3494  indent_down();
3495  indent(out) << "}" << endl << endl;
3496 }
3497 
3504 void t_cpp_generator::generate_static_const_string_definition(ofstream& out,
3505  string name,
3506  const vector<t_field*>& fields) {
3507  vector<t_field*>::const_iterator f_iter;
3508  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3509  if (!((*f_iter)->get_type())->is_static_const_string()) {
3510  continue;
3511  }
3512  t_const_value* cv = (*f_iter)->get_value();
3513  assert(cv != NULL);
3514  out << base_type_name(t_base_type::TYPE_STRING) << " " << name <<
3515  "::";
3516  print_const_value(out, (*f_iter)->get_name(), (*f_iter)->get_type(), cv);
3517  }
3518 }
3519 
3526 void t_cpp_generator::generate_static_const_string_definition(ofstream& out,
3527  t_sandesh* tsandesh) {
3528  generate_static_const_string_definition(out, tsandesh->get_name(),
3529  tsandesh->get_sorted_members());
3530 }
3537 void t_cpp_generator::generate_static_const_string_definition(ofstream& out,
3538  t_struct* tstruct) {
3539  generate_static_const_string_definition(out, tstruct->get_name(),
3540  tstruct->get_sorted_members());
3541 }
3542 
3543 void t_cpp_generator::generate_sandesh_static_seqnum_def(ofstream& out,
3544  t_sandesh* tsandesh) {
3545  if (((t_base_type *)tsandesh->get_type())->is_sandesh_uve() ||
3546  ((t_base_type *)tsandesh->get_type())->is_sandesh_alarm()) {
3547  out << "tbb::atomic<uint32_t> " << tsandesh->get_name() << "::lseqnum_;" << endl;
3548  } else {
3549  out << "uint32_t " << tsandesh->get_name() << "::lseqnum_ = 1;" << endl;
3550  }
3551 }
3552 
3553 void t_cpp_generator::generate_sandesh_static_versionsig_def(ofstream& out,
3554  t_sandesh* tsandesh) {
3555  out << "uint32_t " << tsandesh->get_name() << "::versionsig_ = "
3556  << tsandesh->get_4byte_fingerprint() << "U;" << endl << endl;
3557 }
3558 
3559 void t_cpp_generator::generate_sandesh_static_rate_limit_buffer_def(
3560  ofstream& out, t_sandesh* tsandesh) {
3561  out << "boost::circular_buffer<time_t> " << tsandesh->get_name() <<
3562  "::rate_limit_buffer_(Sandesh::get_send_rate_limit());" << endl << endl;
3563 }
3564 
3565 void t_cpp_generator::generate_sandesh_static_rate_limit_mutex_def(
3566  ofstream& out,t_sandesh* tsandesh) {
3567  out << "tbb::mutex " << tsandesh->get_name() << "::rate_limit_mutex_; "
3568  << endl << endl;
3569 }
3570 
3571 void t_cpp_generator::generate_sandesh_static_rate_limit_log_def(
3572  ofstream& out, t_sandesh* tsandesh) {
3573  out << "bool " << tsandesh->get_name() << "::do_rate_limit_drop_log_ = true;"
3574  << endl << endl;
3575 }
3576 
3577 
3584 void t_cpp_generator::generate_sandesh_http_reader(ofstream& out,
3585  t_sandesh* tsandesh) {
3586  indent(out) << "#include <boost/tokenizer.hpp>" << endl;
3587  indent(out) << "#include <base/util.h>" << endl << endl;
3588  indent(out) << "bool " << tsandesh->get_name() << "::RequestFromHttp" <<
3589  "(const std::string& ctx, const std::string& snh_query) {" << endl;
3590 
3591  indent_up();
3592 
3593  const vector<t_field*>& fields = tsandesh->get_members();
3594  vector<t_field*>::const_iterator f_iter;
3595 
3596  indent(out) << program_name_ << "_marker = 0;" << endl;
3597  // Declare stack tmp variables
3598  out << endl <<
3599  indent() << "using std::string;" << endl <<
3600  indent() << "boost::char_separator<char> sep(\"&\");" << endl <<
3601  indent() << "boost::char_separator<char> varsep(\"=\");" << endl <<
3602  endl <<
3603  indent() << "CURL * cr = curl_easy_init();" <<
3604  indent() << "boost::tokenizer<boost::char_separator<char> >" <<
3605  "tokens(snh_query, sep);" << endl <<
3606  indent() << "boost::tokenizer<boost::char_separator<char> >" <<
3607  "::iterator it1 = tokens.begin();" << endl << endl;
3608 
3609  indent(out) << "string entity_name;" << endl;
3610  indent(out) << "int fields_vector_size =" << fields.size() << ";" << endl;
3611 
3612 
3613  // Required variables aren't in __isset, so we need tmp vars to check them.
3614  indent(out) << "for(int i =0; i < fields_vector_size; i++)" << endl;
3615  scope_up(out);
3616  indent(out) << "if (it1 != tokens.end())" << endl;
3617  scope_up(out);
3618  indent(out) << "string tok = (*it1++).c_str();" << endl ;
3619  indent(out) << "boost::tokenizer<boost::char_separator<char> >" <<
3620  " var(tok, varsep);" << endl;
3621  indent(out) << "boost::tokenizer<boost::char_separator<char> >" <<
3622  "::iterator it2 = var.begin();" << endl << endl;
3623 
3624  indent(out) << "string tok_new = (*it2).c_str();" << endl;
3625  indent(out) << "if (it2 != var.end()&& ++it2 != var.end()) " << endl;
3626  scope_up(out);
3627 
3628 
3629  indent(out) << "char *unescaped = NULL;" << endl;
3630  indent(out) << "unescaped = (char*) (malloc(sizeof(char)*1024));" <<endl;
3631 
3632  indent(out) << "std::string tmpstr;" << endl;
3633 
3634  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
3635  {
3636  t_type *ftype = (*f_iter)->get_type();
3637  if (ftype->is_base_type())
3638  {
3639  t_base_type *btype = static_cast<t_base_type *>(ftype);
3640  if (btype->is_string() || btype->is_xml())
3641  {
3642  indent(out) << "entity_name=\"" << (*f_iter)->get_name() << "\";" << endl;
3643  indent(out) << "if((tok_new.substr(0,(entity_name.length()))).compare(entity_name) == 0)" << endl;
3644  scope_up(out);
3645  indent(out) << "unescaped = curl_easy_unescape(cr, (*it2).c_str(), 0, NULL);" << endl;
3646  indent(out) << "tmpstr=unescaped;" << endl;
3647  indent(out) << (*f_iter)->get_name() << " = boost::lexical_cast<std::string>((tmpstr));" << endl;
3648  indent(out) << "curl_free(unescaped);" << endl;
3649  // delete[] unescaped;
3650  indent(out) << "continue;" << endl;
3651  scope_down(out);
3652  }
3653  else if (btype->is_uuid())
3654  {
3655  indent(out) << "entity_name=\"" << (*f_iter)->get_name() << "\";" << endl;
3656  indent(out) << "if((tok_new.substr(0,(entity_name.length()))).compare(entity_name) == 0)" << endl;
3657  scope_up(out);
3658  indent(out) << "std::stringstream ss;" << endl;
3659  indent(out) << "ss << *it2;" << endl;
3660  indent(out) << "ss >> " << (*f_iter)->get_name() << ";" << endl;
3661  indent(out) << "continue;" << endl;
3662  scope_down(out);
3663  }
3664  else if (btype->is_ipaddr())
3665  {
3666  indent(out) << "entity_name=\"" << (*f_iter)->get_name() << "\";" << endl;
3667  indent(out) << "if((tok_new.substr(0,(entity_name.length()))).compare(entity_name) == 0)" << endl;
3668  scope_up(out);
3669  indent(out) << "boost::system::error_code ec;" << endl;
3670  indent(out) << (*f_iter)->get_name() <<
3671  " = boost::asio::ip::address::from_string((*it2), ec);" << endl;
3672  indent(out) << "continue;" << endl;
3673  scope_down(out);
3674  }
3675  else
3676  {
3677  indent(out) << "entity_name=\"" << (*f_iter)->get_name() << "\";" << endl;
3678  indent(out) << "if((tok_new.substr(0,(entity_name.length()))).compare(entity_name) == 0)" << endl;
3679  scope_up(out);
3680  assert(btype->is_integer());
3681  indent(out) << "stringToInteger((*it2), " << (*f_iter)->get_name() << ");" << endl;
3682  indent(out) << "continue;" << endl;
3683  scope_down(out);
3684  }
3685  }
3686  else
3687  {
3688  // Ignore this field
3689  indent(out) << "++it2;" << endl;
3690  }
3691  }
3692  vector<t_field*>::const_iterator f_iter2 = fields.begin();
3693  if (f_iter2 != fields.end())
3694  {
3695  t_type *ftype = (*f_iter2)->get_type();
3696  if (ftype->is_base_type())
3697  {
3698  t_base_type *btype = static_cast<t_base_type *>(ftype);
3699  if (btype->is_string() || btype->is_xml())
3700  {
3701  indent(out) << "entity_name=\"" << (*f_iter2)->get_name() << "\";" << endl;
3702  indent(out) << "unescaped = curl_easy_unescape(cr, (*it2).c_str(), 0, NULL);" << endl;
3703  indent(out) << "tmpstr=unescaped;" << endl;
3704  indent(out) << (*f_iter2)->get_name() << " = boost::lexical_cast<std::string>((tmpstr));" << endl;
3705  indent(out) << "curl_free(unescaped);" << endl;
3706  indent(out) << "continue;" << endl;
3707 
3708  }
3709  else if (btype->is_uuid())
3710  {
3711  indent(out) << "entity_name=\"" << (*f_iter2)->get_name() << "\";" << endl;
3712  indent(out) << "std::stringstream ss;" << endl;
3713  indent(out) << "ss << *it2;" << endl;
3714  indent(out) << "ss >> " << (*f_iter2)->get_name() << ";" << endl;
3715  indent(out) << "continue;" << endl;
3716  }
3717  else if (btype->is_ipaddr())
3718  {
3719  indent(out) << "entity_name=\"" << (*f_iter2)->get_name() << "\";" << endl;
3720  indent(out) << "boost::system::error_code ec;" << endl;
3721  indent(out) << (*f_iter2)->get_name() <<
3722  " = boost::asio::ip::address::from_string((*it2), ec);" << endl;
3723  indent(out) << "continue;" << endl;
3724  }
3725  else
3726  {
3727  indent(out) << "entity_name=\"" << (*f_iter2)->get_name() << "\";" << endl;
3728  assert(btype->is_integer());
3729  indent(out) << "stringToInteger((*it2), " << (*f_iter2)->get_name() << ");" << endl;
3730  indent(out) << "continue;" << endl;
3731  }
3732  }
3733  }
3734  indent(out) << "free(unescaped);" << endl;
3735  scope_down(out);
3736  scope_down(out);
3737  scope_down(out);
3738 
3739 
3740  indent(out) << "set_context(ctx);" << endl;
3741  indent(out) << "curl_easy_cleanup(cr);" << endl;
3742  indent(out) << "return true;" << endl;
3743  indent_down();
3744  indent(out) << "}" << endl << endl;
3745 }
3746 
3747 
3754 void t_cpp_generator::generate_sandesh_updater(ofstream& out,
3755  t_sandesh* tsandesh) {
3756 
3757  const vector<t_field*>& fields = tsandesh->get_members();
3758  vector<t_field*>::const_iterator f_iter = fields.begin();
3759  assert((*f_iter)->get_name() == "data");
3760 
3761  bool periodic_ustruct = false;
3762 
3763  std::map<std::string, std::string>::iterator ait;
3764  ait = ((*f_iter)->get_type())->annotations_.find("period");
3765  if (ait != ((*f_iter)->get_type())->annotations_.end()) periodic_ustruct = true;
3766 
3767  string dtype = type_name((*f_iter)->get_type());
3768  t_type* t = get_true_type((*f_iter)->get_type());
3769  assert(t->is_struct());
3770 
3771  t_struct* ts = (t_struct*)t;
3772 
3773  map<string,DSInfo> dsinfo;
3774  map<string,set<string> > rawmap;
3775  derived_stats_info(ts, dsinfo, rawmap);
3776 
3777  std::map<string, CacheAttribute> cache_attrs;
3778  cache_attr_info(ts, cache_attrs);
3779 
3780  const vector<t_field*>& sfields = ts->get_members();
3781  vector<t_field*>::const_iterator s_iter;
3782 
3783  indent(out) << "bool " << tsandesh->get_name() <<
3784  "::LoadUVE(SendType stype, uint32_t cycle) {" << endl;
3785  indent_up();
3786  indent(out) << "(void)cycle;" << endl;
3787  indent(out) << "bool is_periodic_attr = false;" << endl << endl;
3788 
3789  for (s_iter = sfields.begin(); s_iter != sfields.end(); ++s_iter) {
3790  string snm = (*s_iter)->get_name();
3791  if (snm == "deleted") continue;
3792 
3793  // For non-derived stats, setting of attribute would have also set
3794  // the isset flag
3795  map<string,DSInfo>::const_iterator ds_iter = dsinfo.find(snm);
3796  if (ds_iter == dsinfo.end()) {
3797 
3798  CacheAttribute cat = (cache_attrs.find(snm))->second;
3799  if (cat == MANDATORY) continue;
3800 
3801  indent(out) << "if (data.__isset." << snm << ") {" << endl;
3802  indent_up();
3803  if (cat == HIDDEN) {
3804  indent(out) << "if (stype != ST_INTROSPECT) data.__isset." <<
3805  snm << " = false;" << endl;
3806  } else if (cat == INLINE) {
3807  indent(out) << "if (stype == ST_PERIODIC) " <<
3808  "data.__isset." << snm << " = false;" << endl;
3809  } else assert(0);
3810  indent_down();
3811  indent(out) << "}" << endl << endl;
3812  } else {
3813  indent(out) << "if (data.__dsobj_" << snm << "->IsResult()) {" << endl;
3814  indent_up();
3815  CacheAttribute cat = ds_iter->second.cat_;
3816  if (cat == HIDDEN) {
3817  indent(out) << "if (stype != ST_INTROSPECT) data.__isset." <<
3818  snm << " = false;" << endl;
3819  } else if (cat == HIDDEN_PER) {
3820  indent(out) << "if (stype == ST_PERIODIC) {" << endl;
3821  indent_up();
3822  indent(out) << "if (cycle % " << ds_iter->second.period_ <<
3823  " == 0) data.__dsobj_" << snm << "->Flush(data." <<
3824  snm << ");" << endl;
3825  indent(out) << "data.__isset." << snm << " = false;" << endl;
3826  indent_down();
3827  indent(out) << "} else if (stype == ST_SYNC) data.__isset." <<
3828  snm << " = false;" << endl;
3829  } else if (cat == INLINE) {
3830  indent(out) << "if (stype == ST_PERIODIC) " <<
3831  "data.__isset." << snm << " = false;" << endl;
3832  } else if (cat == PERIODIC) {
3833  indent(out) << "if (stype == ST_PERIODIC) {" << endl;
3834  indent_up();
3835 
3836  indent(out) << "if (cycle % " << ds_iter->second.period_ <<
3837  " == 0) {" << endl;
3838  indent_up();
3839 
3840  indent(out) << "data.__dsobj_" << snm << "->Flush(data." <<
3841  snm << ");" << endl;
3842  indent(out) << "data.__dsobj_" << snm << "->FillResult(data." <<
3843  snm << ", data.__isset." << snm << ", true);" << endl;
3844 
3845  indent_down();
3846  indent(out) << "} else data.__isset." << snm << " = false;" << endl;
3847 
3848  indent_down();
3849  indent(out) << "} else if (stype == ST_SYNC) data.__isset." <<
3850  snm << " = false;" << endl;
3851  } else assert(0);
3852 
3853  indent(out) << "else data.__dsobj_" << snm << "->FillResult(data." <<
3854  snm << ", data.__isset." << snm << ", true);" <<endl;
3855 
3856  if (cat == PERIODIC) {
3857  indent(out) << "is_periodic_attr |= data.__isset." << snm << ";" << endl;
3858  }
3859  indent_down();
3860  indent(out) << "}" << endl << endl;
3861  }
3862  }
3863  indent(out) << "if (stype == ST_PERIODIC) return ((is_periodic_attr) || (data.get_deleted()));" << endl;
3864  indent(out) << "else return true;" << endl;
3865  indent_down();
3866  indent(out) << "}" << endl << endl;
3867 
3868  indent(out) << "std::map<std::string, std::string> " << tsandesh->get_name() <<
3869  "::_DSConf(void) {" << endl;
3870  indent_up();
3871 
3872  bool is_dsconf = false;
3873  for (map<string,DSInfo>::const_iterator ds_iter = dsinfo.begin();
3874  ds_iter != dsinfo.end(); ++ds_iter) {
3875  if (!is_dsconf)
3876  indent(out) << "std::map<std::string, std::string> _dsconf = " <<
3877  "boost::assign::map_list_of" << endl;
3878  indent(out) << "(\"" << ds_iter->first << "\", \"" <<
3879  ds_iter->second.annotation_ << "\")" << endl;
3880  is_dsconf = true;
3881  }
3882  if (is_dsconf) indent(out) << ";" << endl;
3883  else indent(out) << "std::map<std::string, std::string> _dsconf;" << endl;
3884 
3885  indent(out) << "return _dsconf;" << endl;
3886  indent_down();
3887  indent(out) << "}" << endl << endl;
3888 
3889  indent(out) << "void " << tsandesh->get_name() <<
3890  "::_InitDerivedStats(" << dtype <<
3891  " & _data, const map<string,string> & _dsconf) {" << endl;
3892  indent_up();
3893 
3894  for (map<string,DSInfo>::const_iterator ds_iter = dsinfo.begin();
3895  ds_iter != dsinfo.end(); ++ds_iter) {
3896 
3897  indent(out) << "{" << endl;
3898  indent_up();
3899  indent(out) << "map<string,string>::const_iterator _dci = _dsconf.find(\"" <<
3900  ds_iter->first << "\");" << endl;
3901  if (ds_iter->second.rmtype_ == RM_AGG) {
3902  indent(out) << "bool is_agg = true;" << endl;
3903  } else {
3904  indent(out) << "bool is_agg = false;" << endl;
3905  }
3906  indent(out) << "assert(_dci != _dsconf.end());" << endl;
3907 
3908  indent(out) << "_data.__dsobj_" << ds_iter->first << ".reset();" << endl;
3909 
3910  if ((ds_iter->second.cat_ == PERIODIC) ||
3911  (ds_iter->second.cat_ == HIDDEN_PER)) {
3912 
3913  if (ds_iter->second.prealgo_.empty()) {
3914  indent(out) << "_data.__dsobj_" << ds_iter->first << " = boost::make_shared<" <<
3915  " ::contrail::sandesh::DerivedStatsPeriodicIf< ::contrail::sandesh::" <<
3916  ds_iter->second.algo_ << ", " <<
3917  ds_iter->second.rawtype_ << ", " <<
3918  ds_iter->second.resulttype_.substr(0, ds_iter->second.resulttype_.size() - 3) << ", " <<
3919  ds_iter->second.resulttype_ << "> >(_dci->second, is_agg);" << endl;
3920  } else {
3921  indent(out) << "_data.__dsobj_" << ds_iter->first << " = boost::make_shared<" <<
3922  " ::contrail::sandesh::DerivedStatsPeriodicAnomalyIf< ::contrail::sandesh::" <<
3923  ds_iter->second.algo_ << ", " <<
3924  ds_iter->second.rawtype_ << ", ::contrail::sandesh::" <<
3925  ds_iter->second.prealgo_ << ", " <<
3926  ds_iter->second.resulttype_ << "> >(_dci->second, is_agg);" << endl;
3927  }
3928  } else {
3929  indent(out) << "_data.__dsobj_" << ds_iter->first << " = boost::make_shared<" <<
3930  " ::contrail::sandesh::DerivedStatsIf< ::contrail::sandesh::" <<
3931  ds_iter->second.algo_ << ", " <<
3932  ds_iter->second.rawtype_ << ", " << ds_iter->second.resulttype_ <<
3933  "> >(_dci->second, is_agg);" << endl;
3934  }
3935  indent_down();
3936  indent(out) << "}" << endl;
3937  }
3938  indent_down();
3939  indent(out) << "}" << endl << endl;
3940 
3941  indent(out) << "bool " << tsandesh->get_name() <<
3942  "::UpdateUVE(" << dtype <<
3943  " & _data, " << dtype <<
3944  " & tdata, uint64_t mono_usec, SandeshLevel::type Xlevel) {" << endl;
3945 
3946  indent_up();
3947 
3948  indent(out) << "bool send = false;" << endl;
3949 
3950  for (s_iter = sfields.begin(); s_iter != sfields.end(); ++s_iter) {
3951  string snm = (*s_iter)->get_name();
3952 
3953  // Only set those attributes that are NOT derived stats results
3954  if (dsinfo.find(snm) == dsinfo.end()) {
3955  CacheAttribute cat = (cache_attrs.find(snm))->second;
3956  if ((*s_iter)->get_req() == t_field::T_OPTIONAL) {
3957  // don't send non-inline attributes
3958  if (cat != INLINE) {
3959  indent(out) << "if (_data.__isset." << snm << ") { _data.__isset." <<
3960  snm << " = false;" << endl;
3961  } else {
3962  indent(out) << "if (_data.__isset." << snm << ") { send = true;" << endl;
3963  }
3964  } else {
3965  if ((snm.compare("name") == 0) || (snm.compare("proxy") == 0)) {
3966  indent(out) << "{" << endl;
3967  } else {
3968  indent(out) << "{ send = true;" << endl;
3969  }
3970  }
3971  indent_up();
3972  indent(out) << "tdata.set_" << snm << "(_data.get_" <<
3973  snm << "());" << endl;
3974  map<string,set<string> >::const_iterator r_iter = rawmap.find(snm);
3975  // Update all derivied stats of this raw attribute
3976  if (r_iter != rawmap.end()) {
3977  t_type* ratype = (*s_iter)->get_type();
3978  if (ratype->is_map()) {
3979  t_type* vtype = ((t_map*)ratype)->get_val_type();
3980  indent(out) << "typedef " << type_name((*s_iter)->get_type()) <<
3981  " _T_" << snm << ";" << endl;
3982  indent(out) << "std::map<string,bool> _delmap_" << snm
3983  << ";" << endl;
3984  indent(out) << "BOOST_FOREACH(const _T_" << snm <<
3985  "::value_type& _tp, _data.get_" << snm << "())" << endl;
3986  indent(out) << " _delmap_" << snm <<
3987  ".insert(make_pair(_tp.first, SandeshStructDeleteTrait<" <<
3988  type_name(vtype) << ">::get(_tp.second)));" << endl;
3989  }
3990  set<string>::const_iterator d_iter;
3991  for (d_iter = r_iter->second.begin(); d_iter != r_iter->second.end(); ++d_iter) {
3992  map<string,DSInfo>::const_iterator c_iter = dsinfo.find(*d_iter);
3993  CacheAttribute dat = c_iter->second.cat_;
3994 
3995  if (c_iter->second.compattr_.empty()) {
3996  if (!c_iter->second.is_map_) {
3997  indent(out) << "tdata.__dsobj_" << *d_iter <<
3998  "->Update(_data.get_" << snm << "(), mono_usec);" << endl;
3999  } else {
4000  indent(out) << "tdata.__dsobj_" << *d_iter <<
4001  "->Update(_data.get_" << snm << "(), _delmap_" <<
4002  snm << ", mono_usec);" << endl;
4003  }
4004  } else {
4005  string getexpr = string("get_") + c_iter->second.compattr_ +
4006  string("()");
4007  if (!c_iter->second.subcompattr_.empty()) {
4008  getexpr += string(".get_") + c_iter->second.subcompattr_ +
4009  string("()");
4010  }
4011  if (!c_iter->second.is_map_) {
4012  indent(out) << "tdata.__dsobj_" << *d_iter << "->Update(_data.get_" <<
4013  snm << "()." << getexpr << ", mono_usec);" << endl;
4014  } else {
4015  indent(out) << "std::map<string," << c_iter->second.rawtype_ << "> temp_" <<
4016  *d_iter << ";" << endl;
4017  indent(out) << "BOOST_FOREACH(const _T_" << snm <<
4018  "::value_type& _tp, _data.get_" << snm << "()) {" << endl;
4019  indent_up();
4020  indent(out) << "temp_" << *d_iter <<
4021  ".insert(make_pair(_tp.first, _tp.second." <<
4022  getexpr << "));" << endl;
4023  indent_down();
4024  indent(out) << "}" << endl;
4025  indent(out) << "tdata.__dsobj_" << *d_iter << "->Update(temp_" <<
4026  *d_iter << ", _delmap_" << snm << ", mono_usec);" << endl;
4027  indent(out) << "temp_" << *d_iter << ".clear();" << endl;
4028  }
4029  }
4030  // If the DS is inline or mandatory
4031  if (dat == INLINE) {
4032  indent(out) << "tdata.__dsobj_" << *d_iter << "->FillResult(_data." <<
4033  *d_iter << ", _data.__isset." << *d_iter << ");" << endl;
4034  indent(out) << "if (_data.__isset." << *d_iter <<") send = true;" << endl;
4035  }
4036  }
4037  }
4038 
4039  indent_down();
4040  indent(out) << "}" << endl << endl;
4041  }
4042  }
4043  if (!periodic_ustruct) {
4044  indent(out) << "send = true;" << endl;
4045  }
4046  indent(out) << "return send;" << endl;
4047  indent_down();
4048  indent(out) << "}" << endl << endl;
4049 
4050  f_iter++;
4051  assert(f_iter == fields.end());
4052 }
4053 
4060 void t_cpp_generator::generate_sandesh_reader(ofstream& out,
4061  t_sandesh* tsandesh) {
4062  indent(out) <<
4063  "int32_t " << tsandesh->get_name() <<
4064  "::Read(boost::shared_ptr<contrail::sandesh::protocol::TProtocol> iprot) {"
4065  << endl;
4066 
4067  generate_common_struct_reader_body(out, tsandesh, false);
4068 
4069  indent(out) <<
4070  "}" << endl << endl;
4071 }
4072 
4079 void t_cpp_generator::generate_sandesh_writer(ofstream& out,
4080  t_sandesh* tsandesh) {
4081  indent(out) <<
4082  "int32_t " << tsandesh->get_name() <<
4083  "::Write(boost::shared_ptr<contrail::sandesh::protocol::TProtocol> oprot) const {" <<
4084  endl;
4085 
4086  generate_common_struct_writer_body(out, tsandesh, false);
4087 
4088  indent(out) <<
4089  "}" << endl <<
4090  endl;
4091 }
4092 
4100 void t_cpp_generator::generate_sandesh_uve_creator(
4101  std::ofstream& out, t_sandesh* tsandesh) {
4102  const vector<t_field*>& fields = tsandesh->get_members();
4103  vector<t_field*>::const_iterator f_iter = fields.begin();
4104  assert((*f_iter)->get_name() == "data");
4105 
4106  bool is_proxy = false;
4107  std::map<std::string, std::string>::iterator ait;
4108  ait = ((*f_iter)->get_type())->annotations_.find("period");
4109 
4110  std::string sname = tsandesh->get_name();
4111  indent(out) << "SANDESH_UVE_DEF(" << sname << "," <<
4112  type_name((*f_iter)->get_type());
4113 
4114  if (ait == ((*f_iter)->get_type())->annotations_.end()) {
4115  indent(out) << ", 0, 0);" << endl;
4116  } else {
4117  std::map<std::string, std::string>::iterator tmit;
4118  tmit = ((*f_iter)->get_type())->annotations_.find("timeout");
4119  if (tmit == ((*f_iter)->get_type())->annotations_.end()) {
4120  indent(out) << ", " << atoi(ait->second.c_str()) << ", 0);" << endl;
4121  } else {
4122  indent(out) << ", " << atoi(ait->second.c_str()) << ", " <<
4123  atoi(tmit->second.c_str()) << ");" << endl;
4124  is_proxy = true;
4125  }
4126  }
4127 
4128  indent(out) << "void " << sname <<
4129  "::Send(const " << type_name((*f_iter)->get_type()) <<
4130  "& cdata, SandeshLevel::type Xlevel, SandeshUVE::SendType stype," <<
4131  " uint32_t seqno, uint32_t cycle, std::string ctx) {" << endl;
4132  indent_up();
4133  indent(out) << sname << " *snh = new " << sname << "(seqno, cdata);" << endl;
4134  indent(out) << "snh->set_level(Xlevel);" << endl;
4135  indent(out) << "if (snh->LoadUVE(stype, cycle)) {" << endl;
4136  indent_up();
4137  indent(out) << "snh->set_context(ctx); snh->set_more(!ctx.empty());" << endl;
4138  indent(out) << "if (stype == SandeshUVE::ST_SYNC) snh->set_hints(snh->hints() | " <<
4139  "g_sandesh_constants.SANDESH_SYNC_HINT);" << endl;
4140  indent(out) << "snh->Dispatch();" << endl;
4141  indent_down();
4142  indent(out) << "} else snh->Release();" << endl;
4143  indent_down();
4144  indent(out) << "}" << endl << endl;
4145  // Generate legacy
4146  indent(out) << "void " << sname <<
4147  "::Send(const " << type_name((*f_iter)->get_type()) <<
4148  "& cdata, SandeshUVE::SendType stype, uint32_t seqno," <<
4149  " uint32_t cycle, std::string ctx) {" << endl;
4150  indent_up();
4151  indent(out) << sname << " *snh = new " << sname << "(seqno, cdata);" << endl;
4152  indent(out) << "snh->set_level(SandeshLevel::SYS_NOTICE);" << endl;
4153  indent(out) << "if (snh->LoadUVE(stype, cycle)) {" << endl;
4154  indent_up();
4155  indent(out) << "snh->set_context(ctx); snh->set_more(!ctx.empty());" << endl;
4156  indent(out) << "if (stype == SandeshUVE::ST_SYNC) snh->set_hints(snh->hints() | " <<
4157  "g_sandesh_constants.SANDESH_SYNC_HINT);" << endl;
4158  indent(out) << "snh->Dispatch();" << endl;
4159  indent_down();
4160  indent(out) << "} else snh->Release();" << endl;
4161  indent_down();
4162  indent(out) << "}" << endl << endl;
4163 
4164  if (is_proxy) {
4165  indent(out) << "void " << sname <<
4166  "::Send(const " << type_name((*f_iter)->get_type()) <<
4167  "& data, SandeshLevel::type Xlevel, std::string table, " <<
4168  "uint64_t mono_usec, int partition) {" << endl;
4169  indent_up();
4170  } else {
4171  indent(out) << "void " << sname <<
4172  "::Send(const " << type_name((*f_iter)->get_type()) <<
4173  "& data, SandeshLevel::type Xlevel, std::string table, " <<
4174  "uint64_t mono_usec) {" << endl;
4175  indent_up();
4176  indent(out) << "int partition = -1;" << endl;
4177  }
4178 
4179  indent(out) << type_name((*f_iter)->get_type()) <<
4180  " & cdata = const_cast<" << type_name((*f_iter)->get_type()) <<
4181  " &>(data);" << endl;
4182  indent(out) << "uint32_t msg_seqno = lseqnum_.fetch_and_increment() + 1;" << endl;
4183  indent(out) << "if (!table.empty()) cdata.table_ = table;" << endl;
4184  indent(out) << "if (uvemap" << sname <<
4185  ".UpdateUVE(cdata, msg_seqno, mono_usec, partition, Xlevel)) {" << endl;
4186  indent_up();
4187  indent(out) << sname << " *snh = new " << sname << "(msg_seqno, cdata);" << endl;
4188  indent(out) << "snh->set_level(Xlevel);" << endl;
4189  indent(out) << "snh->Dispatch();" << endl;
4190  indent_down();
4191  indent(out) << "}" << endl;
4192 
4193  indent_down();
4194  indent(out) << "}" << endl << endl;
4195  // Generate legacy
4196  if (is_proxy) {
4197  indent(out) << "void " << sname <<
4198  "::Send(const " << type_name((*f_iter)->get_type()) <<
4199  "& data, std::string table, " <<
4200  "uint64_t mono_usec, int partition) {" << endl;
4201  indent_up();
4202  } else {
4203  indent(out) << "void " << sname <<
4204  "::Send(const " << type_name((*f_iter)->get_type()) <<
4205  "& data, std::string table, " <<
4206  "uint64_t mono_usec) {" << endl;
4207  indent_up();
4208  indent(out) << "int partition = -1;" << endl;
4209  }
4210 
4211  indent(out) << type_name((*f_iter)->get_type()) <<
4212  " & cdata = const_cast<" << type_name((*f_iter)->get_type()) <<
4213  " &>(data);" << endl;
4214  indent(out) << "uint32_t msg_seqno = lseqnum_.fetch_and_increment() + 1;" << endl;
4215  indent(out) << "if (!table.empty()) cdata.table_ = table;" << endl;
4216  indent(out) << "if (uvemap" << sname <<
4217  ".UpdateUVE(cdata, msg_seqno, mono_usec, partition, SandeshLevel::SYS_NOTICE)) {" << endl;
4218  indent_up();
4219  indent(out) << sname << " *snh = new " << sname << "(msg_seqno, cdata);" << endl;
4220  indent(out) << "snh->set_level(SandeshLevel::SYS_NOTICE);" << endl;
4221  indent(out) << "snh->Dispatch();" << endl;
4222  indent_down();
4223  indent(out) << "}" << endl;
4224 
4225  indent_down();
4226  indent(out) << "}" << endl << endl;
4227 }
4228 
4235 void t_cpp_generator::generate_sandesh_creator(ofstream& out,
4236  t_sandesh* tsandesh) {
4237  const t_type *t = tsandesh->get_type();
4238  assert(t->is_base_type());
4239 
4240  // Creator function name
4241  if (((t_base_type *)t)->is_sandesh_request()) {
4242  indent(out) << "extern int " << program_name_ << "_marker;" << endl;
4243  // Request registration
4244  indent(out) << "SANDESH_REGISTER_DEF_TYPE(" << tsandesh->get_name() <<
4245  ");" << endl << endl;
4246  return;
4247  } else if (((t_base_type *)t)->is_sandesh_trace() ||
4248  ((t_base_type *)t)->is_sandesh_trace_object()) {
4249  generate_sandesh_trace(out, tsandesh);
4250  return;
4251  } else if (((t_base_type *)t)->is_sandesh_buffer()) {
4252  // Buffer registration
4253  indent(out) << "SANDESH_REGISTER_DEF_TYPE(" << tsandesh->get_name() <<
4254  ");" << endl << endl;
4255  return;
4256  } else if (((t_base_type *)t)->is_sandesh_uve() ||
4257  ((t_base_type *)t)->is_sandesh_alarm()) {
4258  generate_sandesh_uve_creator(out, tsandesh);
4259  return;
4260  }
4261  return;
4262 }
4263 
4267 void t_cpp_generator::generate_get_size_field(ofstream& out, t_field *tfield) {
4268  t_type* type = get_true_type(tfield->get_type());
4269  string name = tfield->get_name();
4270  // Handle optional elements
4271  if (tfield->get_req() == t_field::T_OPTIONAL) {
4272  out << indent() << "if (__isset." << name << ") {" <<
4273  endl;
4274  indent_up();
4275  }
4276  if (type->is_struct()) {
4277  generate_get_size_struct(out, (t_struct *)type, name);
4278  } else if (type->is_container()) {
4279  generate_get_size_container(out, type, name);
4280  } else if (type->is_string() || type->is_xml() ||
4281  type->is_static_const_string()) {
4282  out << indent() << "size += " << name << ".length();" << endl;
4283  } else {
4284  out << indent() << "size += sizeof(" + name +");" << endl;
4285  }
4286  // Handle optional elements
4287  if (tfield->get_req() == t_field::T_OPTIONAL) {
4288  indent_down();
4289  out << indent() << "}" << endl;
4290  }
4291 }
4292 
4296 void t_cpp_generator::generate_logger_field(ofstream& out,
4297  t_field *tfield,
4298  string prefix,
4299  bool log_value_only,
4300  bool no_name_log,
4301  bool for_sandesh) {
4302  t_type* type = get_true_type(tfield->get_type());
4303  string name = tfield->get_name();
4304  // Handle optional elements
4305  if (tfield->get_req() == t_field::T_OPTIONAL) {
4306  if (for_sandesh) {
4307  return;
4308  }
4309  out << indent() << "if (__isset." << name << ") {" <<
4310  endl;
4311  indent_up();
4312  }
4313  if (type->is_struct()) {
4314  if (no_name_log) {
4315  out << indent() << "Xbuf << " << prefix << "\"[ \";" << endl;
4316  } else {
4317  out << indent() << "Xbuf << " << prefix << "\"" << name << "\"" << " << \"= [ \";" << endl;
4318  }
4319  generate_logger_struct(out, (t_struct *)type, prefix, name);
4320  out << indent() << "Xbuf << " << "\" ]\";" << endl;
4321  } else if (type->is_container()) {
4322  if (no_name_log) {
4323  out << indent() << "Xbuf << " << prefix << "\"[ \";" << endl;
4324  } else {
4325  out << indent() << "Xbuf << " << prefix << "\"" << name << "\"" << " << \"= [ \";" << endl;
4326  }
4327  generate_logger_container(out, type, name, log_value_only);
4328  out << indent() << "Xbuf << " << "\" ]\";" << endl;
4329  } else if (type->is_base_type() || type->is_enum()) {
4330  t_base_type *tbase = static_cast<t_base_type *>(type);
4331  if (log_value_only) {
4332  if (tbase->is_integer()) {
4333  out << indent() << "Xbuf << " << prefix <<
4334  "integerToString(" << name <<
4335  ");" << endl;
4336  } else {
4337  out << indent() << "Xbuf << " << prefix <<
4338  name << ";" << endl;
4339  }
4340  } else {
4341  if (tbase->is_integer()) {
4342  out << indent() << "Xbuf << " << prefix <<
4343  "\"" << name << "\"" <<
4344  " << \" = \" << integerToString(" << name <<
4345  ");" << endl;
4346  } else {
4347  if (tbase->get_name() == "ipv4") {
4348  scope_up(out);
4349  out << indent() << "struct in_addr ip_addr_"<< name <<";" << endl;
4350  out << indent() << "ip_addr_" << name << ".s_addr = htonl(" << name << ");" << endl;
4351  out << indent() << "Xbuf << " << prefix <<
4352  "\"" << name << "\"" <<
4353  " << \" = \" << inet_ntoa(ip_addr_" << name << ");" << endl;
4354  scope_down(out);
4355  }
4356  else {
4357  out << indent() << "Xbuf << " << prefix <<
4358  "\"" << name << "\"" <<
4359  " << \" = \" << " << name <<
4360  ";" << endl;
4361  }
4362  }
4363  }
4364  }
4365  // Handle optional elements
4366  if (tfield->get_req() == t_field::T_OPTIONAL) {
4367  indent_down();
4368  out << indent() << "}" << endl;
4369  }
4370 }
4371 
4375 void t_cpp_generator::generate_get_size_container(ofstream& out,
4376  t_type* ttype,
4377  string name) {
4378  scope_up(out);
4379  string iter = tmp("_iter");
4380  out << indent() << type_name(ttype) << "::const_iterator " << iter
4381  << ";" << endl;
4382  out << indent() << "for (" << iter << " = " << name << ".begin(); "
4383  << iter << " != " << name << ".end(); ++" << iter << ")" << endl;
4384  scope_up(out);
4385  if (ttype->is_map()) {
4386  generate_get_size_map_element(out, (t_map *)ttype, iter);
4387  } else if(ttype->is_set()) {
4388  generate_get_size_set_element(out, (t_set *)ttype, iter);
4389  } else if(ttype->is_list()) {
4390  generate_get_size_list_element(out, (t_list *)ttype, iter);
4391  }
4392  scope_down(out);
4393  scope_down(out);
4394 }
4395 
4399 void t_cpp_generator::generate_get_size_map_element(ofstream& out,
4400  t_map* tmap,
4401  string iter) {
4402  t_field kfield(tmap->get_key_type(), iter + "->first");
4403  generate_get_size_field(out, &kfield);
4404  t_field vfield(tmap->get_val_type(), iter + "->second");
4405  generate_get_size_field(out, &vfield);
4406 }
4407 
4411 void t_cpp_generator::generate_get_size_list_element(ofstream& out,
4412  t_list* tlist,
4413  string iter) {
4414  t_field efield(tlist->get_elem_type(), "(*" + iter + ")");
4415  generate_get_size_field(out, &efield);
4416 }
4417 
4421 void t_cpp_generator::generate_get_size_set_element(ofstream& out,
4422  t_set* tset,
4423  string iter) {
4424  t_field efield(tset->get_elem_type(), "(*" + iter + ")");
4425  generate_get_size_field(out, &efield);
4426 }
4427 
4431 void t_cpp_generator::generate_logger_container(ofstream& out,
4432  t_type* ttype,
4433  string name,
4434  bool log_value_only) {
4435  scope_up(out);
4436  string iter = tmp("_iter");
4437  string prefix = "\" \" << ";
4438  out << indent() << "Xbuf << " << prefix << "\"[\";" << endl;
4439  out <<
4440  indent() << type_name(ttype) << "::const_iterator " << iter << ";" << endl <<
4441  indent() << "for (" << iter << " = " << name << ".begin(); " << iter << " != " << name << ".end(); ++" << iter << ")" << endl;
4442  scope_up(out);
4443  if (ttype->is_map()) {
4444  generate_logger_map_element(out, (t_map*)ttype, iter, log_value_only);
4445  } else if (ttype->is_set()) {
4446  generate_logger_set_element(out, (t_set*)ttype, iter, log_value_only);
4447  } else if (ttype->is_list()) {
4448  generate_logger_list_element(out, (t_list*)ttype, iter, log_value_only);
4449  }
4450  out << indent() << "Xbuf << " << "\", \";" << endl;
4451  scope_down(out);
4452  out << indent() << "Xbuf << " << prefix << "\"]\";" << endl;
4453  scope_down(out);
4454 }
4455 
4459 void t_cpp_generator::generate_logger_map_element(ofstream& out,
4460  t_map* tmap,
4461  string iter,
4462  bool log_value_only) {
4463  string prefix = "\" \" << ";
4464  t_field kfield(tmap->get_key_type(), iter + "->first");
4465  generate_logger_field(out, &kfield, prefix, log_value_only, true);
4466  t_field vfield(tmap->get_val_type(), iter + "->second");
4467  generate_logger_field(out, &vfield, prefix, log_value_only, true);
4468 }
4469 
4473 void t_cpp_generator::generate_logger_set_element(ofstream& out,
4474  t_set* tset,
4475  string iter,
4476  bool log_value_only) {
4477  string prefix = "\" \" << ";
4478  t_field efield(tset->get_elem_type(), "(*" + iter + ")");
4479  generate_logger_field(out, &efield, prefix, log_value_only, true);
4480 }
4481 
4485 void t_cpp_generator::generate_logger_list_element(ofstream& out,
4486  t_list* tlist,
4487  string iter,
4488  bool log_value_only) {
4489  string prefix = "\" \" << ";
4490  t_field efield(tlist->get_elem_type(), "(*" + iter + ")");
4491  generate_logger_field(out, &efield, prefix, log_value_only, true);
4492 }
4493 
4497 void t_cpp_generator::generate_get_size_struct(ofstream& out,
4498  t_struct *tstruct,
4499  string name) {
4500  (void) tstruct;
4501  out << indent() << "size += " << name << ".GetSize();" << endl;
4502 }
4503 
4507 void t_cpp_generator::generate_logger_struct(ofstream& out,
4508  t_struct *tstruct,
4509  string prefix,
4510  string name) {
4511  (void) tstruct;
4512  out << indent() << "Xbuf << " << prefix << name << ".log();" << endl;
4513 }
4514 
4521 void t_cpp_generator::generate_sandesh_static_drop_logger(ofstream &out,
4522  t_sandesh *tsandesh, bool generate_sandesh_object) {
4523  // Generate DropLog
4524  if (generate_sandesh_object) {
4525  out << indent() << "static void DropLog(const std::string& " <<
4526  "drop_reason, std::string category, SandeshLevel::type level, " <<
4527  tsandesh->get_name() << " *snh) {" << endl;
4528  } else {
4529  out << indent() << "static void DropLog" <<
4530  generate_sandesh_async_creator(tsandesh, true, false, false, "", "",
4531  false, false, true) << " {" << endl;
4532  }
4533  indent_up();
4534  out << indent() << "log4cplus::LogLevel Xlog4level(" <<
4535  "SandeshLevelTolog4Level(SandeshLevel::SYS_ERR));" << endl;
4536  out << indent() <<
4537  "log4cplus::Logger Xlogger = Sandesh::logger();" << endl;
4538  out << indent() <<
4539  "if (!Xlogger.isEnabledFor(Xlog4level)) {" << endl;
4540  indent_up();
4541  out << indent() << "return;" << endl;
4542  scope_down(out);
4543  out << indent() << "log4cplus::tostringstream Xbuf;" << endl;
4544  // Only systemlog, objectlog, flowlog, and UVE have valid level
4545  // and category
4546  if (tsandesh->is_level_category_supported()) {
4547  if (generate_sandesh_object) {
4548  out << indent() << "Xbuf << drop_reason << snh->ToString();"
4549  << endl;
4550  } else {
4551  out << indent() << "Xbuf << drop_reason << category << " <<
4552  "\" [\" << LevelToString(level) << \"]: " <<
4553  tsandesh->get_name() << ": \";" << endl;
4554  }
4555  } else {
4556  assert(!generate_sandesh_object);
4557  out << indent() << "Xbuf << drop_reason << \"" <<
4558  tsandesh->get_name() << ": \";" << endl;
4559  }
4560 
4561  bool is_system =
4562  ((t_base_type *)tsandesh->get_type())->is_sandesh_system();
4563  bool is_trace =
4564  ((t_base_type *)tsandesh->get_type())->is_sandesh_trace();
4565  bool log_value_only = is_system || is_trace;
4566  bool init = false;
4567  string prefix;
4568  const vector<t_field*>& fields = tsandesh->get_members();
4569  vector<t_field*>::const_iterator f_iter;
4570  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4571  if (init) {
4572  prefix = "\" \" << ";
4573  } else {
4574  init = true;
4575  }
4576  if (!generate_sandesh_object) {
4577  generate_logger_field(out, *f_iter, prefix, log_value_only, false,
4578  true);
4579  }
4580  }
4581  out << indent() << "Xlogger.forcedLog(Xlog4level, Xbuf.str());" <<
4582  endl;
4583  indent_down();
4584  indent(out) << "}" << endl << endl;
4585 }
4586 
4587 void t_cpp_generator::generate_sandesh_static_logger(ofstream &out,
4588  t_sandesh *tsandesh, bool generate_sandesh_object) {
4589  // Generate Log
4590  if (generate_sandesh_object) {
4591  out << indent() << "static void Log(std::string category, " <<
4592  "SandeshLevel::type level, " << tsandesh->get_name() <<
4593  " *snh) {" << endl;
4594  } else {
4595  out << indent() << "static void Log" <<
4596  generate_sandesh_async_creator(tsandesh, true, false, false, "", "",
4597  false, false, false) << " {" << endl;
4598  }
4599  indent_up();
4600  out << indent() <<
4601  "if (!IsLevelCategoryLoggingAllowed(" <<
4602  generate_sandesh_base_name(tsandesh, true) <<
4603  ", level, category)) {" << endl;
4604  indent_up();
4605  out << indent() << "return;" << endl;
4606  scope_down(out);
4607  out << indent() << "log4cplus::LogLevel Xlog4level(" <<
4608  "SandeshLevelTolog4Level(level));" << endl;
4609  out << indent() <<
4610  "log4cplus::Logger Xlogger = Sandesh::logger();" << endl;
4611  out << indent() <<
4612  "if (!Xlogger.isEnabledFor(Xlog4level)) {" << endl;
4613  indent_up();
4614  out << indent() << "return;" << endl;
4615  scope_down(out);
4616  out << indent() << "log4cplus::tostringstream Xbuf;" << endl;
4617  // Only systemlog, objectlog, flowlog, and UVE have valid level
4618  // and category
4619  if (tsandesh->is_level_category_supported()) {
4620  if (generate_sandesh_object) {
4621  out << indent() << "Xbuf << snh->ToString();" << endl;
4622  } else {
4623  out << indent() << "Xbuf << category << " <<
4624  "\" [\" << LevelToString(level) << \"]: " <<
4625  tsandesh->get_name() << ": \";" << endl;
4626  }
4627  } else {
4628  assert(!generate_sandesh_object);
4629  out << indent() << "Xbuf << \"" <<
4630  tsandesh->get_name() << ": \";" << endl;
4631  }
4632 
4633  bool is_system =
4634  ((t_base_type *)tsandesh->get_type())->is_sandesh_system();
4635  bool is_trace =
4636  ((t_base_type *)tsandesh->get_type())->is_sandesh_trace();
4637  bool log_value_only = is_system || is_trace;
4638  bool init = false;
4639  string prefix;
4640  const vector<t_field*>& fields = tsandesh->get_members();
4641  vector<t_field*>::const_iterator f_iter;
4642  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4643  if (init) {
4644  prefix = "\" \" << ";
4645  } else {
4646  init = true;
4647  }
4648  if (!generate_sandesh_object) {
4649  generate_logger_field(out, *f_iter, prefix, log_value_only, false,
4650  true);
4651  }
4652  }
4653  out << indent() << "Xlogger.forcedLog(Xlog4level, Xbuf.str());" <<
4654  endl;
4655  indent_down();
4656  indent(out) << "}" << endl << endl;
4657 }
4658 
4666 void t_cpp_generator::generate_sandesh_logger(ofstream &out,
4667  t_sandesh *tsandesh,
4668  sandesh_logger::type ltype) {
4669  if (ltype == sandesh_logger::BUFFER) {
4670  indent(out) << "std::string " << tsandesh->get_name() <<
4671  "::ToString() const {" << endl;
4672  indent_up();
4673  } else if (ltype == sandesh_logger::LOG) {
4674  indent(out) << "void " << tsandesh->get_name() <<
4675  "::Log() const {" << endl;
4676  indent_up();
4677  } else if (ltype == sandesh_logger::FORCED_LOG) {
4678  indent(out) << "void " << tsandesh->get_name() <<
4679  "::ForcedLog() const {" << endl;
4680  indent_up();
4681  } else {
4682  assert(0);
4683  }
4684  const vector<t_field*>& fields = tsandesh->get_members();
4685  vector<t_field*>::const_iterator f_iter;
4686  bool init = false;
4687  bool log_value_only =
4688  ((t_base_type *)tsandesh->get_type())->is_sandesh_system() ||
4689  ((t_base_type *)tsandesh->get_type())->is_sandesh_trace();
4690  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4691  string prefix = "\" \" << ";
4692  // Handle init
4693  if (!init) {
4694  init = true;
4695  string category_str = "Sandesh::category()";
4696  string level_str = "Sandesh::level()";
4697  if (ltype == sandesh_logger::LOG) {
4698  out << indent() << "if (!IsLevelCategoryLoggingAllowed(" <<
4699  generate_sandesh_base_name(tsandesh, true) << ", " <<
4700  level_str << ", " << category_str << ")) {" << endl;
4701  indent_up();
4702  out << indent() << "return;" << endl;
4703  scope_down(out);
4704  out << indent() << "log4cplus::LogLevel Xlog4level(" <<
4705  "SandeshLevelTolog4Level(" << level_str << "));" << endl;
4706  out << indent() <<
4707  "log4cplus::Logger Xlogger = Sandesh::logger();" << endl;
4708  out << indent() <<
4709  "if (!Xlogger.isEnabledFor(Xlog4level)) {" << endl;
4710  indent_up();
4711  out << indent() << "return;" << endl;
4712  scope_down(out);
4713  out << indent() << "log4cplus::tostringstream Xbuf;" << endl;
4714  } else if (ltype == sandesh_logger::FORCED_LOG) {
4715  out << indent() << "log4cplus::LogLevel Xlog4level(" <<
4716  "SandeshLevelTolog4Level(" << level_str << "));" << endl;
4717  out << indent() <<
4718  "log4cplus::Logger Xlogger = Sandesh::logger();" << endl;
4719  out << indent() << "log4cplus::tostringstream Xbuf;" << endl;
4720  } else if (ltype == sandesh_logger::BUFFER) {
4721  out << indent() << "std::stringstream Xbuf;" << endl;
4722  // Timestamp
4723  out << indent() <<
4724  "Xbuf << integerToString(timestamp()) << \" \";" <<
4725  endl;
4726  }
4727  prefix = "";
4728  // Only systemlog, objectlog, and flowlog have valid level and category
4729  if (tsandesh->is_level_category_supported()) {
4730  out << indent() << "Xbuf << " << category_str <<
4731  " << \" [\" << LevelToString(" << level_str << ") << \"]: "
4732  << tsandesh->get_name() << ": \";" << endl;
4733  } else {
4734  out << indent() << "Xbuf << \"" << tsandesh->get_name() <<
4735  ": \";" << endl;
4736  }
4737  }
4738  generate_logger_field(out, *f_iter, prefix, log_value_only, false);
4739  }
4740  if (init) {
4741  if (ltype == sandesh_logger::BUFFER) {
4742  out << indent() << "return Xbuf.str();" << endl;
4743  } else {
4744  out << indent() << "Xlogger.forcedLog(Xlog4level, Xbuf.str());" <<
4745  endl;
4746  }
4747  } else {
4748  if (ltype == sandesh_logger::BUFFER) {
4749  out << indent() << "return std::string();" << endl;
4750  }
4751  }
4752  indent_down();
4753  indent(out) << "}" << endl << endl;
4754 }
4755 
4762 void t_cpp_generator::generate_sandesh_get_size(ofstream& out,
4763  t_sandesh* tsandesh) {
4764  //Generate GetSize function to return size of sandesh
4765  indent(out) << "size_t " << tsandesh->get_name() <<
4766  "::GetSize() const {" << endl;
4767  indent_up();
4768  indent(out) << "size_t size = 0;" << endl;
4769  const vector<t_field*>& fields = tsandesh->get_members();
4770  vector<t_field*>::const_iterator f_iter;
4771  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4772  generate_get_size_field(out, *f_iter);
4773  }
4774  indent(out) << "return size;" << endl;
4775  indent_down();
4776  indent(out) << "}" << endl << endl;
4777 }
4778 
4785 void t_cpp_generator::generate_sandesh_loggers(ofstream& out,
4786  t_sandesh* tsandesh) {
4787  // Generate Log printing to log4cplus
4788  generate_sandesh_logger(out, tsandesh, sandesh_logger::LOG);
4789  // Generate forcedLog printing to log4cplus
4790  generate_sandesh_logger(out, tsandesh, sandesh_logger::FORCED_LOG);
4791  // Generate Log printing to buffer
4792  generate_sandesh_logger(out, tsandesh, sandesh_logger::BUFFER);
4793 }
4794 
4801 void t_cpp_generator::generate_sandesh_trace(ofstream& out,
4802  t_sandesh* tsandesh) {
4803  std::string creator_name = "trace_sandesh";
4804  indent(out) << "void " << tsandesh->get_name() << "::TraceMsg" <<
4805  generate_sandesh_no_static_const_string_function(tsandesh, true, false, true) <<
4806  " {" << endl;
4807  indent_up();
4808  out << indent() << "TraceSandeshType *trace = " <<
4809  "TraceSandeshType::GetInstance();" << endl;
4810  out << indent() << "if (trace != NULL && trace->IsTraceOn() && trace_buf->IsTraceOn()) {" << endl;
4811  indent_up();
4812  out << indent() << tsandesh->get_name() << " *" << creator_name << " = " <<
4813  "new " << tsandesh->get_name() <<
4814  generate_sandesh_no_static_const_string_function(tsandesh, false, false, false, false, true) <<
4815  ";" << endl;
4816  out << indent() << creator_name << "->set_category(trace_buf->Name());" << endl;
4817  out << indent() << "uint32_t seqnum(trace_buf->GetNextSeqNum());" << endl;
4818  out << indent() << creator_name << "->set_seqnum(seqnum);" << endl;
4819  out << indent() << "trace_buf->TraceWrite(" << creator_name << ");" << endl;
4820  out << indent() << "if ((IsLocalLoggingEnabled() && IsTracePrintEnabled()) || IsUnitTest()) " << creator_name << "->Log();" << endl;
4821  indent_down();
4822  out << indent() << "}" <<endl;
4823  indent_down();
4824  indent(out) <<
4825  "}" << endl << endl;
4826 }
4827 
4828 /*
4829  * Generate IsRatelimitPass function
4830  *
4831  */
4832 void t_cpp_generator::generate_isRatelimitPass(ofstream& out,
4833  t_sandesh* tsandesh) {
4834  out << indent() << "uint32_t send_rate_limit = Sandesh::get_send_rate_limit();" << endl;
4835  out << indent() << "if (send_rate_limit == 0) {" << endl;
4836  indent_up();
4837  out << indent() << "return false;" << endl;
4838  indent_down();
4839  out << indent() << "}" << endl;
4840  out << indent() << "tbb::mutex::scoped_lock lock(rate_limit_mutex_);" << endl;
4841  out << indent() << "if (rate_limit_buffer_.capacity() !="
4842  " send_rate_limit) {" << endl;
4843  indent_up();
4844  out << indent() << "//Resize the buffer to the "
4845  "buffer_threshold_" << endl;
4846  out << indent() << "rate_limit_buffer_.rresize(send_rate_limit);"
4847  << endl;
4848  out << indent() << "rate_limit_buffer_.set_capacity("
4849  "send_rate_limit);" << endl;
4850  indent_down();
4851  out << indent() << "}" << endl;
4852  out << indent() << "time_t current_time = time(0);" << endl;
4853  out << indent() << "if (rate_limit_buffer_.capacity() == rate_limit_buffer_"
4854  ".size()) {" << endl;
4855  indent_up();
4856  out << indent() << "if (*rate_limit_buffer_.begin() == current_time) {" << endl;
4857  indent_up();
4858  out << indent() << "//update tx and call droplog" << endl;
4859  out << indent() << "//Dont have to log more than once" << endl;
4860  out << indent() << "return false;" << endl;
4861  indent_down();
4862  out << indent() << "}" << endl;
4863  indent_down();
4864  out << indent() << "}" << endl;
4865  out << indent() << "//Should log failure after a sucessful write" << endl;
4866  out << indent() << "do_rate_limit_drop_log_ = true;" << endl;
4867  out << indent() << "rate_limit_buffer_.push_back(current_time);" << endl;
4868  out << indent() << "return true;" << endl;
4869 }
4870 
4871 
4872 #endif
4873 
4883  t_struct* tstruct,
4884  bool pointers) {
4885  string name = tstruct->get_name();
4886  const vector<t_field*>& fields = tstruct->get_sorted_members();
4887  vector<t_field*>::const_iterator f_iter;
4888 
4889  if (gen_templates_) {
4890  out <<
4891  indent() << "template <class Protocol_>" << endl <<
4892  indent() << "uint32_t " << tstruct->get_name() <<
4893  "::write(Protocol_* oprot) const {" << endl;
4894  } else {
4895  indent(out) <<
4896  "uint32_t " << tstruct->get_name() <<
4897  "::write(::contrail::sandesh::protocol::TProtocol* oprot) const {" << endl;
4898  }
4899  indent_up();
4900 
4901  out <<
4902  endl <<
4903  indent() << "uint32_t xfer = 0;" << endl <<
4904  endl;
4905 
4906  indent(out) <<
4907  "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
4908 
4909  bool first = true;
4910  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4911  if (first) {
4912  first = false;
4913  out <<
4914  endl <<
4915  indent() << "if ";
4916  } else {
4917  out <<
4918  " else if ";
4919  }
4920 
4921  out << "(this->__isset." << (*f_iter)->get_name() << ") {" << endl;
4922 
4923  indent_up();
4924 
4925  // Write field header
4926  out <<
4927  indent() << "xfer += oprot->writeFieldBegin(" <<
4928  "\"" << (*f_iter)->get_name() << "\", " <<
4929  type_to_enum((*f_iter)->get_type()) << ", " <<
4930  (*f_iter)->get_key() << ");" << endl;
4931  // Write field contents
4932  if (pointers) {
4933  generate_serialize_field(out, *f_iter, "(*(this->", "))");
4934  } else {
4935  generate_serialize_field(out, *f_iter, "this->");
4936  }
4937  // Write field closer
4938  indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
4939 
4940  indent_down();
4941  indent(out) << "}";
4942  }
4943 
4944  // Write the struct map
4945  out <<
4946  endl <<
4947  indent() << "xfer += oprot->writeFieldStop();" << endl <<
4948  indent() << "xfer += oprot->writeStructEnd();" << endl <<
4949  indent() << "return xfer;" << endl;
4950 
4951  indent_down();
4952  indent(out) <<
4953  "}" << endl <<
4954  endl;
4955 }
4956 
4966  string svcname = tservice->get_name();
4967 
4968  // Make output files
4969  string f_header_name = get_out_dir()+svcname+".h";
4970  f_header_.open(f_header_name.c_str());
4971 
4972  // Print header file includes
4973  f_header_ <<
4974  autogen_comment();
4975  f_header_ <<
4976  "#ifndef " << svcname << "_H" << endl <<
4977  "#define " << svcname << "_H" << endl <<
4978  endl;
4979  if (gen_cob_style_) {
4980  f_header_ <<
4981  "#include <transport/TBufferTransports.h>" << endl << // TMemoryBuffer
4982  "#include <tr1/functional>" << endl <<
4983  "namespace apache { namespace thrift { namespace async {" << endl <<
4984  "class TAsyncChannel;" << endl <<
4985  "}}}" << endl;
4986  }
4987  f_header_ <<
4988  "#include <TProcessor.h>" << endl;
4989  if (gen_cob_style_) {
4990  f_header_ <<
4991  "#include <async/TAsyncProcessor.h>" << endl;
4992  }
4993  f_header_ <<
4994  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
4995  "_types.h\"" << endl;
4996 
4997  t_service* extends_service = tservice->get_extends();
4998  if (extends_service != NULL) {
4999  f_header_ <<
5000  "#include \"" << get_include_prefix(*(extends_service->get_program())) <<
5001  extends_service->get_name() << ".h\"" << endl;
5002  }
5003 
5004  f_header_ <<
5005  endl <<
5006  ns_open_ << endl <<
5007  endl;
5008 
5009  // Service implementation file includes
5010  string f_service_name = get_out_dir()+svcname+".cpp";
5011  f_service_.open(f_service_name.c_str());
5012  f_service_ <<
5013  autogen_comment();
5014  f_service_ <<
5015  "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl;
5016  if (gen_cob_style_) {
5017  f_service_ <<
5018  "#include \"async/TAsyncChannel.h\"" << endl;
5019  }
5020  if (gen_templates_) {
5021  f_service_ <<
5022  "#include \"" << get_include_prefix(*get_program()) << svcname <<
5023  ".tcc\"" << endl;
5024 
5025  string f_service_tcc_name = get_out_dir()+svcname+".tcc";
5026  f_service_tcc_.open(f_service_tcc_name.c_str());
5027  f_service_tcc_ <<
5028  autogen_comment();
5029  f_service_tcc_ <<
5030  "#include \"" << get_include_prefix(*get_program()) << svcname <<
5031  ".h\"" << endl;
5032 
5033  f_service_tcc_ <<
5034  "#ifndef " << svcname << "_TCC" << endl <<
5035  "#define " << svcname << "_TCC" << endl <<
5036  endl;
5037 
5038  if (gen_cob_style_) {
5039  f_service_tcc_ <<
5040  "#include \"async/TAsyncChannel.h\"" << endl;
5041  }
5042  }
5043 
5044  f_service_ <<
5045  endl << ns_open_ << endl << endl;
5046  f_service_tcc_ <<
5047  endl << ns_open_ << endl << endl;
5048 
5049  // Generate all the components
5050  generate_service_interface(tservice, "");
5051  generate_service_interface_factory(tservice, "");
5052  generate_service_null(tservice, "");
5053  generate_service_helpers(tservice);
5054  generate_service_client(tservice, "");
5055  generate_service_processor(tservice, "");
5056  generate_service_multiface(tservice);
5057  generate_service_skeleton(tservice);
5058 
5059  // Generate all the cob components
5060  if (gen_cob_style_) {
5061  generate_service_interface(tservice, "CobCl");
5062  generate_service_interface(tservice, "CobSv");
5063  generate_service_interface_factory(tservice, "CobSv");
5064  generate_service_null(tservice, "CobSv");
5065  generate_service_client(tservice, "Cob");
5066  generate_service_processor(tservice, "Cob");
5067  generate_service_async_skeleton(tservice);
5068  }
5069 
5070  // Close the namespace
5071  f_service_ <<
5072  ns_close_ << endl <<
5073  endl;
5074  f_service_tcc_ <<
5075  ns_close_ << endl <<
5076  endl;
5077  f_header_ <<
5078  ns_close_ << endl <<
5079  endl;
5080 
5081  // TODO(simpkins): Make this a separate option
5082  if (gen_templates_) {
5083  f_header_ <<
5084  "#include \"" << get_include_prefix(*get_program()) << svcname <<
5085  ".tcc\"" << endl <<
5086  "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
5087  "_types.tcc\"" << endl <<
5088  endl;
5089  }
5090 
5091  f_header_ <<
5092  "#endif" << endl;
5093  f_service_tcc_ <<
5094  "#endif" << endl;
5095 
5096  // Close the files
5097  f_service_tcc_.close();
5098  f_service_.close();
5099  f_header_.close();
5100 }
5101 
5109  vector<t_function*> functions = tservice->get_functions();
5110  vector<t_function*>::iterator f_iter;
5111  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
5112 
5113  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
5114  t_struct* ts = (*f_iter)->get_arglist();
5115  string name_orig = ts->get_name();
5116 
5117  // TODO(dreiss): Why is this stuff not in generate_function_helpers?
5118  ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args");
5119  generate_struct_definition(f_header_, ts, false);
5120  generate_struct_reader(out, ts);
5121  generate_struct_writer(out, ts);
5122  ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs");
5123  generate_struct_definition(f_header_, ts, false, true, false, true);
5124  generate_struct_writer(out, ts, true);
5125  ts->set_name(name_orig);
5126 
5127  generate_function_helpers(tservice, *f_iter);
5128  }
5129 }
5130 
5137 
5138  string service_if_name = service_name_ + style + "If";
5139  if (style == "CobCl") {
5140  // Forward declare the client.
5141  string client_name = service_name_ + "CobClient";
5142  if (gen_templates_) {
5143  client_name += "T";
5144  service_if_name += "T";
5145  indent(f_header_) <<
5146  "template <class Protocol_>" << endl;
5147  }
5148  indent(f_header_) << "class " << client_name << ";" <<
5149  endl << endl;
5150  }
5151 
5152  string extends = "";
5153  if (tservice->get_extends() != NULL) {
5154  extends = " : virtual public " + type_name(tservice->get_extends()) +
5155  style + "If";
5156  if (style == "CobCl" && gen_templates_) {
5157  // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
5158  // parent services were also generated with templates enabled.
5159  extends += "T<Protocol_>";
5160  }
5161  }
5162 
5163  if (style == "CobCl" && gen_templates_) {
5164  f_header_ << "template <class Protocol_>" << endl;
5165  }
5166  f_header_ <<
5167  "class " << service_if_name << extends << " {" << endl <<
5168  " public:" << endl;
5169  indent_up();
5170  f_header_ <<
5171  indent() << "virtual ~" << service_if_name << "() {}" << endl;
5172 
5173  vector<t_function*> functions = tservice->get_functions();
5174  vector<t_function*>::iterator f_iter;
5175  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
5176  f_header_ <<
5177  indent() << "virtual " << function_signature(*f_iter, style) << " = 0;" << endl;
5178  }
5179  indent_down();
5180  f_header_ <<
5181  "};" << endl << endl;
5182 
5183  if (style == "CobCl" && gen_templates_) {
5184  // generate a backwards-compatible typedef for clients that do not
5185  // know about the new template-style code
5186  f_header_ <<
5187  "typedef " << service_if_name <<
5188  "< ::contrail::sandesh::protocol::TProtocol> " <<
5189  service_name_ << style << "If;" <<
5190  endl << endl;
5191  }
5192 }
5193 
5200  string style) {
5201  string service_if_name = service_name_ + style + "If";
5202 
5203  // Figure out the name of the upper-most parent class.
5204  // Getting everything to work out properly with inheritance is annoying.
5205  // Here's what we're doing for now:
5206  //
5207  // - All handlers implement getHandler(), but subclasses use covariant return
5208  // types to return their specific service interface class type. We have to
5209  // use raw pointers because of this; shared_ptr<> can't be used for
5210  // covariant return types.
5211  //
5212  // - Since we're not using shared_ptr<>, we also provide a releaseHandler()
5213  // function that must be called to release a pointer to a handler obtained
5214  // via getHandler().
5215  //
5216  // releaseHandler() always accepts a pointer to the upper-most parent class
5217  // type. This is necessary since the parent versions of releaseHandler()
5218  // may accept any of the parent types, not just the most specific subclass
5219  // type. Implementations can use dynamic_cast to cast the pointer to the
5220  // subclass type if desired.
5221  t_service* base_service = tservice;
5222  while (base_service->get_extends() != NULL) {
5223  base_service = base_service->get_extends();
5224  }
5225  string base_if_name = type_name(base_service) + style + "If";
5226 
5227  // Generate the abstract factory class
5228  string factory_name = service_if_name + "Factory";
5229  string extends;
5230  if (tservice->get_extends() != NULL) {
5231  extends = " : virtual public " + type_name(tservice->get_extends()) +
5232  style + "IfFactory";
5233  }
5234 
5235  f_header_ <<
5236  "class " << factory_name << extends << " {" << endl <<
5237  " public:" << endl;
5238  indent_up();
5239  f_header_ <<
5240  indent() << "typedef " << service_if_name << " Handler;" << endl <<
5241  endl <<
5242  indent() << "virtual ~" << factory_name << "() {}" << endl <<
5243  endl <<
5244  indent() << "virtual " << service_if_name << "* getHandler(" <<
5245  "const ::contrail::sandesh::TConnectionInfo& connInfo) = 0;" <<
5246  endl <<
5247  indent() << "virtual void releaseHandler(" << base_if_name <<
5248  "* /* handler */) = 0;" << endl;
5249 
5250  indent_down();
5251  f_header_ <<
5252  "};" << endl << endl;
5253 
5254  // Generate the singleton factory class
5255  string singleton_factory_name = service_if_name + "SingletonFactory";
5256  f_header_ <<
5257  "class " << singleton_factory_name <<
5258  " : virtual public " << factory_name << " {" << endl <<
5259  " public:" << endl;
5260  indent_up();
5261  f_header_ <<
5262  indent() << singleton_factory_name << "(const boost::shared_ptr<" <<
5263  service_if_name << ">& iface) : iface_(iface) {}" << endl <<
5264  indent() << "virtual ~" << singleton_factory_name << "() {}" << endl <<
5265  endl <<
5266  indent() << "virtual " << service_if_name << "* getHandler(" <<
5267  "const ::contrail::sandesh::TConnectionInfo&) {" << endl <<
5268  indent() << " return iface_.get();" << endl <<
5269  indent() << "}" << endl <<
5270  indent() << "virtual void releaseHandler(" << base_if_name <<
5271  "* /* handler */) {}" << endl;
5272 
5273  f_header_ <<
5274  endl <<
5275  " protected:" << endl <<
5276  indent() << "boost::shared_ptr<" << service_if_name << "> iface_;" << endl;
5277 
5278  indent_down();
5279  f_header_ <<
5280  "};" << endl << endl;
5281 }
5282 
5288 void t_cpp_generator::generate_service_null(t_service* tservice, string style) {
5289  string extends = "";
5290  if (tservice->get_extends() != NULL) {
5291  extends = " , virtual public " + type_name(tservice->get_extends()) + style + "Null";
5292  }
5293  f_header_ <<
5294  "class " << service_name_ << style << "Null : virtual public " << service_name_ << style << "If" << extends << " {" << endl <<
5295  " public:" << endl;
5296  indent_up();
5297  f_header_ <<
5298  indent() << "virtual ~" << service_name_ << style << "Null() {}" << endl;
5299  vector<t_function*> functions = tservice->get_functions();
5300  vector<t_function*>::iterator f_iter;
5301  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
5302  f_header_ <<
5303  indent() << function_signature(*f_iter, style, "", false) << " {" << endl;
5304  indent_up();
5305 
5306  t_type* returntype = (*f_iter)->get_returntype();
5307  t_field returnfield(returntype, "_return");
5308 
5309  if (style == "") {
5310  if (returntype->is_void() || is_complex_type(returntype)) {
5311  f_header_ << indent() << "return;" << endl;
5312  } else {
5313  f_header_ <<
5314  indent() << declare_field(&returnfield, true) << endl <<
5315  indent() << "return _return;" << endl;
5316  }
5317  } else if (style == "CobSv") {
5318  if (returntype->is_void()) {
5319  f_header_ << indent() << "return cob();" << endl;
5320  } else {
5321  t_field returnfield(returntype, "_return");
5322  f_header_ <<
5323  indent() << declare_field(&returnfield, true) << endl <<
5324  indent() << "return cob(_return);" << endl;
5325  }
5326 
5327  } else {
5328  throw "UNKNOWN STYLE";
5329  }
5330 
5331  indent_down();
5332  f_header_ <<
5333  indent() << "}" << endl;
5334  }
5335  indent_down();
5336  f_header_ <<
5337  "};" << endl << endl;
5338 }
5339 
5340 void t_cpp_generator::generate_function_call(ostream& out, t_function* tfunction, string target, string iface, string arg_prefix) {
5341  bool first = true;
5342  t_type* ret_type = get_true_type(tfunction->get_returntype());
5343  out << indent();
5344  if (!tfunction->is_oneway() && !ret_type->is_void()) {
5345  if (is_complex_type(ret_type)) {
5346  first = false;
5347  out << iface << "->" << tfunction->get_name() << "(" << target;
5348  } else {
5349  out << target << " = " << iface << "->" << tfunction->get_name() << "(";
5350  }
5351  } else {
5352  out << iface << "->" << tfunction->get_name() << "(";
5353  }
5354  const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members();
5355  vector<t_field*>::const_iterator f_iter;
5356  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
5357  if (first) {
5358  first = false;
5359  } else {
5360  out << ", ";
5361  }
5362  out << arg_prefix << (*f_iter)->get_name();
5363  }
5364  out << ");" << endl;
5365 }
5366 
5368  string svcname = tservice->get_name();
5369 
5370  // Service implementation file includes
5371  string f_skeleton_name = get_out_dir()+svcname+"_async_server.skeleton.cpp";
5372 
5373  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
5374 
5375  ofstream f_skeleton;
5376  f_skeleton.open(f_skeleton_name.c_str());
5377  f_skeleton <<
5378  "// This autogenerated skeleton file illustrates one way to adapt a synchronous" << endl <<
5379  "// interface into an asynchronous interface. You should copy it to another" << endl <<
5380  "// filename to avoid overwriting it and rewrite as asynchronous any functions" << endl <<
5381  "// that would otherwise introduce unwanted latency." << endl <<
5382  endl <<
5383  "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl <<
5384  "#include <protocol/TBinaryProtocol.h>" << endl <<
5385  "#include <async/TEventServer.h>" << endl <<
5386  endl <<
5387  "using namespace ::contrail::sandesh;" << endl <<
5388  "using namespace ::contrail::sandesh::protocol;" << endl <<
5389  "using namespace ::contrail::sandesh::transport;" << endl <<
5390  "using namespace ::contrail::sandesh::async;" << endl <<
5391  endl <<
5392  "using boost::shared_ptr;" << endl <<
5393  endl;
5394 
5395  if (!ns.empty()) {
5396  f_skeleton <<
5397  "using namespace " << string(ns, 0, ns.size()-2) << ";" << endl <<
5398  endl;
5399  }
5400 
5401  f_skeleton <<
5402  "class " << svcname << "AsyncHandler : " <<
5403  "public " << svcname << "CobSvIf {" << endl <<
5404  " public:" << endl;
5405  indent_up();
5406  f_skeleton <<
5407  indent() << svcname << "AsyncHandler() {" << endl <<
5408  indent() << " syncHandler_ = std::unique_ptr<" << svcname <<
5409  "Handler>(new " << svcname << "Handler);" << endl <<
5410  indent() << " // Your initialization goes here" << endl <<
5411  indent() << "}" << endl;
5412  f_skeleton <<
5413  indent() << "virtual ~" << service_name_ << "AsyncHandler();" << endl;
5414 
5415  vector<t_function*> functions = tservice->get_functions();
5416  vector<t_function*>::iterator f_iter;
5417  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
5418  f_skeleton <<
5419  endl <<
5420  indent() << function_signature(*f_iter, "CobSv", "", true) << " {" << endl;
5421  indent_up();
5422 
5423  t_type* returntype = (*f_iter)->get_returntype();
5424  t_field returnfield(returntype, "_return");
5425 
5426  string target = returntype->is_void() ? "" : "_return";
5427  if (!returntype->is_void()) {
5428  f_skeleton <<
5429  indent() << declare_field(&returnfield, true) << endl;
5430  }
5431  generate_function_call(f_skeleton, *f_iter, target, "syncHandler_", "");
5432  f_skeleton << indent() << "return cob(" << target << ");" << endl;
5433 
5434  scope_down(f_skeleton);
5435  }
5436  f_skeleton << endl <<
5437  " protected:" << endl <<
5438  indent() << "std::unique_ptr<" << svcname << "Handler> syncHandler_;" << endl;
5439  indent_down();
5440  f_skeleton <<
5441  "};" << endl << endl;
5442 }
5443 
5452  // Generate the dispatch methods
5453  vector<t_function*> functions = tservice->get_functions();
5454  vector<t_function*>::iterator f_iter;
5455 
5456  string extends = "";
5457  string extends_multiface = "";
5458  if (tservice->get_extends() != NULL) {
5459  extends = type_name(tservice->get_extends());
5460  extends_multiface = ", public " + extends + "Multiface";
5461  }
5462 
5463  string list_type = string("std::vector<boost::shared_ptr<") + service_name_ + "If> >";
5464 
5465  // Generate the header portion
5466  f_header_ <<
5467  "class " << service_name_ << "Multiface : " <<
5468  "virtual public " << service_name_ << "If" <<
5469  extends_multiface << " {" << endl <<
5470  " public:" << endl;
5471  indent_up();
5472  f_header_ <<
5473  indent() << service_name_ << "Multiface(" << list_type << "& ifaces) : ifaces_(ifaces) {" << endl;
5474  if (!extends.empty()) {
5475  f_header_ <<
5476  indent() << " std::vector<boost::shared_ptr<" + service_name_ + "If> >::iterator iter;" << endl <<
5477  indent() << " for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {" << endl <<
5478  indent() << " " << extends << "Multiface::add(*iter);" << endl <<
5479  indent() << " }" << endl;
5480  }
5481  f_header_ <<
5482  indent() << "}" << endl <<
5483  indent() << "virtual ~" << service_name_ << "Multiface() {}" << endl;
5484  indent_down();
5485 
5486  // Protected data members
5487  f_header_ <<
5488  " protected:" << endl;
5489  indent_up();
5490  f_header_ <<
5491  indent() << list_type << " ifaces_;" << endl <<
5492  indent() << service_name_ << "Multiface() {}" << endl <<
5493  indent() << "void add(boost::shared_ptr<" << service_name_ << "If> iface) {" << endl;
5494  if (!extends.empty()) {
5495  f_header_ <<
5496  indent() << " " << extends << "Multiface::add(iface);" << endl;
5497  }
5498  f_header_ <<
5499  indent() << " ifaces_.push_back(iface);" << endl <<
5500  indent() << "}" << endl;
5501  indent_down();
5502 
5503  f_header_ <<
5504  indent() << " public:" << endl;
5505  indent_up();
5506 
5507  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
5508  t_struct* arglist = (*f_iter)->get_arglist();
5509  const vector<t_field*>& args = arglist->get_members();
5510  vector<t_field*>::const_iterator a_iter;
5511 
5512  string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "(";
5513  bool first = true;
5514  if (is_complex_type((*f_iter)->get_returntype())) {
5515  call += "_return";
5516  first = false;
5517  }
5518  for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
5519  if (first) {
5520  first = false;
5521  } else {
5522  call += ", ";
5523  }
5524  call += (*a_iter)->get_name();
5525  }
5526  call += ")";
5527 
5528  f_header_ <<
5529  indent() << function_signature(*f_iter, "") << " {" << endl;
5530  indent_up();
5531  f_header_ <<
5532  indent() << "size_t sz = ifaces_.size();" << endl <<
5533  indent() << "for (size_t i = 0; i < sz; ++i) {" << endl;
5534  if (!(*f_iter)->get_returntype()->is_void()) {
5535  f_header_ <<
5536  indent() << " if (i == sz - 1) {" << endl;
5537  if (is_complex_type((*f_iter)->get_returntype())) {
5538  f_header_ <<
5539  indent() << " " << call << ";" << endl <<
5540  indent() << " return;" << endl;
5541  } else {
5542  f_header_ <<
5543  indent() << " return " << call << ";" << endl;
5544  }
5545  f_header_ <<
5546  indent() << " } else {" << endl <<
5547  indent() << " " << call << ";" << endl <<
5548  indent() << " }" << endl;
5549  } else {
5550  f_header_ <<
5551  indent() << " " << call << ";" << endl;
5552  }
5553 
5554  f_header_ <<
5555  indent() << "}" << endl;
5556 
5557  indent_down();
5558  f_header_ <<
5559  indent() << "}" << endl <<
5560  endl;
5561  }
5562 
5563  indent_down();
5564  f_header_ <<
5565  indent() << "};" << endl <<
5566  endl;
5567 }
5568 
5575  string ifstyle;
5576  if (style == "Cob") {
5577  ifstyle = "CobCl";
5578  }
5579 
5580  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
5581  string template_header, template_suffix, short_suffix, protocol_type, _this;
5582  string const prot_factory_type =
5583  "::contrail::sandesh::protocol::TProtocolFactory";
5584  if (gen_templates_) {
5585  template_header = "template <class Protocol_>\n";
5586  short_suffix = "T";
5587  template_suffix = "T<Protocol_>";
5588  protocol_type = "Protocol_";
5589  _this = "this->";
5590  } else {
5591  protocol_type = "::contrail::sandesh::protocol::TProtocol";
5592  }
5593  string prot_ptr = "boost::shared_ptr< " + protocol_type + ">";
5594  string client_suffix = "Client" + template_suffix;
5595  string if_suffix = "If";
5596  if (style == "Cob") {
5597  if_suffix += template_suffix;
5598  }
5599 
5600  string extends = "";
5601  string extends_client = "";
5602  if (tservice->get_extends() != NULL) {
5603  // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
5604  // parent services were also generated with templates enabled.
5605  extends = type_name(tservice->get_extends());
5606  extends_client = ", public " + extends + style + client_suffix;
5607  }
5608 
5609  // Generate the header portion
5610  f_header_ <<
5611  template_header <<
5612  "class " << service_name_ << style << "Client" << short_suffix << " : " <<
5613  "virtual public " << service_name_ << ifstyle << if_suffix <<
5614  extends_client << " {" << endl <<
5615  " public:" << endl;
5616 
5617  indent_up();
5618  if (style != "Cob") {
5619  f_header_ <<
5620  indent() << service_name_ << style << "Client" << short_suffix <<
5621  "(" << prot_ptr << " prot) :" <<
5622  endl;
5623  if (extends.empty()) {
5624  f_header_ <<
5625  indent() << " piprot_(prot)," << endl <<
5626  indent() << " poprot_(prot) {" << endl <<
5627  indent() << " iprot_ = prot.get();" << endl <<
5628  indent() << " oprot_ = prot.get();" << endl <<
5629  indent() << "}" << endl;
5630  } else {
5631  f_header_ <<
5632  indent() << " " << extends << style << client_suffix <<
5633  "(prot, prot) {}" << endl;
5634  }
5635 
5636  f_header_ <<
5637  indent() << service_name_ << style << "Client" << short_suffix <<
5638  "(" << prot_ptr << " iprot, " << prot_ptr << " oprot) :" << endl;
5639  if (extends.empty()) {
5640  f_header_ <<
5641  indent() << " piprot_(iprot)," << endl <<
5642  indent() << " poprot_(oprot) {" << endl <<
5643  indent() << " iprot_ = iprot.get();" << endl <<
5644  indent() << " oprot_ = oprot.get();" << endl <<
5645  indent() << "}" << endl;
5646  } else {
5647  f_header_ <<
5648  indent() << " " << extends << style << client_suffix <<
5649  "(iprot, oprot) {}" << endl;
5650  }
5651 
5652  // Generate getters for the protocols.
5653  // Note that these are not currently templated for simplicity.
5654  // TODO(simpkins): should they be templated?
5655  f_header_ <<
5656  indent() << "boost::shared_ptr< ::contrail::sandesh::protocol::TProtocol> getInputProtocol() {" << endl <<
5657  indent() << " return " << _this << "piprot_;" << endl <<
5658  indent() << "}" << endl;
5659 
5660  f_header_ <<
5661  indent() << "boost::shared_ptr< ::contrail::sandesh::protocol::TProtocol> getOutputProtocol() {" << endl <<
5662  indent() << " return " << _this << "poprot_;" << endl <<
5663  indent() << "}" << endl;
5664 
5665  } else /* if (style == "Cob") */ {
5666  f_header_ <<
5667  indent() << service_name_ << style << "Client" << short_suffix << "(" <<
5668  "boost::shared_ptr< ::contrail::sandesh::async::TAsyncChannel> channel, " <<
5669  "::contrail::sandesh::protocol::TProtocolFactory* protocolFactory) :" <<
5670  endl;
5671  if (extends.empty()) {
5672  f_header_ <<
5673  indent() << " channel_(channel)," << endl <<
5674  indent() << " itrans_(new ::contrail::sandesh::transport::TMemoryBuffer())," << endl <<
5675  indent() << " otrans_(new ::contrail::sandesh::transport::TMemoryBuffer())," << endl;
5676  if (gen_templates_) {
5677  // TProtocolFactory classes return generic TProtocol pointers.
5678  // We have to dynamic cast to the Protocol_ type we are expecting.
5679  f_header_ <<
5680  indent() << " piprot_(boost::dynamic_pointer_cast<Protocol_>(" <<
5681  "protocolFactory->getProtocol(itrans_)))," << endl <<
5682  indent() << " poprot_(boost::dynamic_pointer_cast<Protocol_>(" <<
5683  "protocolFactory->getProtocol(otrans_))) {" << endl;
5684  // Throw a TException if either dynamic cast failed.
5685  f_header_ <<
5686  indent() << " if (!piprot_ || !poprot_) {" << endl <<
5687  indent() << " throw ::contrail::sandesh::TException(\"" <<
5688  "TProtocolFactory returned unexpected protocol type in " <<
5689  service_name_ << style << "Client" << short_suffix <<
5690  " constructor\");" << endl <<
5691  indent() << " }" << endl;
5692  } else {
5693  f_header_ <<
5694  indent() << " piprot_(protocolFactory->getProtocol(itrans_))," <<
5695  endl <<
5696  indent() << " poprot_(protocolFactory->getProtocol(otrans_)) {" <<
5697  endl;
5698  }
5699  f_header_ <<
5700  indent() << " iprot_ = piprot_.get();" << endl <<
5701  indent() << " oprot_ = poprot_.get();" << endl <<
5702  indent() << "}" << endl;
5703  } else {
5704  f_header_ <<
5705  indent() << " " << extends << style << client_suffix <<
5706  "(channel, protocolFactory) {}" << endl;
5707  }
5708  }
5709 
5710  if (style == "Cob") {
5711  f_header_ <<
5712  indent() << "boost::shared_ptr< ::contrail::sandesh::async::TAsyncChannel> getChannel() {" << endl <<
5713  indent() << " return " << _this << "channel_;" << endl <<
5714  indent() << "}" << endl;
5715  if (!gen_no_client_completion_) {
5716  f_header_ <<
5717  indent() << "virtual void completed__(bool /* success */) {}" << endl;
5718  }
5719  }
5720 
5721  vector<t_function*> functions = tservice->get_functions();
5722  vector<t_function*>::const_iterator f_iter;
5723  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
5724  indent(f_header_) << function_signature(*f_iter, ifstyle) << ";" << endl;
5725  // TODO(dreiss): Use private inheritance to avoid generating thise in cob-style.
5726  t_function send_function(g_type_void,
5727  string("send_") + (*f_iter)->get_name(),
5728  (*f_iter)->get_arglist());
5729  indent(f_header_) << function_signature(&send_function, "") << ";" << endl;
5730  if (!(*f_iter)->is_oneway()) {
5731  t_struct noargs(program_);
5732  t_function recv_function((*f_iter)->get_returntype(),
5733  string("recv_") + (*f_iter)->get_name(),
5734  &noargs);
5735  indent(f_header_) << function_signature(&recv_function, "") << ";" << endl;
5736  }
5737  }
5738  indent_down();
5739 
5740  if (extends.empty()) {
5741  f_header_ <<
5742  " protected:" << endl;
5743  indent_up();
5744 
5745  if (style == "Cob") {
5746  f_header_ <<
5747  indent() << "boost::shared_ptr< ::contrail::sandesh::async::TAsyncChannel> channel_;" << endl <<
5748  indent() << "boost::shared_ptr< ::contrail::sandesh::transport::TMemoryBuffer> itrans_;" << endl <<
5749  indent() << "boost::shared_ptr< ::contrail::sandesh::transport::TMemoryBuffer> otrans_;" << endl;
5750  }
5751  f_header_ <<
5752  indent() << prot_ptr << " piprot_;" << endl <<
5753  indent() << prot_ptr << " poprot_;" << endl <<
5754  indent() << protocol_type << "* iprot_;" << endl <<
5755  indent() << protocol_type << "* oprot_;" << endl;
5756 
5757  indent_down();
5758  }
5759 
5760  f_header_ <<
5761  "};" << endl <<
5762  endl;
5763 
5764  if (gen_templates_) {
5765  // Output a backwards compatibility typedef using
5766  // TProtocol as the template parameter.
5767  f_header_ <<
5768  "typedef " << service_name_ << style <<
5769  "ClientT< ::contrail::sandesh::protocol::TProtocol> " <<
5770  service_name_ << style << "Client;" << endl <<
5771  endl;
5772  }
5773 
5774  string scope = service_name_ + style + client_suffix + "::";
5775 
5776  // Generate client method implementations
5777  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
5778  string funname = (*f_iter)->get_name();
5779 
5780  // Open function
5781  if (gen_templates_) {
5782  indent(out) << template_header;
5783  }
5784  indent(out) <<
5785  function_signature(*f_iter, ifstyle, scope) << endl;
5786  scope_up(out);
5787  indent(out) <<
5788  "send_" << funname << "(";
5789 
5790  // Get the struct of function call params
5791  t_struct* arg_struct = (*f_iter)->get_arglist();
5792 
5793  // Declare the function arguments
5794  const vector<t_field*>& fields = arg_struct->get_members();
5795  vector<t_field*>::const_iterator fld_iter;
5796  bool first = true;
5797  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
5798  if (first) {
5799  first = false;
5800  } else {
5801  out << ", ";
5802  }
5803  out << (*fld_iter)->get_name();
5804  }
5805  out << ");" << endl;
5806 
5807  if (style != "Cob") {
5808  if (!(*f_iter)->is_oneway()) {
5809  out << indent();
5810  if (!(*f_iter)->get_returntype()->is_void()) {
5811  if (is_complex_type((*f_iter)->get_returntype())) {
5812  out << "recv_" << funname << "(_return);" << endl;
5813  } else {
5814  out << "return recv_" << funname << "();" << endl;
5815  }
5816  } else {
5817  out <<
5818  "recv_" << funname << "();" << endl;
5819  }
5820  }
5821  } else {
5822  if (!(*f_iter)->is_oneway()) {
5823  out <<
5824  indent() << _this << "channel_->sendAndRecvMessage(" <<
5825  "std::tr1::bind(cob, this), " << _this << "otrans_.get(), " <<
5826  _this << "itrans_.get());" << endl;
5827  } else {
5828  out <<
5829  indent() << _this << "channel_->sendMessage(" <<
5830  "std::tr1::bind(cob, this), " << _this << "otrans_.get());" << endl;
5831  }
5832  }
5833  scope_down(out);
5834  out << endl;
5835 
5836  //if (style != "Cob") // TODO(dreiss): Libify the client and don't generate this for cob-style
5837  if (true) {
5838  // Function for sending
5839  t_function send_function(g_type_void,
5840  string("send_") + (*f_iter)->get_name(),
5841  (*f_iter)->get_arglist());
5842 
5843  // Open the send function
5844  if (gen_templates_) {
5845  indent(out) << template_header;
5846  }
5847  indent(out) <<
5848  function_signature(&send_function, "", scope) << endl;
5849  scope_up(out);
5850 
5851  // Function arguments and results
5852  string argsname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs";
5853  string resultname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_presult";
5854 
5855  // Serialize the request
5856  out <<
5857  indent() << "int32_t cseqid = 0;" << endl <<
5858  indent() << _this << "oprot_->writeMessageBegin(\"" <<
5859  (*f_iter)->get_name() <<
5860  "\", ::contrail::sandesh::protocol::T_CALL, cseqid);" << endl <<
5861  endl <<
5862  indent() << argsname << " args;" << endl;
5863 
5864  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
5865  out <<
5866  indent() << "args." << (*fld_iter)->get_name() << " = &" << (*fld_iter)->get_name() << ";" << endl;
5867  }
5868 
5869  out <<
5870  indent() << "args.write(" << _this << "oprot_);" << endl <<
5871  endl <<
5872  indent() << _this << "oprot_->writeMessageEnd();" << endl <<
5873  indent() << _this << "oprot_->getTransport()->writeEnd();" << endl <<
5874  indent() << _this << "oprot_->getTransport()->flush();" << endl;
5875 
5876  scope_down(out);
5877  out << endl;
5878 
5879  // Generate recv function only if not an oneway function
5880  if (!(*f_iter)->is_oneway()) {
5881  t_struct noargs(program_);
5882  t_function recv_function((*f_iter)->get_returntype(),
5883  string("recv_") + (*f_iter)->get_name(),
5884  &noargs);
5885  // Open the recv function
5886  if (gen_templates_) {
5887  indent(out) << template_header;
5888  }
5889  indent(out) <<
5890  function_signature(&recv_function, "", scope) << endl;
5891  scope_up(out);
5892 
5893  out <<
5894  endl <<
5895  indent() << "int32_t rseqid = 0;" << endl <<
5896  indent() << "std::string fname;" << endl <<
5897  indent() << "::contrail::sandesh::protocol::TMessageType mtype;" << endl;
5898  if (style == "Cob" && !gen_no_client_completion_) {
5899  out <<
5900  indent() << "bool completed = false;" << endl << endl <<
5901  indent() << "try {";
5902  indent_up();
5903  }
5904  out << endl <<
5905  indent() << _this << "iprot_->readMessageBegin(fname, mtype, rseqid);" << endl <<
5906  indent() << "if (mtype == ::contrail::sandesh::protocol::T_EXCEPTION) {" << endl <<
5907  indent() << " ::contrail::sandesh::TApplicationException x;" << endl <<
5908  indent() << " x.read(" << _this << "iprot_);" << endl <<
5909  indent() << " " << _this << "iprot_->readMessageEnd();" << endl <<
5910  indent() << " " << _this << "iprot_->getTransport()->readEnd();" <<
5911  endl;
5912  if (style == "Cob" && !gen_no_client_completion_) {
5913  out <<
5914  indent() << " completed = true;" << endl <<
5915  indent() << " completed__(true);" << endl;
5916  }
5917  out <<
5918  indent() << " throw x;" << endl <<
5919  indent() << "}" << endl <<
5920  indent() << "if (mtype != ::contrail::sandesh::protocol::T_REPLY) {" << endl <<
5921  indent() << " " << _this << "iprot_->skip(" <<
5922  "::contrail::sandesh::protocol::T_STRUCT);" << endl <<
5923  indent() << " " << _this << "iprot_->readMessageEnd();" << endl <<
5924  indent() << " " << _this << "iprot_->getTransport()->readEnd();" <<
5925  endl;
5926  if (style == "Cob" && !gen_no_client_completion_) {
5927  out <<
5928  indent() << " completed = true;" << endl <<
5929  indent() << " completed__(false);" << endl;
5930  }
5931  out <<
5932  indent() << "}" << endl <<
5933  indent() << "if (fname.compare(\"" << (*f_iter)->get_name() << "\") != 0) {" << endl <<
5934  indent() << " " << _this << "iprot_->skip(" <<
5935  "::contrail::sandesh::protocol::T_STRUCT);" << endl <<
5936  indent() << " " << _this << "iprot_->readMessageEnd();" << endl <<
5937  indent() << " " << _this << "iprot_->getTransport()->readEnd();" <<
5938  endl;
5939  if (style == "Cob" && !gen_no_client_completion_) {
5940  out <<
5941  indent() << " completed = true;" << endl <<
5942  indent() << " completed__(false);" << endl;
5943  }
5944  out <<
5945  indent() << "}" << endl;
5946 
5947  if (!(*f_iter)->get_returntype()->is_void() &&
5948  !is_complex_type((*f_iter)->get_returntype())) {
5949  t_field returnfield((*f_iter)->get_returntype(), "_return");
5950  out <<
5951  indent() << declare_field(&returnfield) << endl;
5952  }
5953 
5954  out <<
5955  indent() << resultname << " result;" << endl;
5956 
5957  if (!(*f_iter)->get_returntype()->is_void()) {
5958  out <<
5959  indent() << "result.success = &_return;" << endl;
5960  }
5961 
5962  out <<
5963  indent() << "result.read(" << _this << "iprot_);" << endl <<
5964  indent() << _this << "iprot_->readMessageEnd();" << endl <<
5965  indent() << _this << "iprot_->getTransport()->readEnd();" << endl <<
5966  endl;
5967 
5968  // Careful, only look for _result if not a void function
5969  if (!(*f_iter)->get_returntype()->is_void()) {
5970  if (is_complex_type((*f_iter)->get_returntype())) {
5971  out <<
5972  indent() << "if (result.__isset.success) {" << endl <<
5973  indent() << " // _return pointer has now been filled" << endl;
5974  if (style == "Cob" && !gen_no_client_completion_) {
5975  out <<
5976  indent() << " completed = true;" << endl <<
5977  indent() << " completed__(true);" << endl;
5978  }
5979  out <<
5980  indent() << " return;" << endl <<
5981  indent() << "}" << endl;
5982  } else {
5983  out <<
5984  indent() << "if (result.__isset.success) {" << endl;
5985  if (style == "Cob" && !gen_no_client_completion_) {
5986  out <<
5987  indent() << " completed = true;" << endl <<
5988  indent() << " completed__(true);" << endl;
5989  }
5990  out <<
5991  indent() << " return _return;" << endl <<
5992  indent() << "}" << endl;
5993  }
5994  }
5995 
5996  t_struct* xs = (*f_iter)->get_xceptions();
5997  const std::vector<t_field*>& xceptions = xs->get_members();
5998  vector<t_field*>::const_iterator x_iter;
5999  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
6000  out <<
6001  indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl;
6002  if (style == "Cob" && !gen_no_client_completion_) {
6003  out <<
6004  indent() << " completed = true;" << endl <<
6005  indent() << " completed__(true);" << endl;
6006  }
6007  out <<
6008  indent() << " throw result." << (*x_iter)->get_name() << ";" << endl <<
6009  indent() << "}" << endl;
6010  }
6011 
6012  // We only get here if we are a void function
6013  if ((*f_iter)->get_returntype()->is_void()) {
6014  if (style == "Cob" && !gen_no_client_completion_) {
6015  out <<
6016  indent() << "completed = true;" << endl <<
6017  indent() << "completed__(true);" << endl;
6018  }
6019  indent(out) <<
6020  "return;" << endl;
6021  } else {
6022  if (style == "Cob" && !gen_no_client_completion_) {
6023  out <<
6024  indent() << "completed = true;" << endl <<
6025  indent() << "completed__(true);" << endl;
6026  }
6027  out <<
6028  indent() << "throw ::contrail::sandesh::TApplicationException(::contrail::sandesh::TApplicationException::MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
6029  }
6030  if (style == "Cob" && !gen_no_client_completion_) {
6031  indent_down();
6032  out <<
6033  indent() << "} catch (...) {" << endl <<
6034  indent() << " if (!completed) {" << endl <<
6035  indent() << " completed__(false);" << endl <<
6036  indent() << " }" << endl <<
6037  indent() << " throw;" << endl <<
6038  indent() << "}" << endl;
6039  }
6040  // Close function
6041  scope_down(out);
6042  out << endl;
6043  }
6044  }
6045  }
6046 }
6047 
6049  public:
6050  ProcessorGenerator(t_cpp_generator* generator, t_service* service,
6051  const string& style);
6052 
6053  void run() {
6054  generate_class_definition();
6055  // Generate the process() function
6056  generate_process();
6057  // Generate the process_fn() function
6058  generate_process_fn();
6059  // Generate all of the process subfunctions
6060  generate_process_functions();
6061 
6062  generate_factory();
6063  }
6064 
6065  void generate_class_definition();
6066  void generate_process();
6067  void generate_process_fn();
6068  void generate_process_functions();
6069  void generate_factory();
6070 
6071  protected:
6072  std::string type_name(t_type* ttype, bool in_typedef=false, bool arg=false) {
6073  return generator_->type_name(ttype, in_typedef, arg);
6074  }
6075 
6076  std::string indent() {
6077  return generator_->indent();
6078  }
6079  std::ostream& indent(std::ostream &os) {
6080  return generator_->indent(os);
6081  }
6082 
6083  void indent_up() {
6084  generator_->indent_up();
6085  }
6086  void indent_down() {
6087  generator_->indent_down();
6088  }
6089 
6092  std::ofstream& f_header_;
6093  std::ofstream& f_out_;
6095  string style_;
6096  string pstyle_;
6097  string class_name_;
6098  string if_name_;
6100  string finish_cob_;
6102  string ret_type_;
6104  string cob_arg_;
6111  string extends_;
6113 };
6114 
6116  t_service* service,
6117  const string& style)
6118  : generator_(generator),
6119  service_(service),
6120  f_header_(generator->f_header_),
6121  f_out_(generator->gen_templates_ ?
6122  generator->f_service_tcc_ : generator->f_service_),
6123  service_name_(generator->service_name_),
6124  style_(style) {
6125  if (style_ == "Cob") {
6126  pstyle_ = "Async";
6127  class_name_ = service_name_ + pstyle_ + "Processor";
6128  if_name_ = service_name_ + "CobSvIf";
6129 
6130  finish_cob_ = "std::tr1::function<void(bool ok)> cob, ";
6131  finish_cob_decl_ = "std::tr1::function<void(bool ok)>, ";
6132  cob_arg_ = "cob, ";
6133  ret_type_ = "void ";
6134  } else {
6135  class_name_ = service_name_ + "Processor";
6136  if_name_ = service_name_ + "If";
6137 
6138  ret_type_ = "bool ";
6139  // TODO(edhall) callContext should eventually be added to TAsyncProcessor
6140  call_context_ = ", void* callContext";
6141  call_context_arg_ = ", callContext";
6142  call_context_decl_ = ", void*";
6143  }
6144 
6145  factory_class_name_ = class_name_ + "Factory";
6146 
6147  if (generator->gen_templates_) {
6148  template_header_ = "template <class Protocol_>\n";
6149  template_suffix_ = "<Protocol_>";
6150  typename_str_ = "typename ";
6151  class_name_ += "T";
6152  factory_class_name_ += "T";
6153  }
6154 
6155  if (service_->get_extends() != NULL) {
6156  extends_ = type_name(service_->get_extends()) + pstyle_ + "Processor";
6157  if (generator_->gen_templates_) {
6158  // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
6159  // parent services were also generated with templates enabled.
6160  extends_ += "T<Protocol_>";
6161  }
6163  } else {
6164  extends_processor_ = "::contrail::sandesh::T" + pstyle_ + "Processor";
6165  }
6166 }
6167 
6169  // Generate the dispatch methods
6170  vector<t_function*> functions = service_->get_functions();
6171  vector<t_function*>::iterator f_iter;
6172 
6173  // Generate the header portion
6174  f_header_ <<
6175  template_header_ <<
6176  "class " << class_name_ <<
6177  " : public " << extends_processor_ << " {" << endl;
6178 
6179  // Protected data members
6180  f_header_ <<
6181  " protected:" << endl;
6182  indent_up();
6183  f_header_ <<
6184  indent() << "boost::shared_ptr<" << if_name_ << "> iface_;" << endl;
6185  f_header_ <<
6186  indent() << "virtual " << ret_type_ << "process_fn(" << finish_cob_ << "contrail::sandesh::protocol::TProtocol* iprot, contrail::sandesh::protocol::TProtocol* oprot, std::string& fname, int32_t seqid" << call_context_ << ");" << endl;
6187  indent_down();
6188 
6189  // Process function declarations
6190  f_header_ <<
6191  " private:" << endl;
6192  indent_up();
6193  f_header_ <<
6194  indent() << "std::map<std::string, void (" <<
6195  class_name_ << "::*)(" << finish_cob_decl_ <<
6196  "int32_t, contrail::sandesh::protocol::TProtocol*, " <<
6197  "contrail::sandesh::protocol::TProtocol*" << call_context_decl_ <<
6198  ")> processMap_;" << endl;
6199  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
6200  indent(f_header_) <<
6201  "void process_" << (*f_iter)->get_name() << "(" << finish_cob_ << "int32_t seqid, contrail::sandesh::protocol::TProtocol* iprot, contrail::sandesh::protocol::TProtocol* oprot" << call_context_ << ");" << endl;
6202  if (generator_->gen_templates_) {
6203  indent(f_header_) <<
6204  "void process_" << (*f_iter)->get_name() << "(" << finish_cob_ <<
6205  "int32_t seqid, Protocol_* iprot, Protocol_* oprot" <<
6206  call_context_ << ");" << endl;
6207  }
6208  if (style_ == "Cob") {
6209  // XXX Factor this out, even if it is a pain.
6210  string ret_arg = ((*f_iter)->get_returntype()->is_void()
6211  ? ""
6212  : ", const " + type_name((*f_iter)->get_returntype()) + "& _return");
6213  f_header_ <<
6214  indent() << "void return_" << (*f_iter)->get_name() <<
6215  "(std::tr1::function<void(bool ok)> cob, int32_t seqid, " <<
6216  "::contrail::sandesh::protocol::TProtocol* oprot, " <<
6217  "void* ctx" << ret_arg << ");" << endl;
6218  if (generator_->gen_templates_) {
6219  f_header_ <<
6220  indent() << "void return_" << (*f_iter)->get_name() <<
6221  "(std::tr1::function<void(bool ok)> cob, int32_t seqid, " <<
6222  "Protocol_* oprot, void* ctx" << ret_arg << ");" << endl;
6223  }
6224  // XXX Don't declare throw if it doesn't exist
6225  f_header_ <<
6226  indent() << "void throw_" << (*f_iter)->get_name() <<
6227  "(std::tr1::function<void(bool ok)> cob, int32_t seqid, " <<
6228  "contrail::sandesh::protocol::TProtocol* oprot, void* ctx, " <<
6229  "contrail::sandesh::TDelayedException* _throw);" << endl;
6230  if (generator_->gen_templates_) {
6231  f_header_ <<
6232  indent() << "void throw_" << (*f_iter)->get_name() <<
6233  "(std::tr1::function<void(bool ok)> cob, int32_t seqid, " <<
6234  "Protocol_* oprot, void* ctx, " <<
6235  "::contrail::sandesh::TDelayedException* _throw);" << endl;
6236  }
6237  }
6238  }
6239  indent_down();
6240 
6241  indent_up();
6242  string declare_map = "";
6243  indent_up();
6244 
6245  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
6246  declare_map += indent();
6247  declare_map += "processMap_[\"";
6248  declare_map += (*f_iter)->get_name();
6249  declare_map += "\"] = &";
6250  declare_map += class_name_;
6251  declare_map += "::process_";
6252  declare_map += (*f_iter)->get_name();
6253  declare_map += ";\n";
6254  }
6255  indent_down();
6256 
6257  f_header_ <<
6258  " public:" << endl <<
6259  indent() << class_name_ <<
6260  "(boost::shared_ptr<" << if_name_ << "> iface) :" << endl;
6261  if (extends_.empty()) {
6262  f_header_ <<
6263  indent() << " iface_(iface) {" << endl;
6264  } else {
6265  f_header_ <<
6266  indent() << " " << extends_ << "(iface)," << endl <<
6267  indent() << " iface_(iface) {" << endl;
6268  }
6269  f_header_ <<
6270  declare_map <<
6271  indent() << "}" << endl <<
6272  endl <<
6273  indent() << "virtual " << ret_type_ << "process(" << finish_cob_ << "boost::shared_ptr<contrail::sandesh::protocol::TProtocol> piprot, boost::shared_ptr<contrail::sandesh::protocol::TProtocol> poprot" << call_context_ << ");" << endl <<
6274  indent() << "virtual ~" << class_name_ <<
6275  "() {}" << endl;
6276  indent_down();
6277  f_header_ <<
6278  "};" << endl << endl;
6279 
6280  if (generator_->gen_templates_) {
6281  // Generate a backwards compatible typedef, for callers who don't know
6282  // about the new template-style code.
6283  //
6284  // We can't use TProtocol as the template parameter, since ProcessorT
6285  // provides overloaded versions of most methods, one of which accepts
6286  // TProtocol pointers, and one which accepts Protocol_ pointers. This
6287  // results in a compile error if instantiated with Protocol_ == TProtocol.
6288  // Therefore, we define TDummyProtocol solely so we can use it as the
6289  // template parameter here.
6290  f_header_ <<
6291  "typedef " << class_name_ <<
6292  "<contrail::sandesh::protocol::TDummyProtocol> " <<
6293  service_name_ << pstyle_ << "Processor;" << endl << endl;
6294  }
6295 }
6296 
6298  f_out_ <<
6299  template_header_ <<
6300  ret_type_ << class_name_ <<
6301  template_suffix_ << "::process(" << finish_cob_ <<
6302  "boost::shared_ptr<contrail::sandesh::protocol::TProtocol> piprot, " <<
6303  "boost::shared_ptr<contrail::sandesh::protocol::TProtocol> poprot" <<
6304  call_context_ << ") {" << endl;
6305  indent_up();
6306 
6307  f_out_ <<
6308  endl <<
6309  indent() << "::contrail::sandesh::protocol::TProtocol* iprot = piprot.get();" << endl <<
6310  indent() << "::contrail::sandesh::protocol::TProtocol* oprot = poprot.get();" << endl <<
6311  indent() << "std::string fname;" << endl <<
6312  indent() << "::contrail::sandesh::protocol::TMessageType mtype;" << endl <<
6313  indent() << "int32_t seqid;" << endl <<
6314  endl <<
6315  indent() << "iprot->readMessageBegin(fname, mtype, seqid);" << endl <<
6316  endl <<
6317  indent() << "if (mtype != ::contrail::sandesh::protocol::T_CALL && mtype != ::contrail::sandesh::protocol::T_ONEWAY) {" << endl <<
6318  indent() << " iprot->skip(::contrail::sandesh::protocol::T_STRUCT);" << endl <<
6319  indent() << " iprot->readMessageEnd();" << endl <<
6320  indent() << " iprot->getTransport()->readEnd();" << endl <<
6321  indent() << " ::contrail::sandesh::TApplicationException x(::contrail::sandesh::TApplicationException::INVALID_MESSAGE_TYPE);" << endl <<
6322  indent() << " oprot->writeMessageBegin(fname, ::contrail::sandesh::protocol::T_EXCEPTION, seqid);" << endl <<
6323  indent() << " x.write(oprot);" << endl <<
6324  indent() << " oprot->writeMessageEnd();" << endl <<
6325  indent() << " oprot->getTransport()->writeEnd();" << endl <<
6326  indent() << " oprot->getTransport()->flush();" << endl <<
6327  indent() << (style_ == "Cob" ? " return cob(true);" : " return true;") << endl <<
6328  indent() << "}" << endl <<
6329  endl <<
6330  indent() << "return process_fn(" << (style_ == "Cob" ? "cob, " : "")
6331  << "iprot, oprot, fname, seqid" << call_context_arg_ << ");" <<
6332  endl;
6333 
6334  indent_down();
6335  f_out_ <<
6336  indent() << "}" << endl <<
6337  endl;
6338 }
6339 
6341  f_out_ <<
6342  template_header_ <<
6343  ret_type_ << class_name_ <<
6344  template_suffix_ << "::process_fn(" << finish_cob_ <<
6345  "contrail::sandesh::protocol::TProtocol* iprot, " <<
6346  "contrail::sandesh::protocol::TProtocol* oprot, " <<
6347  "std::string& fname, int32_t seqid" << call_context_ << ") {" << endl;
6348  indent_up();
6349 
6350  // HOT: member function pointer map
6351  f_out_ <<
6352  indent() << typename_str_ << "std::map<std::string, void (" <<
6353  class_name_ << "::*)(" << finish_cob_decl_ <<
6354  "int32_t, contrail::sandesh::protocol::TProtocol*, " <<
6355  "contrail::sandesh::protocol::TProtocol*" << call_context_decl_ << ")>::iterator pfn;" << endl <<
6356  indent() << "pfn = processMap_.find(fname);" << endl <<
6357  indent() << "if (pfn == processMap_.end()) {" << endl;
6358  if (extends_.empty()) {
6359  f_out_ <<
6360  indent() << " iprot->skip(contrail::sandesh::protocol::T_STRUCT);" << endl <<
6361  indent() << " iprot->readMessageEnd();" << endl <<
6362  indent() << " iprot->getTransport()->readEnd();" << endl <<
6363  indent() << " ::contrail::sandesh::TApplicationException x(::contrail::sandesh::TApplicationException::UNKNOWN_METHOD, \"Invalid method name: '\"+fname+\"'\");" << endl <<
6364  indent() << " oprot->writeMessageBegin(fname, ::contrail::sandesh::protocol::T_EXCEPTION, seqid);" << endl <<
6365  indent() << " x.write(oprot);" << endl <<
6366  indent() << " oprot->writeMessageEnd();" << endl <<
6367  indent() << " oprot->getTransport()->writeEnd();" << endl <<
6368  indent() << " oprot->getTransport()->flush();" << endl <<
6369  indent() << (style_ == "Cob" ? " return cob(true);" : " return true;") << endl;
6370  } else {
6371  f_out_ <<
6372  indent() << " return "
6373  << extends_ << "::process_fn("
6374  << (style_ == "Cob" ? "cob, " : "")
6375  << "iprot, oprot, fname, seqid" << call_context_arg_ << ");" << endl;
6376  }
6377  f_out_ <<
6378  indent() << "}" << endl <<
6379  indent() << "(this->*(pfn->second))(" << cob_arg_ << "seqid, iprot, oprot" << call_context_arg_ << ");" << endl;
6380 
6381  // TODO(dreiss): return pfn ret?
6382  if (style_ == "Cob") {
6383  f_out_ <<
6384  indent() << "return;" << endl;
6385  } else {
6386  f_out_ <<
6387  indent() << "return true;" << endl;
6388  }
6389 
6390  indent_down();
6391  f_out_ <<
6392  "}" << endl <<
6393  endl;
6394 }
6395 
6397  vector<t_function*> functions = service_->get_functions();
6398  vector<t_function*>::iterator f_iter;
6399  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
6400  if (generator_->gen_templates_) {
6403  } else {
6405  }
6406  }
6407 }
6408 
6410  string if_factory_name = if_name_ + "Factory";
6411 
6412  // Generate the factory class definition
6413  f_header_ <<
6414  template_header_ <<
6415  "class " << factory_class_name_ <<
6416  " : public ::contrail::sandesh::" <<
6417  (style_ == "Cob" ? "async::TAsyncProcessorFactory" : "TProcessorFactory") <<
6418  " {" << endl <<
6419  " public:" << endl;
6420  indent_up();
6421 
6422  f_header_ <<
6423  indent() << factory_class_name_ << "(const ::boost::shared_ptr< " <<
6424  if_factory_name << " >& handlerFactory) :" << endl <<
6425  indent() << " handlerFactory_(handlerFactory) {}" << endl <<
6426  endl <<
6427  indent() << "::boost::shared_ptr< ::contrail::sandesh::" <<
6428  (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " <<
6429  "getProcessor(const ::contrail::sandesh::TConnectionInfo& connInfo);" <<
6430  endl;
6431 
6432  f_header_ <<
6433  endl <<
6434  " protected:" << endl <<
6435  indent() << "::boost::shared_ptr< " << if_factory_name <<
6436  " > handlerFactory_;" << endl;
6437 
6438  indent_down();
6439  f_header_ <<
6440  "};" << endl << endl;
6441 
6442  // If we are generating templates, output a typedef for the plain
6443  // factory name.
6444  if (generator_->gen_templates_) {
6445  f_header_ <<
6446  "typedef " << factory_class_name_ <<
6447  "< ::contrail::sandesh::protocol::TDummyProtocol > " <<
6448  service_name_ << pstyle_ << "ProcessorFactory;" << endl << endl;
6449  }
6450 
6451  // Generate the getProcessor() method
6452  f_out_ <<
6453  template_header_ <<
6454  indent() << "::boost::shared_ptr< ::contrail::sandesh::" <<
6455  (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " <<
6456  factory_class_name_ << template_suffix_ << "::getProcessor(" <<
6457  "const ::contrail::sandesh::TConnectionInfo& connInfo) {" << endl;
6458  indent_up();
6459 
6460  f_out_ <<
6461  indent() << "::contrail::sandesh::ReleaseHandler< " << if_factory_name <<
6462  " > cleanup(handlerFactory_);" << endl <<
6463  indent() << "::boost::shared_ptr< " << if_name_ << " > handler(" <<
6464  "handlerFactory_->getHandler(connInfo), cleanup);" << endl <<
6465  indent() << "::boost::shared_ptr< ::contrail::sandesh::" <<
6466  (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " <<
6467  "processor(new " << class_name_ << template_suffix_ <<
6468  "(handler));" << endl <<
6469  indent() << "return processor;" << endl;
6470 
6471  indent_down();
6472  f_out_ <<
6473  indent() << "}" << endl;
6474 }
6475 
6482  string style) {
6483  ProcessorGenerator generator(this, tservice, style);
6484  generator.run();
6485 }
6486 
6493  t_function* tfunction) {
6494  if (tfunction->is_oneway()) {
6495  return;
6496  }
6497 
6498  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
6499 
6500  t_struct result(program_, tservice->get_name() + "_" + tfunction->get_name() + "_result");
6501  t_field success(tfunction->get_returntype(), "success", 0);
6502  if (!tfunction->get_returntype()->is_void()) {
6503  result.append(&success);
6504  }
6505 
6506  t_struct* xs = tfunction->get_xceptions();
6507  const vector<t_field*>& fields = xs->get_members();
6508  vector<t_field*>::const_iterator f_iter;
6509  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
6510  result.append(*f_iter);
6511  }
6512 
6513  generate_struct_definition(f_header_, &result, false);
6514  generate_struct_reader(out, &result);
6515  generate_struct_result_writer(out, &result);
6516 
6517  result.set_name(tservice->get_name() + "_" + tfunction->get_name() + "_presult");
6518  generate_struct_definition(f_header_, &result, false, true, true, gen_cob_style_);
6519  generate_struct_reader(out, &result, true);
6520  if (gen_cob_style_) {
6521  generate_struct_writer(out, &result, true);
6522  }
6523 
6524 }
6525 
6532  t_function* tfunction,
6533  string style,
6534  bool specialized) {
6535  t_struct* arg_struct = tfunction->get_arglist();
6536  const std::vector<t_field*>& fields = arg_struct->get_members();
6537  vector<t_field*>::const_iterator f_iter;
6538 
6539  t_struct* xs = tfunction->get_xceptions();
6540  const std::vector<t_field*>& xceptions = xs->get_members();
6541  vector<t_field*>::const_iterator x_iter;
6542  string service_func_name = tservice->get_name() + "." +
6543  tfunction->get_name();
6544 
6545  std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
6546 
6547  string prot_type =
6548  (specialized ? "Protocol_" : "::contrail::sandesh::protocol::TProtocol");
6549  string class_suffix;
6550  if (gen_templates_) {
6551  class_suffix = "T<Protocol_>";
6552  }
6553 
6554  // I tried to do this as one function. I really did. But it was too hard.
6555  if (style != "Cob") {
6556  // Open function
6557  if (gen_templates_) {
6558  out <<
6559  indent() << "template <class Protocol_>" << endl;
6560  }
6561  const bool unnamed_oprot_seqid = tfunction->is_oneway() &&
6562  !(gen_templates_ && !specialized);
6563  out <<
6564  "void " << tservice->get_name() << "Processor" << class_suffix << "::" <<
6565  "process_" << tfunction->get_name() << "(" <<
6566  "int32_t" << (unnamed_oprot_seqid ? ", " : " seqid, ") <<
6567  prot_type << "* iprot, " <<
6568  prot_type << "*" << (unnamed_oprot_seqid ? ", " : " oprot, ") <<
6569  "void* callContext)" << endl;
6570  scope_up(out);
6571 
6572  if (gen_templates_ && !specialized) {
6573  // If these are instances of Protocol_, instead of any old TProtocol,
6574  // use the specialized process function instead.
6575  out <<
6576  indent() << "Protocol_* _iprot = dynamic_cast<Protocol_*>(iprot);" <<
6577  endl <<
6578  indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" <<
6579  endl <<
6580  indent() << "if (_iprot && _oprot) {" << endl <<
6581  indent() << " return process_" << tfunction->get_name() <<
6582  "(seqid, _iprot, _oprot, callContext);" << endl <<
6583  indent() << "}" << endl <<
6584  indent() << "T_GENERIC_PROTOCOL(this, iprot, _iprot);" << endl <<
6585  indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl << endl;
6586  }
6587 
6588  string argsname = tservice->get_name() + "_" + tfunction->get_name() +
6589  "_args";
6590  string resultname = tservice->get_name() + "_" + tfunction->get_name() +
6591  "_result";
6592 
6593  out <<
6594  indent() << "void* ctx = NULL;" << endl <<
6595  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6596  indent() << " ctx = this->eventHandler_->getContext(\"" <<
6597  service_func_name << "\", callContext);" << endl <<
6598  indent() << "}" << endl <<
6599  indent() << "contrail::sandesh::TProcessorContextFreer freer(" <<
6600  "this->eventHandler_.get(), ctx, \"" << service_func_name << "\");" <<
6601  endl << endl <<
6602  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6603  indent() << " this->eventHandler_->preRead(ctx, \"" <<
6604  service_func_name << "\");" << endl <<
6605  indent() << "}" << endl << endl <<
6606  indent() << argsname << " args;" << endl <<
6607  indent() << "args.read(iprot);" << endl <<
6608  indent() << "iprot->readMessageEnd();" << endl <<
6609  indent() << "uint32_t bytes = iprot->getTransport()->readEnd();" <<
6610  endl << endl <<
6611  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6612  indent() << " this->eventHandler_->postRead(ctx, \"" <<
6613  service_func_name << "\", bytes);" << endl <<
6614  indent() << "}" << endl <<
6615  endl;
6616 
6617  // Declare result
6618  if (!tfunction->is_oneway()) {
6619  out <<
6620  indent() << resultname << " result;" << endl;
6621  }
6622 
6623  // Try block for functions with exceptions
6624  out <<
6625  indent() << "try {" << endl;
6626  indent_up();
6627 
6628  // Generate the function call
6629  bool first = true;
6630  out << indent();
6631  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
6632  if (is_complex_type(tfunction->get_returntype())) {
6633  first = false;
6634  out << "iface_->" << tfunction->get_name() << "(result.success";
6635  } else {
6636  out << "result.success = iface_->" << tfunction->get_name() << "(";
6637  }
6638  } else {
6639  out <<
6640  "iface_->" << tfunction->get_name() << "(";
6641  }
6642  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
6643  if (first) {
6644  first = false;
6645  } else {
6646  out << ", ";
6647  }
6648  out << "args." << (*f_iter)->get_name();
6649  }
6650  out << ");" << endl;
6651 
6652  // Set isset on success field
6653  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
6654  out <<
6655  indent() << "result.__isset.success = true;" << endl;
6656  }
6657 
6658  indent_down();
6659  out << indent() << "}";
6660 
6661  if (!tfunction->is_oneway()) {
6662  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
6663  out << " catch (" << type_name((*x_iter)->get_type()) << " &" <<
6664  (*x_iter)->get_name() << ") {" << endl;
6665  if (!tfunction->is_oneway()) {
6666  indent_up();
6667  out <<
6668  indent() << "result." << (*x_iter)->get_name() << " = " <<
6669  (*x_iter)->get_name() << ";" << endl <<
6670  indent() << "result.__isset." << (*x_iter)->get_name() <<
6671  " = true;" << endl;
6672  indent_down();
6673  out << indent() << "}";
6674  } else {
6675  out << "}";
6676  }
6677  }
6678  }
6679 
6680  out << " catch (const std::exception& e) {" << endl;
6681 
6682  indent_up();
6683  out <<
6684  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6685  indent() << " this->eventHandler_->handlerError(ctx, \"" <<
6686  service_func_name << "\");" << endl <<
6687  indent() << "}" << endl;
6688 
6689  if (!tfunction->is_oneway()) {
6690  out <<
6691  endl <<
6692  indent() << "contrail::sandesh::TApplicationException x(e.what());" <<
6693  endl <<
6694  indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() <<
6695  "\", contrail::sandesh::protocol::T_EXCEPTION, seqid);" << endl <<
6696  indent() << "x.write(oprot);" << endl <<
6697  indent() << "oprot->writeMessageEnd();" << endl <<
6698  indent() << "oprot->getTransport()->writeEnd();" << endl <<
6699  indent() << "oprot->getTransport()->flush();" << endl;
6700  }
6701  out << indent() << "return;" << endl;
6702  indent_down();
6703  out << indent() << "}" << endl << endl;
6704 
6705  // Shortcut out here for oneway functions
6706  if (tfunction->is_oneway()) {
6707  out <<
6708  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6709  indent() << " this->eventHandler_->asyncComplete(ctx, \"" <<
6710  service_func_name << "\");" << endl <<
6711  indent() << "}" << endl << endl <<
6712  indent() << "return;" << endl;
6713  indent_down();
6714  out << "}" << endl <<
6715  endl;
6716  return;
6717  }
6718 
6719  // Serialize the result into a struct
6720  out <<
6721  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6722  indent() << " this->eventHandler_->preWrite(ctx, \"" <<
6723  service_func_name << "\");" << endl <<
6724  indent() << "}" << endl << endl <<
6725  indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() <<
6726  "\", contrail::sandesh::protocol::T_REPLY, seqid);" << endl <<
6727  indent() << "result.write(oprot);" << endl <<
6728  indent() << "oprot->writeMessageEnd();" << endl <<
6729  indent() << "bytes = oprot->getTransport()->writeEnd();" << endl <<
6730  indent() << "oprot->getTransport()->flush();" << endl << endl <<
6731  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6732  indent() << " this->eventHandler_->postWrite(ctx, \"" <<
6733  service_func_name << "\", bytes);" << endl <<
6734  indent() << "}" << endl;
6735 
6736  // Close function
6737  scope_down(out);
6738  out << endl;
6739  }
6740 
6741  // Cob style.
6742  else {
6743  // Processor entry point.
6744  // TODO(edhall) update for callContext when TEventServer is ready
6745  if (gen_templates_) {
6746  out <<
6747  indent() << "template <class Protocol_>" << endl;
6748  }
6749  out <<
6750  "void " << tservice->get_name() << "AsyncProcessor" << class_suffix <<
6751  "::process_" << tfunction->get_name() <<
6752  "(std::tr1::function<void(bool ok)> cob, int32_t seqid, " <<
6753  prot_type << "* iprot, " << prot_type << "* oprot)" << endl;
6754  scope_up(out);
6755 
6756  // TODO(simpkins): we could try to consoldate this
6757  // with the non-cob code above
6758  if (gen_templates_ && !specialized) {
6759  // If these are instances of Protocol_, instead of any old TProtocol,
6760  // use the specialized process function instead.
6761  out <<
6762  indent() << "Protocol_* _iprot = dynamic_cast<Protocol_*>(iprot);" <<
6763  endl <<
6764  indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" <<
6765  endl <<
6766  indent() << "if (_iprot && _oprot) {" << endl <<
6767  indent() << " return process_" << tfunction->get_name() <<
6768  "(cob, seqid, _iprot, _oprot);" << endl <<
6769  indent() << "}" << endl <<
6770  indent() << "T_GENERIC_PROTOCOL(this, iprot, _iprot);" << endl <<
6771  indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl << endl;
6772  }
6773 
6774  if (tfunction->is_oneway()) {
6775  out <<
6776  indent() << "(void) seqid;" << endl <<
6777  indent() << "(void) oprot;" << endl;
6778  }
6779 
6780  out <<
6781  indent() << tservice->get_name() + "_" + tfunction->get_name() <<
6782  "_args args;" << endl <<
6783  indent() << "void* ctx = NULL;" << endl <<
6784  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6785  indent() << " ctx = this->eventHandler_->getContext(\"" <<
6786  service_func_name << "\", NULL);" << endl <<
6787  indent() << "}" << endl <<
6788  indent() << "contrail::sandesh::TProcessorContextFreer freer(" <<
6789  "this->eventHandler_.get(), ctx, \"" << service_func_name << "\");" <<
6790  endl << endl <<
6791  indent() << "try {" << endl;
6792  indent_up();
6793  out <<
6794  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6795  indent() << " this->eventHandler_->preRead(ctx, \"" <<
6796  service_func_name << "\");" << endl <<
6797  indent() << "}" << endl <<
6798  indent() << "args.read(iprot);" << endl <<
6799  indent() << "iprot->readMessageEnd();" << endl <<
6800  indent() << "uint32_t bytes = iprot->getTransport()->readEnd();" <<
6801  endl <<
6802  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6803  indent() << " this->eventHandler_->postRead(ctx, \"" <<
6804  service_func_name << "\", bytes);" << endl <<
6805  indent() << "}" << endl;
6806  scope_down(out);
6807 
6808  // TODO(dreiss): Handle TExceptions? Expose to server?
6809  out <<
6810  indent() << "catch (const std::exception& exn) {" << endl <<
6811  indent() << " if (this->eventHandler_.get() != NULL) {" << endl <<
6812  indent() << " this->eventHandler_->handlerError(ctx, \"" <<
6813  service_func_name << "\");" << endl <<
6814  indent() << " }" << endl <<
6815  indent() << " return cob(false);" << endl <<
6816  indent() << "}" << endl;
6817 
6818  if (tfunction->is_oneway()) {
6819  out <<
6820  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6821  indent() << " this->eventHandler_->asyncComplete(ctx, \"" <<
6822  service_func_name << "\");" << endl <<
6823  indent() << "}" << endl;
6824  }
6825  // TODO(dreiss): Figure out a strategy for exceptions in async handlers.
6826  out <<
6827  indent() << "freer.unregister();" << endl;
6828  if (tfunction->is_oneway()) {
6829  // No return. Just hand off our cob.
6830  // TODO(dreiss): Call the cob immediately?
6831  out <<
6832  indent() << "iface_->" << tfunction->get_name() << "(" <<
6833  "std::tr1::bind(cob, true)" << endl;
6834  indent_up(); indent_up();
6835  } else {
6836  string ret_arg, ret_placeholder;
6837  if (!tfunction->get_returntype()->is_void()) {
6838  ret_arg = ", const " + type_name(tfunction->get_returntype()) +
6839  "& _return";
6840  ret_placeholder = ", std::tr1::placeholders::_1";
6841  }
6842 
6843  // When gen_templates_ is true, the return_ and throw_ functions are
6844  // overloaded. We have to declare pointers to them so that the compiler
6845  // can resolve the correct overloaded version.
6846  out <<
6847  indent() << "void (" << tservice->get_name() << "AsyncProcessor" <<
6848  class_suffix << "::*return_fn)(std::tr1::function<void(bool ok)> " <<
6849  "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" <<
6850  ret_arg << ") =" << endl;
6851  out <<
6852  indent() << " &" << tservice->get_name() << "AsyncProcessor" <<
6853  class_suffix << "::return_" << tfunction->get_name() << ";" << endl;
6854  if (!xceptions.empty()) {
6855  out <<
6856  indent() << "void (" << tservice->get_name() << "AsyncProcessor" <<
6857  class_suffix << "::*throw_fn)(std::tr1::function<void(bool ok)> " <<
6858  "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, " <<
6859  "::contrail::sandesh::TDelayedException* _throw) =" << endl;
6860  out <<
6861  indent() << " &" << tservice->get_name() << "AsyncProcessor" <<
6862  class_suffix << "::throw_" << tfunction->get_name() << ";" << endl;
6863  }
6864 
6865  out <<
6866  indent() << "iface_->" << tfunction->get_name() << "(" << endl;
6867  indent_up(); indent_up();
6868  out <<
6869  indent() << "std::tr1::bind(return_fn, this, cob, seqid, oprot, ctx" <<
6870  ret_placeholder << ")";
6871  if (!xceptions.empty()) {
6872  out
6873  << ',' << endl <<
6874  indent() << "std::tr1::bind(throw_fn, this, cob, seqid, oprot, " <<
6875  "ctx, std::tr1::placeholders::_1)";
6876  }
6877  }
6878 
6879  // XXX Whitespace cleanup.
6880  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
6881  out
6882  << ',' << endl <<
6883  indent() << "args." << (*f_iter)->get_name();
6884  }
6885  out << ");" << endl;
6886  indent_down(); indent_down();
6887  scope_down(out);
6888  out << endl;
6889 
6890  // Normal return.
6891  if (!tfunction->is_oneway()) {
6892  string ret_arg_decl, ret_arg_name;
6893  if (!tfunction->get_returntype()->is_void()) {
6894  ret_arg_decl = ", const " + type_name(tfunction->get_returntype()) +
6895  "& _return";
6896  ret_arg_name = ", _return";
6897  }
6898  if (gen_templates_) {
6899  out <<
6900  indent() << "template <class Protocol_>" << endl;
6901  }
6902  out <<
6903  "void " << tservice->get_name() << "AsyncProcessor" << class_suffix <<
6904  "::return_" << tfunction->get_name() <<
6905  "(std::tr1::function<void(bool ok)> cob, int32_t seqid, " <<
6906  prot_type << "* oprot, void* ctx" << ret_arg_decl << ')' << endl;
6907  scope_up(out);
6908 
6909  if (gen_templates_ && !specialized) {
6910  // If oprot is a Protocol_ instance,
6911  // use the specialized return function instead.
6912  out <<
6913  indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" <<
6914  endl <<
6915  indent() << "if (_oprot) {" << endl <<
6916  indent() << " return return_" << tfunction->get_name() <<
6917  "(cob, seqid, _oprot, ctx" << ret_arg_name << ");" << endl <<
6918  indent() << "}" << endl <<
6919  indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" <<
6920  endl << endl;
6921  }
6922 
6923  out <<
6924  indent() << tservice->get_name() << "_" << tfunction->get_name() <<
6925  "_presult result;" << endl;
6926  if (!tfunction->get_returntype()->is_void()) {
6927  // The const_cast here is unfortunate, but it would be a pain to avoid,
6928  // and we only do a write with this struct, which is const-safe.
6929  out <<
6930  indent() << "result.success = const_cast<" <<
6931  type_name(tfunction->get_returntype()) << "*>(&_return);" <<
6932  endl <<
6933  indent() << "result.__isset.success = true;" << endl;
6934  }
6935  // Serialize the result into a struct
6936  out <<
6937  endl <<
6938  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6939  indent() << " ctx = this->eventHandler_->getContext(\"" <<
6940  service_func_name << "\", NULL);" << endl <<
6941  indent() << "}" << endl <<
6942  indent() << "contrail::sandesh::TProcessorContextFreer freer(" <<
6943  "this->eventHandler_.get(), ctx, \"" << service_func_name <<
6944  "\");" << endl << endl <<
6945  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6946  indent() << " this->eventHandler_->preWrite(ctx, \"" <<
6947  service_func_name << "\");" << endl <<
6948  indent() << "}" << endl << endl <<
6949  indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() <<
6950  "\", contrail::sandesh::protocol::T_REPLY, seqid);" << endl <<
6951  indent() << "result.write(oprot);" << endl <<
6952  indent() << "oprot->writeMessageEnd();" << endl <<
6953  indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" <<
6954  endl <<
6955  indent() << "oprot->getTransport()->flush();" << endl <<
6956  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6957  indent() << " this->eventHandler_->postWrite(ctx, \"" <<
6958  service_func_name << "\", bytes);" << endl <<
6959  indent() << "}" << endl <<
6960  indent() << "return cob(true);" << endl;
6961  scope_down(out);
6962  out << endl;
6963  }
6964 
6965  // Exception return.
6966  if (!tfunction->is_oneway() && !xceptions.empty()) {
6967  if (gen_templates_) {
6968  out <<
6969  indent() << "template <class Protocol_>" << endl;
6970  }
6971  out <<
6972  "void " << tservice->get_name() << "AsyncProcessor" << class_suffix <<
6973  "::throw_" << tfunction->get_name() <<
6974  "(std::tr1::function<void(bool ok)> cob, int32_t seqid, " <<
6975  prot_type << "* oprot, void* ctx, " <<
6976  "::contrail::sandesh::TDelayedException* _throw)" << endl;
6977  scope_up(out);
6978 
6979  if (gen_templates_ && !specialized) {
6980  // If oprot is a Protocol_ instance,
6981  // use the specialized throw function instead.
6982  out <<
6983  indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" <<
6984  endl <<
6985  indent() << "if (_oprot) {" << endl <<
6986  indent() << " return throw_" << tfunction->get_name() <<
6987  "(cob, seqid, _oprot, ctx, _throw);" << endl <<
6988  indent() << "}" << endl <<
6989  indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" <<
6990  endl << endl;
6991  }
6992 
6993  // Get the event handler context
6994  out <<
6995  endl <<
6996  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
6997  indent() << " ctx = this->eventHandler_->getContext(\"" <<
6998  service_func_name << "\", NULL);" << endl <<
6999  indent() << "}" << endl <<
7000  indent() << "contrail::sandesh::TProcessorContextFreer freer(" <<
7001  "this->eventHandler_.get(), ctx, \"" << service_func_name << "\");" <<
7002  endl << endl;
7003 
7004  // Throw the TDelayedException, and catch the result
7005  out <<
7006  indent() << tservice->get_name() << "_" << tfunction->get_name() <<
7007  "_result result;" << endl << endl <<
7008  indent() << "try {" << endl;
7009  indent_up();
7010  out <<
7011  indent() << "_throw->throw_it();" << endl <<
7012  indent() << "return cob(false);" << endl; // Is this possible? TBD.
7013  indent_down();
7014  out <<
7015  indent() << '}';
7016  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
7017  out << " catch (" << type_name((*x_iter)->get_type()) << " &" <<
7018  (*x_iter)->get_name() << ") {" << endl;
7019  indent_up();
7020  out <<
7021  indent() << "result." << (*x_iter)->get_name() << " = " <<
7022  (*x_iter)->get_name() << ";" << endl <<
7023  indent() << "result.__isset." << (*x_iter)->get_name() <<
7024  " = true;" << endl;
7025  scope_down(out);
7026  }
7027 
7028  // Handle the case where an undeclared exception is thrown
7029  out << " catch (std::exception& e) {" << endl;
7030  indent_up();
7031  out <<
7032  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
7033  indent() << " this->eventHandler_->handlerError(ctx, \"" <<
7034  service_func_name << "\");" << endl <<
7035  indent() << "}" << endl <<
7036  endl <<
7037  indent() << "contrail::sandesh::TApplicationException x(e.what());" <<
7038  endl <<
7039  indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() <<
7040  "\", contrail::sandesh::protocol::T_EXCEPTION, seqid);" << endl <<
7041  indent() << "x.write(oprot);" << endl <<
7042  indent() << "oprot->writeMessageEnd();" << endl <<
7043  indent() << "oprot->getTransport()->writeEnd();" << endl <<
7044  indent() << "oprot->getTransport()->flush();" << endl <<
7045  // We pass true to the cob here, since we did successfully write a
7046  // response, even though it is an exception response.
7047  // It looks like the argument is currently ignored, anyway.
7048  indent() << "return cob(true);" << endl;
7049  scope_down(out);
7050 
7051  // Serialize the result into a struct
7052  out <<
7053  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
7054  indent() << " this->eventHandler_->preWrite(ctx, \"" <<
7055  service_func_name << "\");" << endl <<
7056  indent() << "}" << endl << endl <<
7057  indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() <<
7058  "\", contrail::sandesh::protocol::T_REPLY, seqid);" << endl <<
7059  indent() << "result.write(oprot);" << endl <<
7060  indent() << "oprot->writeMessageEnd();" << endl <<
7061  indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" <<
7062  endl <<
7063  indent() << "oprot->getTransport()->flush();" << endl <<
7064  indent() << "if (this->eventHandler_.get() != NULL) {" << endl <<
7065  indent() << " this->eventHandler_->postWrite(ctx, \"" <<
7066  service_func_name << "\", bytes);" << endl <<
7067  indent() << "}" << endl <<
7068  indent() << "return cob(true);" << endl;
7069  scope_down(out);
7070  out << endl;
7071  } // for each function
7072  } // cob style
7073 }
7074 
7081  string svcname = tservice->get_name();
7082 
7083  // Service implementation file includes
7084  string f_skeleton_name = get_out_dir()+svcname+"_server.skeleton.cpp";
7085 
7086  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
7087 
7088  ofstream f_skeleton;
7089  f_skeleton.open(f_skeleton_name.c_str());
7090  f_skeleton <<
7091  "// This autogenerated skeleton file illustrates how to build a server." << endl <<
7092  "// You should copy it to another filename to avoid overwriting it." << endl <<
7093  endl <<
7094  "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl <<
7095  "#include <protocol/TBinaryProtocol.h>" << endl <<
7096  "#include <server/TSimpleServer.h>" << endl <<
7097  "#include <transport/TServerSocket.h>" << endl <<
7098  "#include <transport/TBufferTransports.h>" << endl <<
7099  endl <<
7100  "using namespace ::contrail::sandesh;" << endl <<
7101  "using namespace ::contrail::sandesh::protocol;" << endl <<
7102  "using namespace ::contrail::sandesh::transport;" << endl <<
7103  "using namespace ::contrail::sandesh::server;" << endl <<
7104  endl <<
7105  "using boost::shared_ptr;" << endl <<
7106  endl;
7107 
7108  if (!ns.empty()) {
7109  f_skeleton <<
7110  "using namespace " << string(ns, 0, ns.size()-2) << ";" << endl <<
7111  endl;
7112  }
7113 
7114  f_skeleton <<
7115  "class " << svcname << "Handler : virtual public " << svcname << "If {" << endl <<
7116  " public:" << endl;
7117  indent_up();
7118  f_skeleton <<
7119  indent() << svcname << "Handler() {" << endl <<
7120  indent() << " // Your initialization goes here" << endl <<
7121  indent() << "}" << endl <<
7122  endl;
7123 
7124  vector<t_function*> functions = tservice->get_functions();
7125  vector<t_function*>::iterator f_iter;
7126  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
7127  f_skeleton <<
7128  indent() << function_signature(*f_iter, "") << " {" << endl <<
7129  indent() << " // Your implementation goes here" << endl <<
7130  indent() << " printf(\"" << (*f_iter)->get_name() << "\\n\");" << endl <<
7131  indent() << "}" << endl <<
7132  endl;
7133  }
7134 
7135  indent_down();
7136  f_skeleton <<
7137  "};" << endl <<
7138  endl;
7139 
7140  f_skeleton <<
7141  indent() << "int main(int argc, char **argv) {" << endl;
7142  indent_up();
7143  f_skeleton <<
7144  indent() << "int port = 9090;" << endl <<
7145  indent() << "shared_ptr<" << svcname << "Handler> handler(new " << svcname << "Handler());" << endl <<
7146  indent() << "shared_ptr<TProcessor> processor(new " << svcname << "Processor(handler));" << endl <<
7147  indent() << "shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));" << endl <<
7148  indent() << "shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());" << endl <<
7149  indent() << "shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());" << endl <<
7150  endl <<
7151  indent() << "TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);" << endl <<
7152  indent() << "server.serve();" << endl <<
7153  indent() << "return 0;" << endl;
7154  indent_down();
7155  f_skeleton <<
7156  "}" << endl <<
7157  endl;
7158 
7159  // Close the files
7160  f_skeleton.close();
7161 }
7162 
7167  t_field* tfield,
7168  string prefix,
7169  string suffix) {
7170  t_type* type = get_true_type(tfield->get_type());
7171 
7172  if (type->is_void()) {
7173  throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " +
7174  prefix + tfield->get_name();
7175  }
7176 
7177  string name = prefix + tfield->get_name() + suffix;
7178 
7179  if (type->is_struct() || type->is_xception()) {
7180  generate_deserialize_struct(out, (t_struct*)type, name);
7181  } else if (type->is_container()) {
7182  generate_deserialize_container(out, type, name);
7183  } else if (type->is_base_type()) {
7184  indent(out) <<
7185  "if ((ret = iprot->";
7186  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
7187  switch (tbase) {
7189  throw "compiler error: cannot serialize void field in a struct: " + name;
7190  break;
7192 #ifdef SANDESH
7193  case t_base_type::TYPE_STATIC_CONST_STRING:
7194 #endif
7195  if (((t_base_type*)type)->is_binary()) {
7196  out << "readBinary(" << name << ")) < 0) {" << endl;
7197  }
7198  else {
7199  out << "readString(" << name << ")) < 0) {" << endl;
7200  }
7201  break;
7202 #ifdef SANDESH
7203  case t_base_type::TYPE_XML:
7204  out << "readXML(" << name << ")) < 0) {" << endl;
7205  break;
7206  case t_base_type::TYPE_UUID:
7207  out << "readUUID(" << name << ")) < 0) {" << endl;
7208  break;
7209 #endif
7211  out << "readBool(" << name << ")) < 0) {" << endl;
7212  break;
7214  out << "readByte(" << name << ")) < 0) {" << endl;
7215  break;
7216  case t_base_type::TYPE_I16:
7217  out << "readI16(" << name << ")) < 0) {" << endl;
7218  break;
7219  case t_base_type::TYPE_I32:
7220  out << "readI32(" << name << ")) < 0) {" << endl;
7221  break;
7222  case t_base_type::TYPE_I64:
7223  out << "readI64(" << name << ")) < 0) {" << endl;
7224  break;
7225 #ifdef SANDESH
7226  case t_base_type::TYPE_U16:
7227  out << "readU16(" << name << ")) < 0) {" << endl;
7228  break;
7229  case t_base_type::TYPE_U32:
7230  out << "readU32(" << name << ")) < 0) {" << endl;
7231  break;
7232  case t_base_type::TYPE_U64:
7233  out << "readU64(" << name << ")) < 0) {" << endl;
7234  break;
7235  case t_base_type::TYPE_IPV4:
7236  out << "readIPV4(" << name << ")) < 0) {" << endl;
7237  break;
7238  case t_base_type::TYPE_IPADDR:
7239  out << "readIPADDR(" << name << ")) < 0) {" << endl;
7240  break;
7241 #endif
7243  out << "readDouble(" << name << ")) < 0) {" << endl;
7244  break;
7245  default:
7246  throw "compiler error: no C++ reader for base type " + t_base_type::t_base_name(tbase) + name;
7247  }
7248  indent_up();
7249  out << indent() << "return ret;" << endl;
7250  scope_down(out);
7251  out << indent() << "xfer += ret;" << endl;
7252  out <<
7253  endl;
7254  } else if (type->is_enum()) {
7255  string t = tmp("ecast");
7256  out <<
7257  indent() << "int32_t " << t << ";" << endl <<
7258  indent() << "if ((ret = iprot->readI32(" << t << ")) < 0) {" << endl <<
7259  indent() << " return ret;" << endl <<
7260  indent() << "}" << endl <<
7261  indent() << "xfer += ret;" << endl <<
7262  indent() << name << " = (" << type_name(type) << ")" << t << ";" << endl;
7263  } else {
7264  printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
7265  tfield->get_name().c_str(), type_name(type).c_str());
7266  }
7267 }
7268 
7276  t_struct* tstruct,
7277  string prefix) {
7278  (void) tstruct;
7279  indent(out) <<
7280  "if ((ret = " << prefix << ".read(iprot)) < 0) {" << endl;
7281  indent_up();
7282  indent(out) << "return ret;" << endl;
7283  scope_down(out);
7284  indent(out) << "xfer += ret;" << endl;
7285 }
7286 
7288  t_type* ttype,
7289  string prefix) {
7290  scope_up(out);
7291 
7292  string size = tmp("_size");
7293  string ktype = tmp("_ktype");
7294  string vtype = tmp("_vtype");
7295  string etype = tmp("_etype");
7296 
7297  t_container* tcontainer = (t_container*)ttype;
7298  bool use_push = tcontainer->has_cpp_name();
7299 
7300  indent(out) <<
7301  prefix << ".clear();" << endl <<
7302  indent() << "uint32_t " << size << ";" << endl;
7303 
7304  // Declare variables, read header
7305  if (ttype->is_map()) {
7306  out <<
7307  indent() << "::contrail::sandesh::protocol::TType " << ktype << ";" << endl <<
7308  indent() << "::contrail::sandesh::protocol::TType " << vtype << ";" << endl <<
7309  indent() << "if ((ret = iprot->readMapBegin(" <<
7310  ktype << ", " << vtype << ", " << size << ")) < 0) {" << endl <<
7311  indent() << " return ret;" << endl <<
7312  indent() << "}" << endl <<
7313  indent() << "xfer += ret;" << endl;
7314  } else if (ttype->is_set()) {
7315  out <<
7316  indent() << "::contrail::sandesh::protocol::TType " << etype << ";" << endl <<
7317  indent() << "if ((ret = iprot->readSetBegin(" <<
7318  etype << ", " << size << ")) < 0) {" << endl <<
7319  indent() << " return ret;" << endl <<
7320  indent() << "}" << endl <<
7321  indent() << "xfer += ret;" << endl;
7322  } else if (ttype->is_list()) {
7323  out <<
7324  indent() << "::contrail::sandesh::protocol::TType " << etype << ";" << endl <<
7325  indent() << "if ((ret = iprot->readListBegin(" <<
7326  etype << ", " << size << ")) < 0) {" << endl <<
7327  indent() << " return ret;" << endl <<
7328  indent() << "}" << endl <<
7329  indent() << "xfer += ret;" << endl;
7330  if (!use_push) {
7331  indent(out) << prefix << ".resize(" << size << ");" << endl;
7332  }
7333  }
7334 
7335 
7336  // For loop iterates over elements
7337  string i = tmp("_i");
7338  out <<
7339  indent() << "uint32_t " << i << ";" << endl <<
7340  indent() << "for (" << i << " = 0; " << i << " < " << size << "; ++" << i << ")" << endl;
7341 
7342  scope_up(out);
7343 
7344  if (ttype->is_map()) {
7345  generate_deserialize_map_element(out, (t_map*)ttype, prefix);
7346  } else if (ttype->is_set()) {
7347 #ifdef SANDESH
7348  t_type *etype = ((t_set*)ttype)->get_elem_type();
7349  if (etype->is_base_type() || etype->is_enum()) {
7350  indent(out) << "if ((ret = iprot->readContainerElementBegin()) < 0) {" << endl;
7351  indent_up();
7352  indent(out) << "return ret;" << endl;
7353  scope_down(out);
7354  indent(out) << "xfer += ret;" << endl;
7355  }
7356 #endif
7357  generate_deserialize_set_element(out, (t_set*)ttype, prefix);
7358 #ifdef SANDESH
7359  if (etype->is_base_type() || etype->is_enum()) {
7360  indent(out) << "if ((ret = iprot->readContainerElementEnd()) < 0) {" << endl;
7361  indent_up();
7362  indent(out) << "return ret;" << endl;
7363  scope_down(out);
7364  indent(out) << "xfer += ret;" << endl;
7365  }
7366 #endif
7367  } else if (ttype->is_list()) {
7368 #ifdef SANDESH
7369  t_type *etype = ((t_list*)ttype)->get_elem_type();
7370  if (etype->is_base_type() || etype->is_enum()) {
7371  indent(out) << "if ((ret = iprot->readContainerElementBegin()) < 0) {" << endl;
7372  indent_up();
7373  indent(out) << "return ret;" << endl;
7374  scope_down(out);
7375  indent(out) << "xfer += ret;" << endl;
7376  }
7377 #endif
7378  generate_deserialize_list_element(out, (t_list*)ttype, prefix, use_push, i);
7379 #ifdef SANDESH
7380  if (etype->is_base_type() || etype->is_enum()) {
7381  indent(out) << "if ((ret = iprot->readContainerElementEnd()) < 0) {" << endl;
7382  indent_up();
7383  indent(out) << "return ret;" << endl;
7384  scope_down(out);
7385  indent(out) << "xfer += ret;" << endl;
7386  }
7387 #endif
7388  }
7389 
7390  scope_down(out);
7391 
7392  // Read container end
7393  if (ttype->is_map()) {
7394 #ifdef SANDESH
7395  indent(out) << "if ((ret = iprot->readMapEnd()) < 0) {" << endl;
7396  indent_up();
7397  indent(out) << "return ret;" << endl;
7398  scope_down(out);
7399  indent(out) << "xfer += ret;" << endl;
7400 #else
7401  indent(out) << "iprot->readMapEnd();" << endl;
7402 #endif
7403  } else if (ttype->is_set()) {
7404 #ifdef SANDESH
7405  indent(out) << "if ((ret = iprot->readSetEnd()) < 0) {" << endl;
7406  indent_up();
7407  indent(out) << "return ret;" << endl;
7408  scope_down(out);
7409  indent(out) << "xfer += ret;" << endl;
7410 #else
7411  indent(out) << "iprot->readSetEnd();" << endl;
7412 #endif
7413  } else if (ttype->is_list()) {
7414 #ifdef SANDESH
7415  indent(out) << "if ((ret = iprot->readListEnd()) < 0) {" << endl;
7416  indent_up();
7417  indent(out) << "return ret;" << endl;
7418  scope_down(out);
7419  indent(out) << "xfer += ret;" << endl;
7420 #else
7421  indent(out) << "iprot->readListEnd();" << endl;
7422 #endif
7423  }
7424 
7425  scope_down(out);
7426 }
7427 
7428 
7433  t_map* tmap,
7434  string prefix) {
7435  string key = tmp("_key");
7436  string val = tmp("_val");
7437  t_field fkey(tmap->get_key_type(), key);
7438  t_field fval(tmap->get_val_type(), val);
7439 
7440  out <<
7441  indent() << declare_field(&fkey) << endl;
7442 
7443 #ifdef SANDESH
7444  t_type* kttype = tmap->get_key_type();
7445  if (kttype->is_base_type() || kttype->is_enum()) {
7446  indent(out) << "if ((ret = iprot->readContainerElementBegin()) < 0) {" << endl;
7447  indent_up();
7448  indent(out) << "return ret;" << endl;
7449  scope_down(out);
7450  indent(out) << "xfer += ret;" << endl;
7451  }
7452 #endif
7453  generate_deserialize_field(out, &fkey);
7454 #ifdef SANDESH
7455  if (kttype->is_base_type() || kttype->is_enum()) {
7456  indent(out) << "if ((ret = iprot->readContainerElementEnd()) < 0) {" << endl;
7457  indent_up();
7458  indent(out) << "return ret;" << endl;
7459  scope_down(out);
7460  indent(out) << "xfer += ret;" << endl;
7461  }
7462 #endif
7463  indent(out) <<
7464  declare_field(&fval, false, false, false, true) << " = " <<
7465  prefix << "[" << key << "];" << endl;
7466 
7467 #ifdef SANDESH
7468  t_type* vttype = tmap->get_val_type();
7469  if (vttype->is_base_type() || vttype->is_enum()) {
7470  indent(out) << "if ((ret = iprot->readContainerElementBegin()) < 0) {" << endl;
7471  indent_up();
7472  indent(out) << "return ret;" << endl;
7473  scope_down(out);
7474  indent(out) << "xfer += ret;" << endl;
7475  }
7476 #endif
7477  generate_deserialize_field(out, &fval);
7478 #ifdef SANDESH
7479  if (vttype->is_base_type() || vttype->is_enum()) {
7480  indent(out) << "if ((ret = iprot->readContainerElementEnd()) < 0) {" << endl;
7481  indent_up();
7482  indent(out) << "return ret;" << endl;
7483  scope_down(out);
7484  indent(out) << "xfer += ret;" << endl;
7485  }
7486 #endif
7487 }
7488 
7490  t_set* tset,
7491  string prefix) {
7492  string elem = tmp("_elem");
7493  t_field felem(tset->get_elem_type(), elem);
7494 
7495  indent(out) <<
7496  declare_field(&felem) << endl;
7497 
7498  generate_deserialize_field(out, &felem);
7499 
7500  indent(out) <<
7501  prefix << ".insert(" << elem << ");" << endl;
7502 }
7503 
7505  t_list* tlist,
7506  string prefix,
7507  bool use_push,
7508  string index) {
7509  if (use_push) {
7510  string elem = tmp("_elem");
7511  t_field felem(tlist->get_elem_type(), elem);
7512  indent(out) << declare_field(&felem) << endl;
7513  generate_deserialize_field(out, &felem);
7514  indent(out) << prefix << ".push_back(" << elem << ");" << endl;
7515  } else {
7516  t_field felem(tlist->get_elem_type(), prefix + "[" + index + "]");
7517  generate_deserialize_field(out, &felem);
7518  }
7519 }
7520 
7521 
7529  t_field* tfield,
7530  string prefix,
7531  string suffix) {
7532  t_type* type = get_true_type(tfield->get_type());
7533 
7534  string name = prefix + tfield->get_name() + suffix;
7535 
7536  // Do nothing for void types
7537  if (type->is_void()) {
7538  throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
7539  }
7540 
7541 
7542 
7543  if (type->is_struct() || type->is_xception()) {
7545  (t_struct*)type,
7546  name);
7547  } else if (type->is_container()) {
7548  generate_serialize_container(out, type, name);
7549  } else if (type->is_base_type() || type->is_enum()) {
7550 
7551  indent(out) <<
7552  "if ((ret = oprot->";
7553 
7554  if (type->is_base_type()) {
7555  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
7556  switch (tbase) {
7558  throw
7559  "compiler error: cannot serialize void field in a struct: " + name;
7560  break;
7562 #ifdef SANDESH
7563  case t_base_type::TYPE_STATIC_CONST_STRING:
7564 #endif
7565  if (((t_base_type*)type)->is_binary()) {
7566  out << "writeBinary(" << name << ")) < 0) {" << endl;
7567  }
7568  else {
7569  out << "writeString(" << name << ")) < 0) {" << endl;
7570  }
7571  break;
7572 #ifdef SANDESH
7573  case t_base_type::TYPE_XML:
7574  out << "writeXML(" << name << ")) < 0) {" << endl;
7575  break;
7576  case t_base_type::TYPE_UUID:
7577  out << "writeUUID(" << name << ")) < 0) {" << endl;
7578  break;
7579 #endif
7581  out << "writeBool(" << name << ")) < 0) {" << endl;
7582  break;
7584  out << "writeByte(" << name << ")) < 0) {" << endl;
7585  break;
7586  case t_base_type::TYPE_I16:
7587  out << "writeI16(" << name << ")) < 0) {" << endl;
7588  break;
7589  case t_base_type::TYPE_I32:
7590  out << "writeI32(" << name << ")) < 0) {" << endl;
7591  break;
7592  case t_base_type::TYPE_I64:
7593  out << "writeI64(" << name << ")) < 0) {" << endl;
7594  break;
7595 #ifdef SANDESH
7596  case t_base_type::TYPE_U16:
7597  out << "writeU16(" << name << ")) < 0) {" << endl;
7598  break;
7599  case t_base_type::TYPE_U32:
7600  out << "writeU32(" << name << ")) < 0) {" << endl;
7601  break;
7602  case t_base_type::TYPE_U64:
7603  out << "writeU64(" << name << ")) < 0) {" << endl;
7604  break;
7605  case t_base_type::TYPE_IPV4:
7606  out << "writeIPV4(" << name << ")) < 0) {" << endl;
7607  break;
7608  case t_base_type::TYPE_IPADDR:
7609  out << "writeIPADDR(" << name << ")) < 0) {" << endl;
7610  break;
7611 #endif
7613  out << "writeDouble(" << name << ")) < 0) {" << endl;
7614  break;
7615  default:
7616  throw "compiler error: no C++ writer for base type " + t_base_type::t_base_name(tbase) + name;
7617  }
7618  } else if (type->is_enum()) {
7619  out << "writeI32((int32_t)" << name << ")) < 0) {" << endl;
7620  }
7621  indent_up();
7622  out << indent() << "return ret;" << endl;
7623  scope_down(out);
7624  out << indent() << "xfer += ret;" << endl;
7625  out << endl;
7626 #ifdef SANDESH
7627  } else if (type->is_sandesh()) {
7628  generate_serialize_sandesh(out, (t_sandesh*)type, name);
7629 #endif
7630  } else {
7631  printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
7632  name.c_str(),
7633  type_name(type).c_str());
7634  }
7635 }
7636 
7637 #ifdef SANDESH
7638 
7644 void t_cpp_generator::generate_serialize_sandesh(ofstream& out,
7645  t_sandesh* tsandesh,
7646  string prefix) {
7647  (void) tsandesh;
7648  indent(out) <<
7649  "if ((ret = " << prefix << ".write(oprot)) < 0) {" << endl;
7650  indent_up();
7651  indent(out) << "return ret;" << endl;
7652  scope_down(out);
7653  indent(out) << "xfer += ret;" << endl;
7654 }
7655 #endif
7656 
7664  t_struct* tstruct,
7665  string prefix) {
7666  (void) tstruct;
7667  indent(out) <<
7668  "if ((ret = " << prefix << ".write(oprot)) < 0) {" << endl;
7669  indent_up();
7670  indent(out) << "return ret;" << endl;
7671  scope_down(out);
7672  indent(out) << "xfer += ret;" << endl;
7673 }
7674 
7676  t_type* ttype,
7677  string prefix) {
7678  scope_up(out);
7679 
7680  if (ttype->is_map()) {
7681  indent(out) <<
7682  "if ((ret = oprot->writeMapBegin(" <<
7683  type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
7684  type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
7685  "static_cast<uint32_t>(" << prefix << ".size()))) < 0) {" << endl;
7686  indent_up();
7687  indent(out) << "return ret;" << endl;
7688  scope_down(out);
7689  indent(out) << "xfer += ret;" << endl;
7690  } else if (ttype->is_set()) {
7691  indent(out) <<
7692  "if ((ret = oprot->writeSetBegin(" <<
7693  type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
7694  "static_cast<uint32_t>(" << prefix << ".size()))) < 0) {" << endl;
7695  indent_up();
7696  indent(out) << "return ret;" << endl;
7697  scope_down(out);
7698  indent(out) << "xfer += ret;" << endl;
7699  } else if (ttype->is_list()) {
7700  indent(out) <<
7701  "if ((ret = oprot->writeListBegin(" <<
7702  type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
7703  "static_cast<uint32_t>(" << prefix << ".size()))) < 0) {" << endl;
7704  indent_up();
7705  indent(out) << "return ret;" << endl;
7706  scope_down(out);
7707  indent(out) << "xfer += ret;" << endl;
7708  }
7709 
7710  string iter = tmp("_iter");
7711  out <<
7712  indent() << type_name(ttype) << "::const_iterator " << iter << ";" << endl <<
7713  indent() << "for (" << iter << " = " << prefix << ".begin(); " << iter << " != " << prefix << ".end(); ++" << iter << ")" << endl;
7714  scope_up(out);
7715  if (ttype->is_map()) {
7716  generate_serialize_map_element(out, (t_map*)ttype, iter);
7717  } else if (ttype->is_set()) {
7718 #ifdef SANDESH
7719  t_type *etype = ((t_set*)ttype)->get_elem_type();
7720  if (etype->is_base_type() || etype->is_enum()) {
7721  indent(out) << "if ((ret = oprot->writeContainerElementBegin()) < 0) {" << endl;
7722  indent_up();
7723  indent(out) << "return ret;" << endl;
7724  scope_down(out);
7725  indent(out) << "xfer += ret;" << endl;
7726  }
7727 #endif
7728  generate_serialize_set_element(out, (t_set*)ttype, iter);
7729 #ifdef SANDESH
7730  if (etype->is_base_type() || etype->is_enum()) {
7731  indent(out) << "if ((ret = oprot->writeContainerElementEnd()) < 0) {" << endl;
7732  indent_up();
7733  indent(out) << "return ret;" << endl;
7734  scope_down(out);
7735  indent(out) << "xfer += ret;" << endl;
7736  }
7737 #endif
7738  } else if (ttype->is_list()) {
7739 #ifdef SANDESH
7740  t_type *etype = ((t_list*)ttype)->get_elem_type();
7741  if (etype->is_base_type() || etype->is_enum()) {
7742  indent(out) << "if ((ret = oprot->writeContainerElementBegin()) < 0) {" << endl;
7743  indent_up();
7744  indent(out) << "return ret;" << endl;
7745  scope_down(out);
7746  indent(out) << "xfer += ret;" << endl;
7747  }
7748 #endif
7749  generate_serialize_list_element(out, (t_list*)ttype, iter);
7750 #ifdef SANDESH
7751  if (etype->is_base_type() || etype->is_enum()) {
7752  indent(out) << "if ((ret = oprot->writeContainerElementEnd()) < 0) {" << endl;
7753  indent_up();
7754  indent(out) << "return ret;" << endl;
7755  scope_down(out);
7756  indent(out) << "xfer += ret;" << endl;
7757  }
7758 #endif
7759  }
7760  scope_down(out);
7761 
7762  if (ttype->is_map()) {
7763  indent(out) <<
7764  "if ((ret = oprot->writeMapEnd()) < 0) {" << endl;
7765  indent_up();
7766  indent(out) << "return ret;" << endl;
7767  scope_down(out);
7768  indent(out) << "xfer += ret;" << endl;
7769  } else if (ttype->is_set()) {
7770  indent(out) <<
7771  "if ((ret = oprot->writeSetEnd()) < 0) {" << endl;
7772  indent_up();
7773  indent(out) << "return ret;" << endl;
7774  scope_down(out);
7775  indent(out) << "xfer += ret;" << endl;
7776  } else if (ttype->is_list()) {
7777  indent(out) <<
7778  "if ((ret = oprot->writeListEnd()) < 0) {" << endl;
7779  indent_up();
7780  indent(out) << "return ret;" << endl;
7781  scope_down(out);
7782  indent(out) << "xfer += ret;" << endl;
7783  }
7784 
7785  scope_down(out);
7786 }
7787 
7793  t_map* tmap,
7794  string iter) {
7795 #ifdef SANDESH
7796  t_type* kttype = tmap->get_key_type();
7797  if (kttype->is_base_type() || kttype->is_enum()) {
7798  indent(out) << "if ((ret = oprot->writeContainerElementBegin()) < 0) {" << endl;
7799  indent_up();
7800  indent(out) << "return ret;" << endl;
7801  scope_down(out);
7802  indent(out) << "xfer += ret;" << endl;
7803  }
7804 #endif
7805  t_field kfield(tmap->get_key_type(), iter + "->first");
7806  generate_serialize_field(out, &kfield, "");
7807 #ifdef SANDESH
7808  if (kttype->is_base_type() || kttype->is_enum()) {
7809  indent(out) << "if ((ret = oprot->writeContainerElementEnd()) < 0) {" << endl;
7810  indent_up();
7811  indent(out) << "return ret;" << endl;
7812  scope_down(out);
7813  indent(out) << "xfer += ret;" << endl;
7814  }
7815 #endif
7816 #ifdef SANDESH
7817  t_type* vttype = tmap->get_val_type();
7818  if (vttype->is_base_type() || vttype->is_enum()) {
7819  indent(out) << "if ((ret = oprot->writeContainerElementBegin()) < 0) {" << endl;
7820  indent_up();
7821  indent(out) << "return ret;" << endl;
7822  scope_down(out);
7823  indent(out) << "xfer += ret;" << endl;
7824  }
7825 #endif
7826  t_field vfield(tmap->get_val_type(), iter + "->second");
7827  generate_serialize_field(out, &vfield, "");
7828 #ifdef SANDESH
7829  if (vttype->is_base_type() || vttype->is_enum()) {
7830  indent(out) << "if ((ret = oprot->writeContainerElementEnd()) < 0) {" << endl;
7831  indent_up();
7832  indent(out) << "return ret;" << endl;
7833  scope_down(out);
7834  indent(out) << "xfer += ret;" << endl;
7835  }
7836 #endif
7837 }
7838 
7843  t_set* tset,
7844  string iter) {
7845  t_field efield(tset->get_elem_type(), "(*" + iter + ")");
7846  generate_serialize_field(out, &efield, "");
7847 }
7848 
7853  t_list* tlist,
7854  string iter) {
7855  t_field efield(tlist->get_elem_type(), "(*" + iter + ")");
7856  generate_serialize_field(out, &efield, "");
7857 }
7858 
7866  // Always start with "::", to avoid possible name collisions with
7867  // other names in one of the current namespaces.
7868  //
7869  // We also need a leading space, in case the name is used inside of a
7870  // template parameter. "MyTemplate<::foo::Bar>" is not valid C++,
7871  // since "<:" is an alternative token for "[".
7872  string result = " ::";
7873 
7874  if (ns.size() == 0) {
7875  return result;
7876  }
7877  string::size_type loc;
7878  while ((loc = ns.find(".")) != string::npos) {
7879  result += ns.substr(0, loc);
7880  result += "::";
7881  ns = ns.substr(loc+1);
7882  }
7883  if (ns.size() > 0) {
7884  result += ns + "::";
7885  }
7886  return result;
7887 }
7888 
7896  if (ns.size() == 0) {
7897  return "";
7898  }
7899  string result = "";
7900  string separator = "";
7901  string::size_type loc;
7902  while ((loc = ns.find(".")) != string::npos) {
7903  result += separator;
7904  result += "namespace ";
7905  result += ns.substr(0, loc);
7906  result += " {";
7907  separator = " ";
7908  ns = ns.substr(loc+1);
7909  }
7910  if (ns.size() > 0) {
7911  result += separator + "namespace " + ns + " {";
7912  }
7913  return result;
7914 }
7915 
7923  if (ns.size() == 0) {
7924  return "";
7925  }
7926  string result = "}";
7927  string::size_type loc;
7928  while ((loc = ns.find(".")) != string::npos) {
7929  result += "}";
7930  ns = ns.substr(loc+1);
7931  }
7932  result += " // namespace";
7933  return result;
7934 }
7935 
7942 string t_cpp_generator::type_name(t_type* ttype, bool in_typedef, bool arg) {
7943  if (ttype->is_base_type()) {
7944  string bname = base_type_name(((t_base_type*)ttype)->get_base());
7945  if (!arg) {
7946  return bname;
7947  }
7948 
7949  if (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING
7950 #ifdef SANDESH
7951  || ((t_base_type*)ttype)->get_base() == t_base_type::TYPE_XML
7952  || ((t_base_type*)ttype)->get_base() == t_base_type::TYPE_UUID
7953  || ((t_base_type*)ttype)->get_base() == t_base_type::TYPE_IPADDR
7954 #endif
7955  ) {
7956  return "const " + bname + "&";
7957  } else {
7958  return "const " + bname;
7959  }
7960  }
7961 
7962  // Check for a custom overloaded C++ name
7963  if (ttype->is_container()) {
7964  string cname;
7965 
7966  t_container* tcontainer = (t_container*) ttype;
7967  if (tcontainer->has_cpp_name()) {
7968  cname = tcontainer->get_cpp_name();
7969  } else if (ttype->is_map()) {
7970  t_map* tmap = (t_map*) ttype;
7971  cname = "std::map<" +
7972  type_name(tmap->get_key_type(), in_typedef) + ", " +
7973  type_name(tmap->get_val_type(), in_typedef) + "> ";
7974  } else if (ttype->is_set()) {
7975  t_set* tset = (t_set*) ttype;
7976  cname = "std::set<" + type_name(tset->get_elem_type(), in_typedef) + "> ";
7977  } else if (ttype->is_list()) {
7978  t_list* tlist = (t_list*) ttype;
7979  cname = "std::vector<" + type_name(tlist->get_elem_type(), in_typedef) + "> ";
7980  }
7981 
7982  if (arg) {
7983  return "const " + cname + "&";
7984  } else {
7985  return cname;
7986  }
7987  }
7988 
7989  string class_prefix;
7990  if (in_typedef && (ttype->is_struct() || ttype->is_xception())) {
7991  class_prefix = "class ";
7992  }
7993 
7994  // Check if it needs to be namespaced
7995  string pname;
7996  t_program* program = ttype->get_program();
7997  if (program != NULL && program != program_) {
7998  pname =
7999  class_prefix +
8000  namespace_prefix(program->get_namespace("cpp")) +
8001  ttype->get_name();
8002  } else {
8003  pname = class_prefix + ttype->get_name();
8004  }
8005 
8006  if (ttype->is_enum() && !gen_pure_enums_) {
8007  pname += "::type";
8008  }
8009 
8010  if (arg) {
8011  if (is_complex_type(ttype)) {
8012  return "const " + pname + "&";
8013  } else {
8014  return "const " + pname;
8015  }
8016  } else {
8017  return pname;
8018  }
8019 }
8020 
8028  switch (tbase) {
8030  return "void";
8031 #ifdef SANDESH
8032  case t_base_type::TYPE_STATIC_CONST_STRING:
8033  return "static std::string";
8034 #endif
8036 #ifdef SANDESH
8037  case t_base_type::TYPE_XML:
8038 #endif
8039  return "std::string";
8041  return "bool";
8043  return "int8_t";
8044  case t_base_type::TYPE_I16:
8045  return "int16_t";
8046  case t_base_type::TYPE_I32:
8047  return "int32_t";
8048  case t_base_type::TYPE_I64:
8049  return "int64_t";
8050 #ifdef SANDESH
8051  case t_base_type::TYPE_U16:
8052  return "uint16_t";
8053  case t_base_type::TYPE_U32:
8054  return "uint32_t";
8055  case t_base_type::TYPE_U64:
8056  return "uint64_t";
8057  case t_base_type::TYPE_IPV4:
8058  return "uint32_t";
8059  case t_base_type::TYPE_IPADDR:
8060  return "boost::asio::ip::address";
8061  case t_base_type::TYPE_UUID:
8062  return "boost::uuids::uuid";
8063 #endif
8065  return "double";
8066  default:
8067  throw "compiler error: no C++ base type name for base type " + t_base_type::t_base_name(tbase);
8068  }
8069 }
8070 
8077 #ifdef SANDESH
8078 string t_cpp_generator::declare_field(t_field* tfield, bool init, bool pointer, bool constant, bool reference, bool constructor) {
8079 #else
8080 string t_cpp_generator::declare_field(t_field* tfield, bool init, bool pointer, bool constant, bool reference) {
8081 #endif
8082  // TODO(mcslee): do we ever need to initialize the field?
8083  string result = "";
8084  if (constant) {
8085  result += "const ";
8086  }
8087  result += type_name(tfield->get_type());
8088  if (pointer) {
8089  result += "*";
8090  }
8091  if (reference) {
8092  result += "&";
8093  }
8094  result += " " + tfield->get_name();
8095  if (init) {
8096  t_type* type = get_true_type(tfield->get_type());
8097 
8098  if (type->is_base_type()) {
8099  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
8100  switch (tbase) {
8102  break;
8103 #ifdef SANDESH
8104  case t_base_type::TYPE_UUID:
8105  result += " = boost::uuids::nil_uuid()";
8106  break;
8107  case t_base_type::TYPE_STATIC_CONST_STRING:
8108  case t_base_type::TYPE_XML:
8109 #endif
8111  result += " = \"\"";
8112  break;
8114  result += " = false";
8115  break;
8117  case t_base_type::TYPE_I16:
8118  case t_base_type::TYPE_I32:
8119  case t_base_type::TYPE_I64:
8120 #ifdef SANDESH
8121  case t_base_type::TYPE_U16:
8122  case t_base_type::TYPE_U32:
8123  case t_base_type::TYPE_U64:
8124  case t_base_type::TYPE_IPV4:
8125 #endif
8126  result += " = 0";
8127  break;
8129  result += " = (double)0";
8130  break;
8131 #ifdef SANDESH
8132  case t_base_type::TYPE_IPADDR:
8133  result += " = boost::asio::ip::address()";
8134  break;
8135 #endif
8136  default:
8137  throw "compiler error: no C++ initializer for base type " + t_base_type::t_base_name(tbase);
8138  }
8139  } else if (type->is_enum()) {
8140  result += " = (" + type_name(type) + ")0";
8141  }
8142  }
8143  if (!reference
8144 #ifdef SANDESH
8145  && !constructor
8146 #endif
8147  ) {
8148  result += ";";
8149  }
8150  return result;
8151 }
8152 
8160  string style,
8161  string prefix,
8162  bool name_params) {
8163  t_type* ttype = tfunction->get_returntype();
8164  t_struct* arglist = tfunction->get_arglist();
8165  bool has_xceptions = !tfunction->get_xceptions()->get_members().empty();
8166 #ifdef SANDESH
8167  bool is_static = tfunction->is_static();
8168  bool is_virtual = tfunction->is_virtual();
8169  string func_begin_modifier = "", func_end_modifier = "";
8170 #endif
8171 
8172 #ifdef SANDESH
8173  if (is_static) {
8174  func_begin_modifier = "static ";
8175  } else if (is_virtual) {
8176  func_begin_modifier = "virtual ";
8177  func_end_modifier = " = 0";
8178  }
8179 #endif
8180 
8181  if (style == "") {
8182  if (is_complex_type(ttype)) {
8183  return
8184 #ifdef SANDESH
8185  func_begin_modifier +
8186 #endif
8187  "void " + prefix + tfunction->get_name() +
8188  "(" + type_name(ttype) + (name_params ? "& _return" : "& /* _return */") +
8189  argument_list(arglist, name_params, true) + ")"
8190 #ifdef SANDESH
8191  + func_end_modifier
8192 #endif
8193  ;
8194  } else {
8195  return
8196 #ifdef SANDESH
8197  func_begin_modifier +
8198 #endif
8199  type_name(ttype) + " " + prefix + tfunction->get_name() +
8200  "(" + argument_list(arglist, name_params) + ")"
8201 #ifdef SANDESH
8202  + func_end_modifier
8203 #endif
8204  ;
8205  }
8206  } else if (style.substr(0,3) == "Cob") {
8207  string cob_type;
8208  string exn_cob;
8209  if (style == "CobCl") {
8210  cob_type = "(" + service_name_ + "CobClient";
8211  if (gen_templates_) {
8212  cob_type += "T<Protocol_>";
8213  }
8214  cob_type += "* client)";
8215  } else if (style =="CobSv") {
8216  cob_type = (ttype->is_void()
8217  ? "()"
8218  : ("(" + type_name(ttype) + " const& _return)"));
8219  if (has_xceptions) {
8220  exn_cob = ", std::tr1::function<void(::contrail::sandesh::TDelayedException* _throw)> /* exn_cob */";
8221  }
8222  } else {
8223  throw "UNKNOWN STYLE";
8224  }
8225 
8226  return
8227  "void " + prefix + tfunction->get_name() +
8228  "(std::tr1::function<void" + cob_type + "> cob" + exn_cob +
8229  argument_list(arglist, name_params, true) + ")";
8230  } else {
8231  throw "UNKNOWN STYLE";
8232  }
8233 }
8234 
8241 string t_cpp_generator::argument_list(t_struct* tstruct, bool name_params, bool start_comma) {
8242  string result = "";
8243 
8244  const vector<t_field*>& fields = tstruct->get_members();
8245  vector<t_field*>::const_iterator f_iter;
8246  bool first = !start_comma;
8247  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
8248  if (first) {
8249  first = false;
8250  } else {
8251  result += ", ";
8252  }
8253  result += type_name((*f_iter)->get_type(), false, true) + " " +
8254  (name_params ? (*f_iter)->get_name() : "/* " + (*f_iter)->get_name() + " */");
8255  }
8256  return result;
8257 }
8258 
8266  type = get_true_type(type);
8267 
8268  if (type->is_base_type()) {
8269  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
8270  switch (tbase) {
8272  throw "NO T_VOID CONSTRUCT";
8274  return "::contrail::sandesh::protocol::T_STRING";
8276  return "::contrail::sandesh::protocol::T_BOOL";
8278  return "::contrail::sandesh::protocol::T_BYTE";
8279  case t_base_type::TYPE_I16:
8280  return "::contrail::sandesh::protocol::T_I16";
8281  case t_base_type::TYPE_I32:
8282  return "::contrail::sandesh::protocol::T_I32";
8283  case t_base_type::TYPE_I64:
8284  return "::contrail::sandesh::protocol::T_I64";
8286  return "::contrail::sandesh::protocol::T_DOUBLE";
8287 #ifdef SANDESH
8288  case t_base_type::TYPE_XML:
8289  return "::contrail::sandesh::protocol::T_XML";
8290  case t_base_type::TYPE_UUID:
8291  return "::contrail::sandesh::protocol::T_UUID";
8292  case t_base_type::TYPE_U16:
8293  return "::contrail::sandesh::protocol::T_U16";
8294  case t_base_type::TYPE_U32:
8295  return "::contrail::sandesh::protocol::T_U32";
8296  case t_base_type::TYPE_U64:
8297  return "::contrail::sandesh::protocol::T_U64";
8298  case t_base_type::TYPE_IPV4:
8299  return "::contrail::sandesh::protocol::T_IPV4";
8300  case t_base_type::TYPE_IPADDR:
8301  return "::contrail::sandesh::protocol::T_IPADDR";
8302  case t_base_type::TYPE_STATIC_CONST_STRING:
8303  case t_base_type::TYPE_SANDESH_SYSTEM:
8304  case t_base_type::TYPE_SANDESH_REQUEST:
8305  case t_base_type::TYPE_SANDESH_RESPONSE:
8306  case t_base_type::TYPE_SANDESH_TRACE:
8307  case t_base_type::TYPE_SANDESH_TRACE_OBJECT:
8308  case t_base_type::TYPE_SANDESH_BUFFER:
8309  case t_base_type::TYPE_SANDESH_UVE:
8310  case t_base_type::TYPE_SANDESH_ALARM:
8311  case t_base_type::TYPE_SANDESH_OBJECT:
8312  case t_base_type::TYPE_SANDESH_FLOW:
8313  case t_base_type::TYPE_SANDESH_SESSION:
8314  return "::contrail::sandesh::protocol::T_STRING";
8315 #endif
8316  }
8317  } else if (type->is_enum()) {
8318  return "::contrail::sandesh::protocol::T_I32";
8319  } else if (type->is_struct()) {
8320  return "::contrail::sandesh::protocol::T_STRUCT";
8321  } else if (type->is_xception()) {
8322  return "::contrail::sandesh::protocol::T_STRUCT";
8323 #ifdef SANDESH
8324  } else if (type->is_sandesh()) {
8325  return "::contrail::sandesh::protocol::T_SANDESH";
8326 #endif
8327  } else if (type->is_map()) {
8328  return "::contrail::sandesh::protocol::T_MAP";
8329  } else if (type->is_set()) {
8330  return "::contrail::sandesh::protocol::T_SET";
8331  } else if (type->is_list()) {
8332  return "::contrail::sandesh::protocol::T_LIST";
8333  }
8334 
8335  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
8336 }
8337 
8341 string t_cpp_generator::local_reflection_name(const char* prefix, t_type* ttype, bool external) {
8342  ttype = get_true_type(ttype);
8343 
8344  // We have to use the program name as part of the identifier because
8345  // if two thrift "programs" are compiled into one actual program
8346  // you would get a symbol collision if they both defined list<i32>.
8347  // trlo = Thrift Reflection LOcal.
8348  string prog;
8349  string name;
8350  string nspace;
8351 
8352  // TODO(dreiss): Would it be better to pregenerate the base types
8353  // and put them in Thrift.{h,cpp} ?
8354 
8355  if (ttype->is_base_type()) {
8356  prog = program_->get_name();
8357  name = ttype->get_ascii_fingerprint();
8358  } else if (ttype->is_enum()) {
8359  assert(ttype->get_program() != NULL);
8360  prog = ttype->get_program()->get_name();
8361  name = ttype->get_ascii_fingerprint();
8362  } else if (ttype->is_container()) {
8363  prog = program_->get_name();
8364  name = ttype->get_ascii_fingerprint();
8365  } else {
8366  assert(ttype->is_struct() || ttype->is_xception());
8367  assert(ttype->get_program() != NULL);
8368  prog = ttype->get_program()->get_name();
8369  name = ttype->get_ascii_fingerprint();
8370  }
8371 
8372  if (external &&
8373  ttype->get_program() != NULL &&
8374  ttype->get_program() != program_) {
8375  nspace = namespace_prefix(ttype->get_program()->get_namespace("cpp"));
8376  }
8377 
8378  return nspace + "trlo_" + prefix + "_" + prog + "_" + name;
8379 }
8380 
8381 string t_cpp_generator::get_include_prefix(const t_program& program) const {
8382  string include_prefix = program.get_include_prefix();
8383  if (!use_include_prefix_ ||
8384  (include_prefix.size() > 0 && include_prefix[0] == '/')) {
8385  // if flag is turned off or this is absolute path, return empty prefix
8386  return "";
8387  }
8388 
8389  string::size_type last_slash = string::npos;
8390  if ((last_slash = include_prefix.rfind("/")) != string::npos) {
8391  return include_prefix.substr(0, last_slash) + "/" + out_dir_base_ + "/";
8392  }
8393 
8394  return "";
8395 }
8396 
8398  std::ofstream& out,
8399  t_struct_common* tstruct,
8400  bool pointers) {
8401  indent_up();
8402 
8403  std::string struct_type_name = tstruct->get_struct_type_name();
8404 
8405  const vector<t_field*>& fields = tstruct->get_members();
8406  vector<t_field*>::const_iterator f_iter;
8407 
8408  // Declare stack tmp variables
8409  out <<
8410  endl <<
8411  indent() << "int32_t xfer = 0, ret;" << endl <<
8412  indent() << "std::string fname;" << endl <<
8413  indent() << "::contrail::sandesh::protocol::TType ftype;" << endl <<
8414  indent() << "int16_t fid;" << endl <<
8415  endl <<
8416  indent() <<
8417  "if ((ret = iprot->read" << struct_type_name << "Begin(fname)) < 0) {" <<
8418  endl <<
8419  indent() << " return ret;" << endl <<
8420  indent() << "}" << endl <<
8421  indent() << "xfer += ret;" << endl <<
8422  endl;
8423 
8424  // Required variables aren't in __isset, so we need tmp vars to check them.
8425  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
8426  if ((*f_iter)->get_req() == t_field::T_REQUIRED)
8427  indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl;
8428  }
8429  out << endl;
8430 
8431  // Loop over reading in fields
8432  indent(out) <<
8433  "while (true)" << endl;
8434  scope_up(out);
8435 
8436  // Read beginning field marker
8437  indent(out) <<
8438  "if ((ret = iprot->readFieldBegin(fname, ftype, fid)) < 0) {" << endl;
8439  indent_up();
8440  indent(out) << "return ret;" << endl;
8441  scope_down(out);
8442  indent(out) << "xfer += ret;" << endl;
8443 
8444  // Check for field STOP marker
8445  out <<
8446  indent() << "if (ftype == ::contrail::sandesh::protocol::T_STOP) {" << endl <<
8447  indent() << " break;" << endl <<
8448  indent() << "}" << endl;
8449 
8450  // Generate 'switch' statement only when there is at least
8451  // one 'case' in it. Otherwise, generate just the contents
8452  // of 'default' label, without a 'switch'.
8453  if (fields.empty()) {
8454  out <<
8455  indent() << "if ((ret = iprot->skip(ftype)) < 0) {" << endl <<
8456  indent() << " return ret;" << endl <<
8457  indent() << "}" << endl <<
8458  indent() << "xfer += ret;" << endl;
8459  } else {
8460  // Switch statement on the field we are reading
8461  indent(out) <<
8462  "switch (fid)" << endl;
8463 
8464  scope_up(out);
8465 
8466  // Generate deserialization code for known cases
8467  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
8468  indent(out) <<
8469  "case " << (*f_iter)->get_key() << ":" << endl;
8470  indent_up();
8471  indent(out) <<
8472  "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
8473  indent_up();
8474 
8475  const char *isset_prefix =
8476  ((*f_iter)->get_req() != t_field::T_REQUIRED) ? "this->__isset." : "isset_";
8477 
8478 #if 0
8479  // This code throws an exception if the same field is encountered twice.
8480  // We've decided to leave it out for performance reasons.
8481  // TODO(dreiss): Generate this code and "if" it out to make it easier
8482  // for people recompiling thrift to include it.
8483  out <<
8484  indent() << "if (" << isset_prefix << (*f_iter)->get_name() << ")" << endl <<
8485  indent() << " throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
8486 #endif
8487 
8488  if (pointers && !(*f_iter)->get_type()->is_xception()) {
8489  generate_deserialize_field(out, *f_iter, "(*(this->", "))");
8490  } else {
8491  generate_deserialize_field(out, *f_iter, "this->");
8492  }
8493  out <<
8494  indent() << isset_prefix << (*f_iter)->get_name() << " = true;" << endl;
8495  indent_down();
8496  out <<
8497  indent() << "} else {" << endl <<
8498  indent() << " if ((ret = iprot->skip(ftype)) < 0) {" << endl <<
8499  indent() << " return ret;" << endl <<
8500  indent() << " }" << endl <<
8501  indent() << " xfer += ret;" << endl <<
8502  // TODO(dreiss): Make this an option when thrift structs
8503  // have a common base class.
8504  // indent() << " throw TProtocolException(TProtocolException::INVALID_DATA);" << endl <<
8505  indent() << "}" << endl <<
8506  indent() << "break;" << endl;
8507  indent_down();
8508  }
8509 
8510  // In the default case we skip the field
8511  out <<
8512  indent() << "default:" << endl <<
8513  indent() << " if ((ret = iprot->skip(ftype)) < 0) {" << endl <<
8514  indent() << " return ret;" << endl <<
8515  indent() << " }" << endl <<
8516  indent() << " xfer += ret;" << endl <<
8517  indent() << " break;" << endl;
8518 
8519  scope_down(out);
8520  }
8521 
8522  // Read field end marker
8523  indent(out) <<
8524  "if ((ret = iprot->readFieldEnd()) < 0) {" << endl;
8525  indent_up();
8526  indent(out) << "return ret;" << endl;
8527  scope_down(out);
8528  indent(out) << "xfer += ret;" << endl;
8529 
8530  scope_down(out);
8531 
8532  out <<
8533  endl <<
8534  indent() <<
8535  "if ((ret = iprot->read" << struct_type_name << "End()) < 0) {" << endl;
8536 
8537  indent_up();
8538  indent(out) << "return ret;" << endl;
8539  scope_down(out);
8540  indent(out) << "xfer += ret;" << endl;
8541 
8542  // Throw if any required fields are missing.
8543  // We do this after reading the struct end so that
8544  // there might possibly be a chance of continuing.
8545  out << endl;
8546  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
8547  if ((*f_iter)->get_req() == t_field::T_REQUIRED)
8548  out <<
8549  indent() << "if (!isset_" << (*f_iter)->get_name() << ") {" << endl <<
8550  indent() << " LOG(ERROR, __func__ << \": Required field " << (*f_iter)->get_name()
8551  << " not set\");" << endl <<
8552  indent() << " return -1;" << endl <<
8553  indent() << "}" << endl;
8554  }
8555 
8556  indent(out) << "return xfer;" << endl;
8557 
8558  indent_down();
8559 }
8560 
8562  std::ofstream& out,
8563  t_struct_common* tstruct,
8564  bool pointers) {
8565  indent_up();
8566 
8567  std::string struct_type_name = tstruct->get_struct_type_name();
8568 
8569  string name = tstruct->get_name();
8570  const vector<t_field*>& fields = tstruct->get_members();
8571  vector<t_field*>::const_iterator f_iter;
8572 
8573  out <<
8574  indent() << "int32_t xfer = 0, ret;" << endl;
8575 
8576  indent(out) <<
8577  "if ((ret = oprot->write" << struct_type_name << "Begin(\"" << name << "\")) < 0) {" <<
8578  endl;
8579 
8580  indent_up();
8581  indent(out) << "return ret;" << endl;
8582  scope_down(out);
8583  indent(out) << "xfer += ret;" << endl;
8584  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
8585  if ((*f_iter)->get_req() == t_field::T_OPTIONAL) {
8586  indent(out) << "if (this->__isset." << (*f_iter)->get_name() << ") {" << endl;
8587  indent_up();
8588  }
8589  // Write field header
8590  if (!((*f_iter)->annotations_.empty())) {
8591  out << indent() << "{" << endl;
8592  indent_up();
8593  out << indent() << "std::map<std::string, std::string> annotations_;" << endl;
8594  std::map<std::string, std::string>::iterator it;
8595  for (it = (*f_iter)->annotations_.begin(); it != (*f_iter)->annotations_.end(); it++) {
8596  if (!tstruct->is_sandesh() &&
8597  ((*f_iter)->get_name() == "name") && (it->first == "key")) {
8598  out << indent() << "assert(!table_.empty());" << endl;
8599  out << indent() << "annotations_.insert("
8600  "std::make_pair(\"key\", table_));" << endl;
8601  } else {
8602  out << indent() << "annotations_.insert(std::make_pair(\"" << (*it).first
8603  << "\"" << ", \"" << (*it).second << "\"));" << endl;
8604  }
8605  }
8606  out <<
8607  indent() << "if ((ret = oprot->writeFieldBegin(" <<
8608  "\"" << (*f_iter)->get_name() << "\", " <<
8609  type_to_enum((*f_iter)->get_type()) << ", " <<
8610  (*f_iter)->get_key() << ", &annotations_)) < 0) {" << endl;
8611  indent_up();
8612  indent(out) << "return ret;" << endl;
8613  scope_down(out);
8614  indent(out) << "xfer += ret;" << endl;
8615  indent_down();
8616  out << indent() << "}" << endl;
8617  } else {
8618  out <<
8619  indent() << "if ((ret = oprot->writeFieldBegin(" <<
8620  "\"" << (*f_iter)->get_name() << "\", " <<
8621  type_to_enum((*f_iter)->get_type()) << ", " <<
8622  (*f_iter)->get_key() << ")) < 0) {" << endl;
8623  indent_up();
8624  indent(out) << "return ret;" << endl;
8625  scope_down(out);
8626  indent(out) << "xfer += ret;" << endl;
8627  }
8628 
8629  // Write field contents
8630  if (pointers && !(*f_iter)->get_type()->is_xception()) {
8631  generate_serialize_field(out, *f_iter, "(*(this->", "))");
8632  } else {
8633  generate_serialize_field(out, *f_iter, "this->");
8634  }
8635  // Write field closer
8636  indent(out) <<
8637  "if ((ret = oprot->writeFieldEnd()) < 0) {" << endl;
8638  indent_up();
8639  indent(out) << "return ret;" << endl;
8640  scope_down(out);
8641  indent(out) << "xfer += ret;" << endl;
8642  if ((*f_iter)->get_req() == t_field::T_OPTIONAL) {
8643  indent_down();
8644  indent(out) << '}' << endl;
8645  }
8646  }
8647 
8648  // Write the struct map
8649  out <<
8650  indent() << "if ((ret = oprot->writeFieldStop()) < 0) {" << endl <<
8651  indent() << " return ret;" << endl <<
8652  indent() << "}" << endl <<
8653  indent() << "xfer += ret;" << endl <<
8654  indent() <<
8655  "if ((ret = oprot->write" << struct_type_name << "End()) < 0) {" <<
8656  endl <<
8657  indent() << " return ret;" << endl <<
8658  indent() << "}" << endl <<
8659  indent() << "xfer += ret;" << endl <<
8660  indent() << "return xfer;" << endl;
8661 
8662  indent_down();
8663 }
8664 
8665 
8666 THRIFT_REGISTER_GENERATOR(cpp, "C++",
8667 " cob_style: Generate \"Continuation OBject\"-style classes.\n"
8668 " no_client_completion:\n"
8669 " Omit calls to completion__() in CobClient class.\n"
8670 " templates: Generate templatized reader/writer methods.\n"
8671 " pure_enums: Generate pure enums instead of wrapper classes.\n"
8672 " dense: Generate type specifications for the dense protocol.\n"
8673 " include_prefix: Use full include paths in generated files.\n"
8674 )
std::ofstream f_types_impl_
std::ofstream f_header_
void generate_enum(t_enum *tenum)
void generate_service_async_skeleton(t_service *tservice)
std::string indent()
Definition: t_generator.h:181
std::ofstream & f_out_
virtual bool is_xception() const
Definition: t_type.h:74
const std::string & get_name() const
Definition: t_field.h:95
void generate_serialize_set_element(std::ofstream &out, t_set *tmap, std::string iter)
void generate_serialize_field(std::ofstream &out, t_field *tfield, std::string prefix="", std::string suffix="")
const std::string & get_include_prefix() const
Definition: t_program.h:98
void init()
Definition: bgp_log.cc:37
std::ofstream & f_header_
t_type * get_type() const
Definition: t_typedef.h:42
void generate_xception(t_struct *txception)
bool has_cpp_name()
Definition: t_container.h:38
std::string tmp(std::string name)
Definition: t_generator.h:160
Definition: t_enum.h:30
std::string local_reflection_name(const char *, t_type *ttype, bool external=false)
t_program * program_
Definition: t_generator.h:276
void generate_service_helpers(t_service *tservice)
void generate_service_skeleton(t_service *tservice)
void generate_struct_writer(std::ofstream &out, t_struct *tstruct, bool pointers=false)
std::ofstream f_types_
Definition: t_type.h:48
std::string get_include_prefix(const t_program &program) const
void set_use_include_prefix(bool use_include_prefix)
static std::string t_base_name(t_base tbase)
Definition: t_base_type.h:218
const std::string & get_name() const
Definition: t_function.h:91
bool is_level_category_supported() const
Definition: t_sandesh.h:75
const uint32_t get_4byte_fingerprint() const
Definition: t_type.h:139
void generate_struct(t_struct *tstruct)
virtual bool is_map() const
Definition: t_type.h:78
bool has_fingerprint() const
Definition: t_type.h:101
const std::string & get_name() const
Definition: t_program.h:92
virtual std::string get_fingerprint_material() const =0
std::string declare_field(t_field *tfield, bool init=false, bool pointer=false, bool constant=false, bool reference=false)
std::string get_cpp_name()
Definition: t_container.h:42
void indent_down()
Definition: t_generator.h:174
std::string namespace_prefix(std::string ns)
virtual std::string get_out_dir() const
Definition: t_generator.h:148
void generate_enum_constant_list(std::ofstream &f, const vector< t_enum_value * > &constants, const char *prefix, const char *suffix, bool include_values)
const members_type & get_sorted_members()
static const int fingerprint_len
Definition: t_type.h:96
virtual bool is_enum() const
Definition: t_type.h:72
t_type * get_type() const
Definition: t_field.h:91
virtual bool is_base_type() const
Definition: t_type.h:61
void scope_up(std::ostream &out)
const t_program * get_program() const
Definition: t_generator.h:60
t_cpp_generator(t_program *program, const std::map< std::string, std::string > &parsed_options, const std::string &option_string)
void generate_deserialize_container(std::ofstream &out, t_type *ttype, std::string prefix="")
void generate_process_function(t_service *tservice, t_function *tfunction, string style, bool specialized=false)
void generate_service_multiface(t_service *tservice)
t_type * get_returntype() const
Definition: t_function.h:87
std::string type_to_enum(t_type *ttype)
const std::map< t_const_value *, t_const_value * > & get_map() const
void print_const_value(std::ofstream &out, std::string name, t_type *type, t_const_value *value)
const members_type & get_members()
std::string argument_list(t_struct *tstruct, bool name_params=true, bool start_comma=false)
void generate_service(t_service *tservice)
std::ofstream f_types_tcc_
int64_t get_integer() const
Definition: t_const_value.h:72
t_type * get_key_type() const
Definition: t_map.h:36
void generate_service_interface(t_service *tservice, string style)
bool is_string() const
Definition: t_base_type.h:89
virtual std::string get_struct_type_name()=0
std::string ns_close_
std::string service_name_
Definition: t_generator.h:288
t_const_value_type get_type() const
virtual bool is_container() const
Definition: t_type.h:75
void generate_deserialize_set_element(std::ofstream &out, t_set *tset, std::string prefix="")
#define MKDIR(x)
Definition: platform.h:28
std::string render_const_value(std::ofstream &out, std::string name, t_type *type, t_const_value *value)
void generate_service_client(t_service *tservice, string style)
uint8_t type
Definition: load_balance.h:109
t_struct * get_xceptions() const
Definition: t_function.h:99
t_type * get_elem_type() const
Definition: t_set.h:34
std::string out_dir_base_
Definition: t_generator.h:301
ProcessorGenerator(t_cpp_generator *generator, t_service *service, const string &style)
void generate_function_helpers(t_service *tservice, t_function *tfunction)
void generate_struct_reader(std::ofstream &out, t_struct *tstruct, bool pointers=false)
std::string namespace_close(std::string ns)
virtual bool is_set() const
Definition: t_type.h:77
void generate_struct_result_writer(std::ofstream &out, t_struct *tstruct, bool pointers=false)
virtual void set_name(const std::string &name)
Definition: t_type.h:52
std::string get_uuid() const
void generate_serialize_container(std::ofstream &out, t_type *ttype, std::string prefix="")
std::string type_name(t_type *ttype, bool in_typedef=false, bool arg=false)
void generate_common_struct_reader_body(std::ofstream &out, t_struct_common *tstruct, bool pointers=false)
virtual bool is_void() const
Definition: t_type.h:60
std::string type_name(t_type *ttype, bool in_typedef=false, bool arg=false)
std::ofstream f_service_tcc_
void generate_serialize_list_element(std::ofstream &out, t_list *tlist, std::string iter)
t_type * get_elem_type() const
Definition: t_list.h:34
e_req get_req() const
Definition: t_field.h:113
void generate_serialize_struct(std::ofstream &out, t_struct *tstruct, std::string prefix="")
t_type * get_val_type() const
Definition: t_map.h:40
void scope_down(std::ostream &out)
std::string ns_open_
void generate_local_reflection(std::ofstream &out, t_type *ttype, bool is_definition)
const std::string & get_symbolic() const
Definition: t_typedef.h:46
t_base get_base() const
Definition: t_base_type.h:81
const std::vector< t_function * > & get_functions() const
Definition: t_service.h:56
bool is_complex_type(t_type *ttype)
std::string namespace_open(std::string ns)
std::ofstream f_service_
virtual const std::string & get_name() const
Definition: t_type.h:56
void generate_cpp_struct(t_struct *tstruct, bool is_exception)
Definition: t_map.h:30
virtual bool is_list() const
Definition: t_type.h:76
virtual bool has_key_annotation() const
void generate_typedef(t_typedef *ttypedef)
std::string function_signature(t_function *tfunction, std::string style, std::string prefix="", bool name_params=true)
const std::vector< t_enum_value * > & get_constants()
Definition: t_enum.h:43
void generate_service_processor(t_service *tservice, string style)
static std::string byte_to_hex(uint8_t byte)
Definition: t_type.h:132
void generate_struct_fingerprint(std::ofstream &out, t_struct *tstruct, bool is_definition)
void generate_serialize_map_element(std::ofstream &out, t_map *tmap, std::string iter)
void generate_deserialize_struct(std::ofstream &out, t_struct *tstruct, std::string prefix="")
std::string get_string() const
Definition: t_const_value.h:63
static t_type * get_true_type(t_type *type)
Definition: t_generator.h:268
double get_double() const
Definition: t_const_value.h:99
const std::string & get_namespace() const
Definition: t_program.h:95
std::string get_ascii_fingerprint() const
Definition: t_type.h:114
t_program * get_program()
Definition: t_type.h:81
virtual bool is_struct() const
Definition: t_type.h:73
t_service * get_extends()
Definition: t_service.h:60
Definition: t_set.h:29
const t_type * get_type()
Definition: t_sandesh.h:71
void indent_up()
Definition: t_generator.h:170
#define LOG(_Level, _Msg)
Definition: logging.h:33
void generate_consts(std::vector< t_const * > consts)
std::map< std::string, std::string > annotations_
Definition: t_type.h:171
Definition: t_list.h:29
void generate_common_struct_writer_body(std::ofstream &out, t_struct_common *tstruct, bool pointers=false)
const uint8_t * get_binary_fingerprint() const
Definition: t_type.h:110
std::ostream & indent(std::ostream &os)
std::set< std::string > reflected_fingerprints_
void generate_deserialize_map_element(std::ofstream &out, t_map *tmap, std::string prefix="")
std::string base_type_name(t_base_type::t_base tbase)
void generate_function_call(ostream &out, t_function *tfunction, string target, string iface, string arg_prefix)
void generate_local_reflection_pointer(std::ofstream &out, t_type *ttype)
t_cpp_generator * generator_
void generate_struct_definition(std::ofstream &out, t_struct *tstruct, bool is_exception=false, bool pointers=false, bool read=true, bool write=true)
virtual bool is_string() const
Definition: t_type.h:62
void generate_service_interface_factory(t_service *tservice, string style)
void generate_service_null(t_service *tservice, string style)
void generate_deserialize_list_element(std::ofstream &out, t_list *tlist, std::string prefix, bool push_back, std::string index)
static const char namespace_prefix[]
bool is_oneway() const
Definition: t_function.h:103
int32_t skip(Protocol_ &prot, TType type)
Definition: TProtocol.h:187
#define THRIFT_REGISTER_GENERATOR(language, long_name, doc)
void generate_deserialize_field(std::ofstream &out, t_field *tfield, std::string prefix="", std::string suffix="")
const std::vector< t_const_value * > & get_list() const
t_struct * get_arglist() const
Definition: t_function.h:95