├── .gitignore
├── README.md
├── conf
├── rocket.xml
└── rocket_client.xml
├── generator
├── rocket_generator.py
└── template
│ ├── business_exception.h.template
│ ├── conf.xml.template
│ ├── interface.cc.template
│ ├── interface.h.template
│ ├── interface_base.cc.template
│ ├── interface_base.h.template
│ ├── main.cc.template
│ ├── makefile.template
│ ├── run.sh
│ ├── server.cc.template
│ ├── server.h.template
│ ├── shutdown.sh
│ └── test_rocket_client.cc.template
├── imgs
├── main-sub-reactor.drawio.png
└── multiple_definition.jpg
├── make.sh
├── makefile
├── rocket
├── common
│ ├── config.cc
│ ├── config.h
│ ├── error_code.h
│ ├── exception.h
│ ├── log.cc
│ ├── log.h
│ ├── msg_id_util.cc
│ ├── msg_id_util.h
│ ├── mutex.h
│ ├── run_time.cc
│ ├── run_time.h
│ ├── util.cc
│ └── util.h
└── net
│ ├── coder
│ ├── abstract_coder.h
│ ├── abstract_protocol.h
│ ├── string_coder.h
│ ├── tinypb_coder.cc
│ ├── tinypb_coder.h
│ ├── tinypb_protocol.cc
│ └── tinypb_protocol.h
│ ├── eventloop.cc
│ ├── eventloop.h
│ ├── fd_event.cc
│ ├── fd_event.h
│ ├── fd_event_group.cc
│ ├── fd_event_group.h
│ ├── io_thread.cc
│ ├── io_thread.h
│ ├── io_thread_group.cc
│ ├── io_thread_group.h
│ ├── rpc
│ ├── rpc_channel.cc
│ ├── rpc_channel.h
│ ├── rpc_closure.h
│ ├── rpc_controller.cc
│ ├── rpc_controller.h
│ ├── rpc_dispatcher.cc
│ ├── rpc_dispatcher.h
│ ├── rpc_interface.cc
│ └── rpc_interface.h
│ ├── tcp
│ ├── net_addr.cc
│ ├── net_addr.h
│ ├── tcp_acceptor.cc
│ ├── tcp_acceptor.h
│ ├── tcp_buffer.cc
│ ├── tcp_buffer.h
│ ├── tcp_client.cc
│ ├── tcp_client.h
│ ├── tcp_connection.cc
│ ├── tcp_connection.h
│ ├── tcp_server.cc
│ └── tcp_server.h
│ ├── timer.cc
│ ├── timer.h
│ ├── timer_event.cc
│ ├── timer_event.h
│ ├── wakeup_fd_event.cc
│ └── wakeup_fd_event.h
└── testcases
├── order.proto
├── test_client.cc
├── test_eventloop.cc
├── test_log.cc
├── test_rpc_client.cc
├── test_rpc_server.cc
└── test_tcp.cc
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/*
2 | lib/*
3 | obj/*
4 | log/*
5 |
6 | *.pb.h
7 | *.pb.cc
8 |
--------------------------------------------------------------------------------
/conf/rocket.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DEBUG
5 | test_rpc_server
6 | ../log/
7 | 1000000000
8 | 500
9 |
10 |
11 |
12 | 12345
13 | 4
14 |
15 |
16 |
17 |
18 |
19 |
20 | default
21 | 0.0.0.0
22 | 12345
23 | 1000
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/conf/rocket_client.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DEBUG
5 | test_rpc_client
6 | ../log/
7 | 1000000000
8 | 500
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/generator/rocket_generator.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3.7
2 |
3 | import getopt
4 | import traceback
5 | import os
6 | import sys
7 | from string import Template
8 | from datetime import datetime
9 |
10 | project_name = ""
11 | proto_file = ""
12 | out_project_path = "./"
13 | bin_path = ""
14 | conf_path = ""
15 | test_client_path = ""
16 | test_client_tool_path = ""
17 | src_path = ""
18 |
19 | generator_path = sys.path[0]
20 |
21 |
22 |
23 | def to_camel(input_s):
24 | if input_s.find('_') == -1:
25 | return input_s
26 | re = ''
27 | for s in input_s.split('_'):
28 | re += s.capitalize()
29 | return re
30 |
31 | def to_underline(input_s):
32 | tmp = to_camel(input_s)
33 | re = ''
34 | for s in tmp:
35 | re += s if s.islower() else '_' + s.lower()
36 | re = re[1:]
37 | return re
38 |
39 | def parseInput():
40 | opts,args = getopt.getopt(sys.argv[1:], "hi:o:", longopts=["help", "input=", "output="])
41 |
42 | for opts,arg in opts:
43 |
44 | if opts=="-h" or opts=="--help":
45 | printHelp()
46 | sys.exit(0)
47 | if opts=="-i" or opts=="--input":
48 | global proto_file
49 | proto_file = arg
50 | elif opts=="-o" or opts=="--output_path":
51 | global out_project_path
52 | out_project_path = arg
53 | if out_project_path[-1] != '/':
54 | out_project_path = out_project_path + '/'
55 | else:
56 | raise Exception("invalid options: [" + opts + ": " + arg + "]")
57 |
58 | if not os.path.exists(proto_file):
59 | raise Exception("Generate error, not exist protobuf file: " + proto_file)
60 |
61 | if ".proto" not in proto_file:
62 | raise Exception("Generate error, input file is't standard protobuf file:[" + proto_file + "]")
63 |
64 | global project_name
65 | project_name = proto_file[0: -6]
66 | print("project name is " + project_name)
67 |
68 |
69 | def printHelp():
70 | print('=' * 100)
71 | print('Welcome to use Rocket Generator, this is help document:\n')
72 | print('Run Environment: Python(version 3.6 or high version is better).')
73 | print('Run Platform: Linux Only(kernel version >= 3.9 is better).')
74 | print('Others: Only protobuf3 support, not support protobuf2.\n')
75 | print('Usage:')
76 | print('rocket_generator.py -[options][target]\n')
77 | print('Options:')
78 | print('-h, --help')
79 | print((' ') + 'Print help document.\n')
80 |
81 | print('-i xxx.proto, --input xxx.proto')
82 | print((' ') + 'Input the target proto file, must standard protobuf3 file, not support protobuf2.\n')
83 |
84 | print('-o dir, --output dir')
85 | print((' ') + 'Set the path that your want to generate project, please give a dir param.\n')
86 |
87 | print('')
88 | print('For example:')
89 | print('rocket_generator.py -i order_server.proto -o ./')
90 |
91 | print('')
92 | print('=' * 100)
93 |
94 |
95 | def generate_dir():
96 | print('=' * 100)
97 | print('Begin to generate project dir')
98 |
99 | if out_project_path == "":
100 | proj_path = './' + project_name.strip()
101 | if out_project_path[-1] == '/':
102 | proj_path = out_project_path + project_name.strip()
103 | else:
104 | proj_path = out_project_path + './' + project_name.strip()
105 |
106 | global bin_path
107 | bin_path = proj_path + '/bin'
108 |
109 | global conf_path
110 | conf_path = proj_path + '/conf'
111 |
112 | global test_client_path
113 | test_client_path = proj_path + '/test_client'
114 |
115 | global test_client_tool_path
116 | test_client_tool_path = test_client_path + '/test_tool'
117 |
118 | log_path = proj_path + '/log'
119 | lib_path = proj_path + '/lib'
120 | obj_path = proj_path + '/obj'
121 |
122 | global src_path
123 | src_path = proj_path + '/' + project_name
124 | src_interface_path = src_path + '/interface'
125 | src_service_path = src_path + '/service'
126 | src_pb_path = src_path + '/pb'
127 | src_stubs_path = src_path + '/stubs'
128 | src_comm_path = src_path + '/comm'
129 |
130 | dir_list = []
131 | dir_list.append(proj_path)
132 | dir_list.append(bin_path)
133 | dir_list.append(conf_path)
134 | dir_list.append(log_path)
135 | dir_list.append(lib_path)
136 | dir_list.append(obj_path)
137 | dir_list.append(test_client_path)
138 | dir_list.append(test_client_tool_path)
139 | dir_list.append(src_path)
140 | dir_list.append(src_interface_path)
141 | dir_list.append(src_service_path)
142 | dir_list.append(src_pb_path)
143 | dir_list.append(src_stubs_path)
144 | dir_list.append(src_comm_path)
145 |
146 | for each in dir_list:
147 | if not os.path.exists(each):
148 | os.mkdir(each)
149 | print("succ make dir in " + each)
150 |
151 | print('End generate project dir')
152 | print('=' * 100)
153 |
154 |
155 |
156 | def generate_pb():
157 | print('=' * 100)
158 | print('Begin generate protobuf file')
159 | pb_path = src_path + '/pb/'
160 | cmd = 'cp -r ' + proto_file + ' ' + pb_path
161 | cmd += ' && cd ' + pb_path + ' && protoc --cpp_out=./ ' + proto_file
162 | print('excute cmd: ' + cmd)
163 |
164 | if os.system(cmd) is not 0:
165 | raise Exception("execute cmd failed [" + cmd + "]")
166 |
167 | print('End generate protobuf file')
168 | print('=' * 100)
169 |
170 |
171 |
172 | def generate_makefile():
173 | print('=' * 100)
174 | print('Begin to generate makefile')
175 | out_file = src_path + '/makefile'
176 | if os.path.exists(out_file):
177 | print('makefile exist, skip generate')
178 | print('End generate makefile')
179 | print('=' * 100)
180 | return
181 |
182 | template_file = open(generator_path + '/template/makefile.template','r')
183 | tmpl = Template(template_file.read())
184 |
185 | content = tmpl.safe_substitute(
186 | PROJECT_NAME = project_name,
187 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
188 |
189 | file = open(out_file, 'w')
190 | file.write(content)
191 | file.close()
192 | print('succ write to ' + out_file)
193 | print('End generate makefile')
194 | print('=' * 100)
195 |
196 |
197 | def gen_run_script():
198 | print('=' * 100)
199 | print('Begin to generate run script')
200 | script = open(generator_path + '/template/conf.xml.template','r')
201 | dir_src = generator_path + '/template/'
202 | cmd = 'cp -r ' + dir_src + '*.sh ' + bin_path + "/"
203 | print('excute cmd: ' + cmd)
204 | os.system(cmd)
205 |
206 | print('End generate run script')
207 | print('=' * 100)
208 |
209 | def gen_conf_file():
210 | print('=' * 100)
211 | file_name = "rocket.xml"
212 | print('Begin to generate tinyrpc conf file')
213 | out_file = conf_path + '/' + file_name
214 | if os.path.exists(out_file):
215 | print('config exist, skip generate')
216 | print('End generate ' + file_name)
217 | print('=' * 100)
218 | return
219 |
220 | template_file = open(generator_path + '/template/conf.xml.template','r')
221 | # print(template_file.read())
222 | tmpl = Template(template_file.read())
223 |
224 | content = tmpl.safe_substitute(
225 | PROJECT_NAME = project_name,
226 | FILE_NAME = file_name,
227 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
228 |
229 | file = open(out_file, 'w')
230 | file.write(content)
231 | file.close()
232 | print('succ write to ' + out_file)
233 | print('End generate rocket conf file')
234 | print('=' * 100)
235 |
236 |
237 | def generate_framework_code():
238 | print('=' * 100)
239 | print('Begin to generate tinyrpc framework code')
240 | pb_head_file = src_path + '/pb/' + project_name + '.pb.h'
241 | file = open(pb_head_file, 'r')
242 | origin_text = file.read()
243 |
244 | # parse all rpc interface method from pb.h file
245 | begin = origin_text.find('virtual ~')
246 | i1 = origin_text[begin:].find('~')
247 | i2 = origin_text[begin:].find('(')
248 | service_name = origin_text[begin + i1 + 1 : begin + i2]
249 | print("service name is " + service_name)
250 |
251 | origin_text = origin_text[begin + i2: ]
252 | method_list = []
253 |
254 | i1 = 0
255 | while 1:
256 | i1 = origin_text.find('virtual void')
257 | if (i1 == -1):
258 | break
259 | i2 = origin_text[i1:].find(');')
260 | method_list.append(origin_text[i1: i1 + i2 + 2])
261 | # print(origin_text[i1: i1 + i2 + 2])
262 | origin_text = origin_text[i1 + i2 + 3: ]
263 |
264 |
265 | print('=' * 100)
266 | print('Begin generate business_exception.h')
267 | exception_file = src_path + '/comm/' + 'business_exception.h'
268 | if not os.path.exists(exception_file):
269 | # generate business_exception.h
270 | exception_template = Template(open(generator_path + '/template/business_exception.h.template', 'r').read())
271 | exception_content = exception_template.safe_substitute(
272 | PROJECT_NAME = project_name,
273 | FILE_NAME = 'business_exception.cc',
274 | HEADER_DEFINE = project_name.upper() + '_COMM_BUSINESSEXCEPTION_H',
275 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
276 | INCLUDE_INTERFACEBASE_HEADER_FILE = '#include "' + project_name + '/interface/interface.h"',
277 | )
278 | out_exception_file = open(exception_file, 'w')
279 | out_exception_file.write(exception_content)
280 | out_exception_file.close()
281 | else:
282 | print("file: [" + exception_file + "] exist, skip")
283 |
284 | print('End generate business_exception.h')
285 | print('=' * 100)
286 |
287 |
288 | print('=' * 100)
289 | print('Begin generate server.h')
290 | # genneator server.h file
291 | class_name = to_camel(service_name) + 'Impl'
292 | head_file_temlate = Template(open(generator_path + '/template/server.h.template','r').read())
293 | head_file_content = head_file_temlate.safe_substitute(
294 | HEADER_DEFINE = project_name.upper() + '_SERVICE_' + project_name.upper() + '_H',
295 | FILE_NAME = project_name + '.h',
296 | PROJECT_NAME = project_name,
297 | CLASS_NAME = class_name,
298 | SERVICE_NAME = service_name,
299 | PB_HEAD_FILE = project_name + '/pb/' + project_name + '.pb.h',
300 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
301 | INCLUDE_PB_HEADER = '#include "' + project_name + '/pb/' + project_name + '.pb.h"',
302 | )
303 |
304 | i1 = head_file_content.find('${METHOD}')
305 | pre_content = head_file_content[0: i1]
306 | next_content = head_file_content[i1 + 9: ]
307 | for each in method_list:
308 | each = each.replace('PROTOBUF_NAMESPACE_ID', 'google::protobuf')
309 | pre_content += '// override from ' + service_name + '\n '
310 | pre_content += each
311 | pre_content += '\n\n '
312 | content = pre_content + next_content
313 | out_head_file = open(src_path + '/service/' + project_name + '.h', 'w')
314 | out_head_file.write(content)
315 | out_head_file.close()
316 |
317 | print('End generate server.h')
318 | print('=' * 100)
319 |
320 | print('=' * 100)
321 | print('Begin generate server.cc')
322 | # genneator server.cc file
323 | cc_file_temlate = Template(open(generator_path + '/template/server.cc.template','r').read())
324 | cc_file_content = cc_file_temlate.safe_substitute(
325 | FILE_NAME = project_name + '.cc',
326 | PROJECT_NAME = project_name,
327 | INCLUDE_PB_HEADER = '#include "' + project_name + '/pb/' + project_name + '.pb.h"',
328 | INCLUDE_BUSINESS_EXCEPTION_HEADER = '#include "' + project_name + '/comm/business_exception.h"',
329 | INCLUDE_SERVER_HEADER = '#include "' + project_name + '/service/' + project_name + '.h"',
330 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
331 | )
332 |
333 |
334 | method_i = cc_file_content.find('${METHOD}')
335 | pre_content = cc_file_content[0: method_i]
336 | next_content = cc_file_content[method_i + 9: ]
337 | interface_list = []
338 |
339 | for each in method_list:
340 | tmp = each.replace('PROTOBUF_NAMESPACE_ID', 'google::protobuf')
341 | i1 = tmp.find('void')
342 | tmp = tmp[i1:]
343 |
344 | i2 = tmp.find('(')
345 | method_name = tmp[5: i2]
346 | # print(method_name)
347 | interface_class_name = to_camel(method_name) + 'Interface'
348 | interface_file_name = to_underline(method_name)
349 | l = tmp.split(',')
350 | y = l[1].find('request')
351 | request_type = l[1][0: y - 1].replace('*', '').replace('const ', '').replace('\n', '').replace(' ', '')
352 | # print(request_type)
353 |
354 | y = l[2].find('response')
355 | response_type = l[2][0: y - 1].replace('*', '').replace('\n', '').replace(' ', '')
356 | # print(response_type)
357 |
358 |
359 | interface_list.append({
360 | 'interface_name': interface_file_name,
361 | 'method_name': method_name,
362 | 'interface_class_name': interface_class_name,
363 | 'request_type': request_type,
364 | 'response_type': response_type
365 | })
366 | # print(interface_list)
367 |
368 | tmp = tmp[0: 5] + class_name + '::' + tmp[5:]
369 | tmp = tmp[0: -1] + '{\n\n ' + 'CALL_RPC_INTERFACE(' + interface_class_name + ');\n}'
370 | # print(tmp)
371 | pre_content += tmp
372 | pre_content += '\n\n'
373 |
374 | include_str = ''
375 | for each in interface_list:
376 | include_str += '#include "' + project_name + '/interface/' + each['interface_name'] + '.h"\n'
377 | pre_content = pre_content.replace('${INCLUDE_SERVICE}', include_str)
378 |
379 | out_cc_file = open(src_path + '/service/' + project_name + '.cc', 'w')
380 | out_cc_file.write(pre_content + next_content)
381 | out_cc_file.close()
382 |
383 | print('End generate server.cc')
384 | print('=' * 100)
385 |
386 |
387 | print('=' * 100)
388 | print('Begin generate main.cc')
389 | # genneator main.cc file
390 | main_file = src_path + '/main.cc'
391 | if not os.path.exists(main_file):
392 | main_file_temlate = Template(open(generator_path + '/template/main.cc.template','r').read())
393 | main_file_content = main_file_temlate.safe_substitute(
394 | FILE_NAME = project_name + '.h',
395 | PROJECT_NAME = project_name,
396 | CLASS_NAME = project_name + "::" + class_name,
397 | INCLUDE_SERVER_HEADER = '#include "service/' + project_name + '.h"',
398 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
399 | )
400 | main_file_handler = open(main_file, 'w')
401 | main_file_handler.write(main_file_content)
402 | main_file_handler.close()
403 | else:
404 | print("file: [" + main_file + "] exist, skip")
405 |
406 | print('End generate main.cc')
407 | print('=' * 100)
408 |
409 |
410 | # genneator interface.h file
411 | interfase_base_h_file = src_path + '/interface/interface.h'
412 | if not os.path.exists(interfase_base_h_file):
413 | interface_base_h_file_temlate = Template(open(generator_path + '/template/interface_base.h.template','r').read())
414 | interfase_base_h_file_content = interface_base_h_file_temlate.safe_substitute(
415 | FILE_NAME = 'interface.h',
416 | PROJECT_NAME = project_name,
417 | HEADER_DEFINE = project_name.upper() + '_INTERFACE_H',
418 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
419 | )
420 | interface_base_h_handler = open(interfase_base_h_file, 'w')
421 | interface_base_h_handler.write(interfase_base_h_file_content)
422 | interface_base_h_handler.close()
423 | else:
424 | print("file: [" + interfase_base_h_file + "] exist, skip")
425 |
426 | print('End generate interface.h')
427 | print('=' * 100)
428 |
429 | # genneator interface.cc file
430 | interfase_base_cc_file = src_path + '/interface/interface.cc'
431 | if not os.path.exists(interfase_base_cc_file):
432 | interface_base_cc_file_temlate = Template(open(generator_path + '/template/interface_base.cc.template','r').read())
433 | interfase_base_cc_file_content = interface_base_cc_file_temlate.safe_substitute(
434 | FILE_NAME = 'interface.cc',
435 | PROJECT_NAME = project_name,
436 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
437 | INCLUDE_INTERFACEBASE_HEADER_FILE = '#include "' + project_name + '/interface/interface.h"',
438 | )
439 | interface_base_cc_handler = open(interfase_base_cc_file, 'w')
440 | interface_base_cc_handler.write(interfase_base_cc_file_content)
441 | interface_base_cc_handler.close()
442 | else:
443 | print("file: [" + interfase_base_cc_file + "] exist, skip")
444 |
445 | print('End generate interface.cc')
446 | print('=' * 100)
447 |
448 |
449 |
450 |
451 | print('=' * 100)
452 | print('Begin generate each rpc method interface.cc & interface.h')
453 | # genneator each interface.cc and .h file
454 | interface_head_file_temlate = Template(open(generator_path + '/template/interface.h.template','r').read())
455 | interface_cc_file_temlate = Template(open(generator_path + '/template/interface.cc.template','r').read())
456 | interface_test_client_file_template = Template(open(generator_path + '/template/test_rocket_client.cc.template','r').read())
457 |
458 | stub_name = service_name + "_Stub"
459 | for each in interface_list:
460 |
461 | # interface.h
462 | file = src_path + '/interface/' + each['interface_name'] + '.h'
463 | if not os.path.exists(file):
464 | header_content = interface_head_file_temlate.safe_substitute(
465 | PROJECT_NAME = project_name,
466 | INCLUDE_PB_HEADER = '#include "' + project_name + '/pb/' + project_name + '.pb.h"',
467 | HEADER_DEFINE = project_name.upper() + '_INTERFACE_' + each['interface_name'].upper() + '_H',
468 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
469 | CLASS_NAME = each['interface_class_name'],
470 | REQUEST_TYPE = each['request_type'],
471 | RESPONSE_TYPE = each['response_type'],
472 | INCLUDE_INTERFACEBASE_HEADER_FILE = '#include "' + project_name + '/interface/interface.h"',
473 | FILE_NAME = each['interface_name'] + '.h'
474 | )
475 | out_interface_header_file = open(file, 'w')
476 | out_interface_header_file.write(header_content)
477 | out_interface_header_file.close()
478 | else:
479 | print("file: [" + file + "] exist, skip")
480 |
481 | # interface.cc
482 | file = src_path + '/interface/' + each['interface_name'] + '.cc'
483 | if not os.path.exists(file):
484 | cc_file_content = interface_cc_file_temlate.safe_substitute(
485 | PROJECT_NAME = project_name,
486 | INCLUDE_PB_HEADER = '#include "' + project_name + '/pb/' + project_name + '.pb.h"',
487 | INCLUDE_INTERFACE_HEADER_FILE = '#include "' + project_name + '/interface/' + each['interface_name'] + '.h"',
488 | INCLUDE_INTERFACEBASE_HEADER_FILE = '#include "' + project_name + '/interface/interface.h"',
489 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
490 | CLASS_NAME = each['interface_class_name'],
491 | REQUEST_TYPE = each['request_type'],
492 | RESPONSE_TYPE = each['response_type'],
493 | FILE_NAME = each['interface_name'] + '.cc'
494 | )
495 | out_interface_cc_file = open(file, 'w')
496 | out_interface_cc_file.write(cc_file_content)
497 | out_interface_cc_file.close()
498 | else:
499 | print("file: [" + file + "] exist, skip")
500 |
501 | # test_interface_client.cc
502 | file = test_client_path + '/test_' + each['interface_name'] + '_client.cc'
503 | if not os.path.exists(file):
504 | cc_file_content = interface_test_client_file_template.safe_substitute(
505 | INCLUDE_PB_HEADER = '#include "' + project_name + '/pb/' + project_name + '.pb.h"',
506 | CREATE_TIME = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
507 | REQUEST_TYPE = each['request_type'],
508 | RESPONSE_TYPE = each['response_type'],
509 | STUBCLASS = stub_name,
510 | METHOD_NAME = each['method_name'],
511 | FILE_NAME = 'test_' + each['interface_name'] + '_client.cc',
512 | )
513 | out_interface_cc_file = open(file, 'w')
514 | out_interface_cc_file.write(cc_file_content)
515 | out_interface_cc_file.close()
516 | else:
517 | print("file: [" + file + "] exist, skip")
518 |
519 |
520 |
521 | print('End generate each interface.cc & interface.h & test_interface_client.h')
522 | print('=' * 100)
523 |
524 | print('End generate rocket framework code')
525 | print('=' * 100)
526 |
527 | def generate_project():
528 |
529 | try:
530 | parseInput()
531 |
532 | print('=' * 150)
533 | print("Begin to generate rocket rpc server")
534 |
535 | generate_dir()
536 |
537 | generate_pb()
538 |
539 | generate_makefile()
540 |
541 | gen_run_script()
542 |
543 | gen_conf_file()
544 |
545 | generate_framework_code()
546 |
547 | print('Succ generate rocket project')
548 | print('=' * 150)
549 |
550 | except Exception as e:
551 | print("Failed to generate rocket rpc server, err: " + str(e))
552 | print('=' * 150)
553 |
554 |
555 | if __name__ == '__main__':
556 | generate_project()
557 |
--------------------------------------------------------------------------------
/generator/template/business_exception.h.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * File will not generate while exist
11 | * Allow editing
12 | ****************************************************/
13 |
14 |
15 | #ifndef ${HEADER_DEFINE}
16 | #define ${HEADER_DEFINE}
17 |
18 |
19 |
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 |
28 | namespace ${PROJECT_NAME} {
29 |
30 | class BusinessException : public rocket::RocketException {
31 | public:
32 |
33 | BusinessException(int code, const std::string& err_info, const std::string& file_name, int line):
34 | rocket::RocketException(code, err_info), m_file_name(file_name), m_line(line) {
35 |
36 | APPINFOLOG("[%s:%lld] throw BusinessException[code: %d, error info: %s]", file_name.c_str(), line, code, err_info.c_str());
37 | }
38 |
39 | ~BusinessException() {
40 |
41 | }
42 |
43 | void handle() override {
44 |
45 | }
46 |
47 | const char* what() {
48 | return m_error_info.c_str();
49 | }
50 |
51 | std::string file_name() {
52 | return m_file_name;
53 | }
54 |
55 | int line() {
56 | return m_line;
57 | }
58 |
59 | private:
60 |
61 | std::string m_file_name;
62 |
63 | int m_line {0};
64 |
65 | };
66 |
67 | }
68 |
69 | #endif
--------------------------------------------------------------------------------
/generator/template/conf.xml.template:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | DEBUG
10 |
11 |
12 | ${PROJECT_NAME}
13 |
14 |
15 | ../log/
16 |
17 |
18 | 1000000000
19 |
20 |
21 | 500
22 |
23 |
24 |
25 |
26 | 12345
27 |
28 |
29 | 4
30 |
31 |
32 |
33 |
34 |
35 |
36 | demo
37 |
38 | 127.0.0.1
39 | 54321
40 | 2000
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/generator/template/interface.cc.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * File will not generate while exist
11 | * Allow editing
12 | ****************************************************/
13 |
14 |
15 | #include
16 | ${INCLUDE_INTERFACE_HEADER_FILE}
17 | ${INCLUDE_INTERFACEBASE_HEADER_FILE}
18 | ${INCLUDE_PB_HEADER}
19 |
20 | namespace ${PROJECT_NAME} {
21 |
22 | ${CLASS_NAME}::${CLASS_NAME}(const ${REQUEST_TYPE}* request, ${RESPONSE_TYPE}* response,
23 | rocket::RpcClosure* done, rocket::RpcController* controller)
24 | : Interface(dynamic_cast(request), dynamic_cast(response), done, controller),
25 | m_request(request),
26 | m_response(response) {
27 | APPINFOLOG("In|request:{%s}", request->ShortDebugString().c_str());
28 | }
29 |
30 | ${CLASS_NAME}::~${CLASS_NAME}() {
31 | APPINFOLOG("Out|response:{%s}", m_response->ShortDebugString().c_str());
32 | }
33 |
34 | void ${CLASS_NAME}::run() {
35 |
36 | //
37 | // Run your business logic at here
38 | //
39 |
40 | m_response->set_ret_code(0);
41 | m_response->set_res_info("OK");
42 |
43 | }
44 |
45 | void ${CLASS_NAME}::setError(int code, const std::string& err_info) {
46 | m_response->set_ret_code(code);
47 | m_response->set_res_info(err_info);
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/generator/template/interface.h.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * File will not generate while exist
11 | * Allow editing
12 | ****************************************************/
13 |
14 | #ifndef ${HEADER_DEFINE}
15 | #define ${HEADER_DEFINE}
16 |
17 | #include
18 | ${INCLUDE_PB_HEADER}
19 | ${INCLUDE_INTERFACEBASE_HEADER_FILE}
20 |
21 |
22 | namespace ${PROJECT_NAME} {
23 |
24 | /*
25 | * Rpc Interface Class
26 | * Alloc one object every time RPC call begin, and destroy this object while RPC call end
27 | */
28 |
29 | class ${CLASS_NAME} : public Interface {
30 | public:
31 |
32 | ${CLASS_NAME}(const ${REQUEST_TYPE}* request, ${RESPONSE_TYPE}* response,
33 | rocket::RpcClosure* done, rocket::RpcController* controller);
34 |
35 | ~${CLASS_NAME}();
36 |
37 | public:
38 | // core business deal method
39 | virtual void run() override;
40 |
41 | // set error code and error into to response message
42 | virtual void setError(int code, const std::string& err_info) override;
43 |
44 | private:
45 | const ${REQUEST_TYPE}* m_request {NULL}; // request object fron client
46 |
47 | ${RESPONSE_TYPE}* m_response {NULL}; // response object that reply to client
48 |
49 | };
50 |
51 |
52 | }
53 |
54 |
55 | #endif
--------------------------------------------------------------------------------
/generator/template/interface_base.cc.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * File will not generate while exist
11 | * Allow editing
12 | ****************************************************/
13 |
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | ${INCLUDE_INTERFACEBASE_HEADER_FILE}
22 |
23 | namespace ${PROJECT_NAME} {
24 |
25 |
26 | Interface::Interface(const google::protobuf::Message* req, google::protobuf::Message* rsp, rocket::RpcClosure* done, rocket::RpcController* controller)
27 | : rocket::RpcInterface(req, rsp, done, controller) {
28 |
29 | }
30 |
31 | Interface::~Interface() {
32 |
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/generator/template/interface_base.h.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * File will not generate while exist
11 | * Allow editing
12 | ****************************************************/
13 |
14 | #ifndef ${HEADER_DEFINE}
15 | #define ${HEADER_DEFINE}
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | namespace ${PROJECT_NAME} {
23 |
24 | /*
25 | * Rpc Interface Base Class
26 | * All interface should extend this abstract class
27 | */
28 |
29 | class Interface : public rocket::RpcInterface {
30 | public:
31 |
32 | Interface(const google::protobuf::Message* req, google::protobuf::Message* rsp, rocket::RpcClosure* done, rocket::RpcController* controller);
33 |
34 | virtual ~Interface() = 0;
35 |
36 | };
37 |
38 |
39 | }
40 |
41 |
42 | #endif
--------------------------------------------------------------------------------
/generator/template/main.cc.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * Do not edit !!!
11 | ****************************************************/
12 |
13 |
14 |
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | ${INCLUDE_SERVER_HEADER}
24 |
25 | int main(int argc, char* argv[]) {
26 |
27 | if (argc != 2) {
28 | printf("Start ${PROJECT_NAME} error, argc not 2 \n");
29 | printf("Start like this: \n");
30 | printf("./${PROJECT_NAME} ../conf/rocket.xml \n");
31 | return 0;
32 | }
33 |
34 | rocket::Config::SetGlobalConfig(argv[1]);
35 |
36 | rocket::Logger::InitGlobalLogger();
37 |
38 | rocket::RpcDispatcher::GetRpcDispatcher()->registerService(std::make_shared<${CLASS_NAME}>());
39 |
40 | rocket::IPNetAddr::s_ptr addr = std::make_shared("127.0.0.1", rocket::Config::GetGlobalConfig()->m_port);
41 |
42 | rocket::TcpServer tcp_server(addr);
43 |
44 | tcp_server.start();
45 |
46 | return 0;
47 | }
--------------------------------------------------------------------------------
/generator/template/makefile.template:
--------------------------------------------------------------------------------
1 | #####################################################################
2 | ## **** *** **** * * ***** *****
3 | ## * * * * * **** *** *
4 | ## * * *** **** * * ***** *
5 | ## MakeFile
6 | ## Generated by rocket framework rocket_generator.py
7 | ## Create Time: ${CREATE_TIME}
8 | ## How to use:
9 | ## make clean && make -j4
10 | #####################################################################
11 |
12 |
13 |
14 | PATH_BIN = ../bin
15 | PATH_SERVICE = service
16 | PATH_INTERFACE = interface
17 | PATH_PB = pb
18 | PATH_COMM = comm
19 | PATH_STUBS = stubs
20 | PATH_OBJ = ../obj
21 | PATH_TEST_CLIENT = ../test_client
22 | PATH_TEST_CLIENT_TOOL = $(PATH_TEST_CLIENT)/test_tool
23 |
24 |
25 | # librocket
26 | # if you have installed librocket.a in another path, please modify it
27 | ROCKET_LIB = /usr/lib/librocket.a
28 | ROCKET_PATH = /usr/include/rocket
29 |
30 | # protobuf
31 | # if you have installed libprotobuf.a in another path, please modify it
32 | PROTOBUF_LIB = /usr/lib/libprotobuf.a
33 |
34 | # tinyxml
35 | # if you have installed libtinyxml.a in another path, please modify it
36 | TINYXML_LIB = /usr/lib/libtinyxml.a
37 |
38 | # out bin file
39 | TARGET = $(PATH_BIN)/${PROJECT_NAME}
40 |
41 | CXX := g++
42 |
43 | CXX_FLAGS := -g -O3 -std=c++11 -Wall -Wno-deprecated -Wno-unused-but-set-variable
44 |
45 | CXX_FLAGS += -I../ -I ./$(PATH_PB) -I ./$(PATH_SERVICE) -I ./$(PATH_INTERFACE) -I ./$(PATH_COMM) -I$(PATH_STUBS) -I$(ROCKET_PATH)
46 |
47 | LIBS += $(ROCKET_LIB)
48 |
49 | LIBS += $(PROTOBUF_LIB) $(TINYXML_LIB)
50 |
51 | PB_OBJS := $(patsubst $(PATH_PB)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_PB)/*.cc))
52 | STUB_OBJS := $(patsubst $(PATH_STUBS)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_STUBS)/*.cc))
53 | SERVICE_OBJS := $(patsubst $(PATH_SERVICE)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_SERVICE)/*.cc))
54 | INTERFACE_OBJS := $(patsubst $(PATH_INTERFACE)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_INTERFACE)/*.cc))
55 | COMM_OBJS := $(patsubst $(PATH_COMM)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_COMM)/*.cc))
56 | TEST_BINS := $(patsubst $(PATH_TEST_CLIENT)/%.cc, $(PATH_TEST_CLIENT_TOOL)/%, $(wildcard $(PATH_TEST_CLIENT)/*.cc))
57 |
58 | OUT : $(TARGET) $(TEST_BINS)
59 |
60 | $(TARGET) : $(PB_OBJS) $(STUB_OBJS) $(SERVICE_OBJS) $(INTERFACE_OBJS)
61 | $(CXX) $(CXX_FLAGS) main.cc -o $@ $^ $(LIBS) -ldl -lpthread
62 |
63 | $(PATH_TEST_CLIENT_TOOL)/%: $(PATH_TEST_CLIENT)/%.cc $(PB_OBJS)
64 | $(CXX) $(CXX_FLAGS) $< -o $@ $(LIBS) $(PB_OBJS) -ldl -lpthread
65 |
66 | $(PATH_OBJ)/%.o : $(PATH_PB)/%.cc
67 | $(CXX) $(CXX_FLAGS) -c $< -o $@
68 |
69 | $(PATH_OBJ)/%.o : $(PATH_SERVICE)/%.cc
70 | $(CXX) $(CXX_FLAGS) -c $< -o $@
71 |
72 | $(PATH_OBJ)/%.o : $(PATH_INTERFACE)/%.cc
73 | $(CXX) $(CXX_FLAGS) -c $< -o $@
74 |
75 | $(PATH_OBJ)/%.o : $(PATH_COMM)/%.cc
76 | $(CXX) $(CXX_FLAGS) -c $< -o $@
77 |
78 | $(PATH_OBJ)/%.o : $(PATH_STUBS)/%.cc
79 | $(CXX) $(CXX_FLAGS) -c $< -o $@
80 |
81 |
82 |
83 | PRINT-% : ; @echo $* = $($*)
84 |
85 | clean :
86 | rm -f $(PB_OBJS) $(STUB_OBJS) $(SERVICE_OBJS) $(INTERFACE_OBJS) $(COMM_OBJS) $(TARGET) $(TEST_BINS)
--------------------------------------------------------------------------------
/generator/template/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | FILE_NAME=$1
3 | PROJECT_NAME=$(basename ${FILE_NAME})
4 | CURRENT_PATH=$(cd $(dirname $0); pwd)
5 | PROJECT_ROOT_PATH=$(cd $(dirname $0); cd ..; pwd)
6 | PROJECT_BIN_FILE="${CURRENT_PATH}"/"${PROJECT_NAME}"
7 | PROJECT_CONF_FILE="../conf/rocket.xml"
8 |
9 |
10 | echo "Run rocket rpc project, name: ${PROJECT_NAME}, path: ${PROJECT_BIN_FILE}"
11 |
12 | if [ -z "$1" ]
13 | then
14 | echo "Please input execuable binary file!"
15 | fi
16 |
17 | # check bin file exist
18 | if [ ! -e ${PROJECT_BIN_FILE} ]
19 | then
20 | echo "Run rocket rpc server eror, file: ${PROJECT_BIN_FILE} not exist, please check file"
21 | exit -1
22 | fi
23 |
24 | # check config xml file exist
25 | if [ ! -e ${PROJECT_CONF_FILE} ]
26 | then
27 | echo "Run rocket rpc error, file: ${PROJECT_CONF_FILE} not exist, please check config file"
28 | exit -1
29 | fi
30 |
31 | # check bin file execute privilege
32 | if [ ! -x ${PROJECT_BIN_FILE} ]
33 | then
34 | echo "chmod +x : ${PROJECT_BIN_FILE}"
35 | chmod +x ${PROJECT_BIN_FILE}
36 | fi
37 |
38 | sh shutdown.sh ${PROJECT_NAME}
39 | nohup ./${PROJECT_NAME} ${PROJECT_CONF_FILE} & > ${PROJECT_ROOT_PATH}/log/${PROJECT_NAME}.nohup_log
40 | echo "Start rocket rpc server ${PROJECT_CONF_FILE} succ"
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/generator/template/server.cc.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * Do not edit !!!
11 | ****************************************************/
12 |
13 |
14 | #include
15 | #include
16 | #include
17 | ${INCLUDE_PB_HEADER}
18 | ${INCLUDE_SERVER_HEADER}
19 | ${INCLUDE_BUSINESS_EXCEPTION_HEADER}
20 | ${INCLUDE_SERVICE}
21 |
22 | #define CALL_RPC_INTERFACE(Type) \
23 | { \
24 | rocket::RpcClosure* clo = dynamic_cast(done); \
25 | rocket::RpcController* con = dynamic_cast(controller); \
26 | std::shared_ptr impl = std::make_shared(request, response, clo, con); \
27 | rocket::RunTime::GetRunTime()->m_rpc_interface = std::dynamic_pointer_cast(impl).get(); \
28 | response->set_ret_code(0); \
29 | response->set_res_info("OK"); \
30 | try { \
31 | impl->run(); \
32 | } catch (BusinessException& e) { \
33 | APPDEBUGLOG("business exception"); \
34 | response->set_ret_code(e.errorCode()); \
35 | response->set_res_info(e.errorInfo()); \
36 | } catch (rocket::RocketException& e) { \
37 | APPDEBUGLOG("RocketException"); \
38 | response->set_ret_code(-1); \
39 | response->set_res_info("Unknown RocketException"); \
40 | } catch (std::exception& e) { \
41 | APPDEBUGLOG("std::exception"); \
42 | response->set_ret_code(-1); \
43 | response->set_res_info("Unknown std::exception"); \
44 | } catch (...) { \
45 | APPDEBUGLOG("... exception"); \
46 | response->set_ret_code(-1); \
47 | response->set_res_info("Unknown exception"); \
48 | } \
49 | } \
50 |
51 | namespace ${PROJECT_NAME} {
52 |
53 | ${METHOD}
54 |
55 | }
--------------------------------------------------------------------------------
/generator/template/server.h.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | * Do not edit !!!
11 | ****************************************************/
12 |
13 |
14 | #ifndef ${HEADER_DEFINE}
15 | #define ${HEADER_DEFINE}
16 |
17 | #include
18 | ${INCLUDE_PB_HEADER}
19 |
20 | namespace ${PROJECT_NAME} {
21 |
22 | class ${CLASS_NAME} : public ${SERVICE_NAME} {
23 |
24 | public:
25 |
26 | ${CLASS_NAME}() = default;
27 |
28 | ~${CLASS_NAME}() = default;
29 |
30 | ${METHOD}
31 |
32 | };
33 |
34 | }
35 |
36 |
37 | #endif
--------------------------------------------------------------------------------
/generator/template/shutdown.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ -z "$1" ]
4 | then
5 | echo "Please input rocket server name!"
6 | exit -1
7 | fi
8 |
9 | FILE_NAME=$1
10 | PROJECT_NAME=$(basename ${FILE_NAME})
11 | CURRENT_PATH=$(cd $(dirname $0); pwd)
12 | PROJECT_BIN_FILE="${CURRENT_PATH}"/"${PROJECT_NAME}"
13 | PROJECT_CONF_FILE="../conf/rocket.xml"
14 |
15 | echo "Shutdown rocket rpc project, name: ${PROJECT_NAME}, path: ${PROJECT_BIN_FILE}"
16 |
17 | # check bin file exist
18 | if [ ! -e ${PROJECT_BIN_FILE} ]
19 | then
20 | echo "Shtdown rpcket rpc eror, file: ${PROJECT_BIN_FILE} not exist, please check file"
21 | exit -1
22 | fi
23 |
24 |
25 | proc_list=`ps -elf | grep "${PROJECT_NAME}" | grep -v 'grep' | grep -v 'shutdown.sh' | awk '{print $4}'`
26 | echo ${proc_list[0]}
27 |
28 | for i in ${proc_list[@]}
29 | do
30 | bin_path=`ls -l /proc/${i}/exe | awk '{print $11}'`
31 | echo ${bin_path}
32 | if [ "$bin_path" = "$PROJECT_BIN_FILE" ]
33 | then
34 | echo "kill this proc: ${i}"
35 | kill -9 ${i}
36 | fi
37 | done
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/generator/template/test_rocket_client.cc.template:
--------------------------------------------------------------------------------
1 | /****************************************************
2 | *
3 | * **** *** **** * * ***** *****
4 | * * * * * * **** *** *
5 | * * * *** **** * * ***** *
6 | *
7 | * ${FILE_NAME}
8 | * ${CREATE_TIME}
9 | * Generated by rocket framework rocket_generator.py
10 | ****************************************************/
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | ${INCLUDE_PB_HEADER}
19 |
20 |
21 | void test_client(const std::string& addr) {
22 |
23 | NEWMESSAGE(${REQUEST_TYPE}, request);
24 | NEWMESSAGE(${RESPONSE_TYPE}, response);
25 |
26 | // request->set_xxx(100);
27 |
28 | NEWRPCCONTROLLER(controller);
29 | controller->SetTimeout(2000);
30 |
31 | std::shared_ptr closure = std::make_shared(nullptr, [request, response, controller]() mutable {
32 | if (controller->GetErrorCode() == 0) {
33 | INFOLOG("call rpc success, request[%s], response[%s]", request->ShortDebugString().c_str(), response->ShortDebugString().c_str());
34 |
35 | } else {
36 | ERRORLOG("call rpc failed, request[%s], error code[%d], error info[%s]",
37 | request->ShortDebugString().c_str(),
38 | controller->GetErrorCode(),
39 | controller->GetErrorInfo().c_str());
40 | }
41 |
42 | exit(0);
43 | });
44 |
45 | CALLRPRC(addr, ${STUBCLASS}, ${METHOD_NAME}, controller, request, response, closure);
46 |
47 | }
48 |
49 | int main(int argc, char* argv[]) {
50 |
51 | if (argc != 3) {
52 | printf ("param error, Usage: ./client ip port\n");
53 | printf ("For example: ./client 127.0.0.1 12345\n");
54 | return -1;
55 | }
56 |
57 | rocket::Config::SetGlobalConfig(NULL);
58 |
59 | rocket::Logger::InitGlobalLogger(0);
60 |
61 | std::string addr = std::string(argv[1]) + ":" + std::string(argv[2]);
62 |
63 | test_client(addr);
64 |
65 | return 0;
66 | }
67 |
--------------------------------------------------------------------------------
/imgs/main-sub-reactor.drawio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gooddbird/rocket/0228310396a90c57b32a95fdae9a40a6dc2e5fce/imgs/main-sub-reactor.drawio.png
--------------------------------------------------------------------------------
/imgs/multiple_definition.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gooddbird/rocket/0228310396a90c57b32a95fdae9a40a6dc2e5fce/imgs/multiple_definition.jpg
--------------------------------------------------------------------------------
/make.sh:
--------------------------------------------------------------------------------
1 | #/usr/bin/bash
2 |
3 | function create_dir() {
4 | if [ ! -d $1 ]; then
5 | mkdir $1
6 | fi
7 | }
8 |
9 | create_dir 'bin'
10 | create_dir 'log'
11 | create_dir 'obj'
12 | create_dir 'lib'
13 |
14 | make clean && make -j4
15 |
--------------------------------------------------------------------------------
/makefile:
--------------------------------------------------------------------------------
1 | ##################################
2 | # makefile
3 | # ikerli
4 | # 2022-05-23
5 | ##################################
6 |
7 | PATH_BIN = bin
8 | PATH_LIB = lib
9 | PATH_OBJ = obj
10 |
11 | PATH_ROCKET = rocket
12 | PATH_COMM = $(PATH_ROCKET)/common
13 | PATH_NET = $(PATH_ROCKET)/net
14 | PATH_TCP = $(PATH_ROCKET)/net/tcp
15 | PATH_CODER = $(PATH_ROCKET)/net/coder
16 | PATH_RPC = $(PATH_ROCKET)/net/rpc
17 |
18 | PATH_TESTCASES = testcases
19 |
20 | # will install lib to /usr/lib/librocket.a
21 | PATH_INSTALL_LIB_ROOT = /usr/lib
22 |
23 | # will install all header file to /usr/include/rocket
24 | PATH_INSTALL_INC_ROOT = /usr/include
25 |
26 | PATH_INSTALL_INC_COMM = $(PATH_INSTALL_INC_ROOT)/$(PATH_COMM)
27 | PATH_INSTALL_INC_NET = $(PATH_INSTALL_INC_ROOT)/$(PATH_NET)
28 | PATH_INSTALL_INC_TCP = $(PATH_INSTALL_INC_ROOT)/$(PATH_TCP)
29 | PATH_INSTALL_INC_CODER = $(PATH_INSTALL_INC_ROOT)/$(PATH_CODER)
30 | PATH_INSTALL_INC_RPC = $(PATH_INSTALL_INC_ROOT)/$(PATH_RPC)
31 |
32 |
33 | # PATH_PROTOBUF = /usr/include/google
34 | # PATH_TINYXML = /usr/include/tinyxml
35 |
36 | CXX := g++
37 |
38 | CXXFLAGS += -g -O0 -std=c++11 -Wall -Wno-deprecated -Wno-unused-but-set-variable
39 |
40 | CXXFLAGS += -I./ -I$(PATH_ROCKET) -I$(PATH_COMM) -I$(PATH_NET) -I$(PATH_TCP) -I$(PATH_CODER) -I$(PATH_RPC)
41 |
42 | LIBS += /usr/lib/libprotobuf.a /usr/lib/libtinyxml.a
43 |
44 |
45 | COMM_OBJ := $(patsubst $(PATH_COMM)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_COMM)/*.cc))
46 | NET_OBJ := $(patsubst $(PATH_NET)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_NET)/*.cc))
47 | TCP_OBJ := $(patsubst $(PATH_TCP)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_TCP)/*.cc))
48 | CODER_OBJ := $(patsubst $(PATH_CODER)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_CODER)/*.cc))
49 | RPC_OBJ := $(patsubst $(PATH_RPC)/%.cc, $(PATH_OBJ)/%.o, $(wildcard $(PATH_RPC)/*.cc))
50 |
51 | ALL_TESTS : $(PATH_BIN)/test_log $(PATH_BIN)/test_eventloop $(PATH_BIN)/test_tcp $(PATH_BIN)/test_client $(PATH_BIN)/test_rpc_client $(PATH_BIN)/test_rpc_server
52 | # ALL_TESTS : $(PATH_BIN)/test_log
53 |
54 | TEST_CASE_OUT := $(PATH_BIN)/test_log $(PATH_BIN)/test_eventloop $(PATH_BIN)/test_tcp $(PATH_BIN)/test_client $(PATH_BIN)/test_rpc_client $(PATH_BIN)/test_rpc_server
55 |
56 | LIB_OUT := $(PATH_LIB)/librocket.a
57 |
58 | $(PATH_BIN)/test_log: $(LIB_OUT)
59 | $(CXX) $(CXXFLAGS) $(PATH_TESTCASES)/test_log.cc -o $@ $(LIB_OUT) $(LIBS) -ldl -pthread
60 |
61 | $(PATH_BIN)/test_eventloop: $(LIB_OUT)
62 | $(CXX) $(CXXFLAGS) $(PATH_TESTCASES)/test_eventloop.cc -o $@ $(LIB_OUT) $(LIBS) -ldl -pthread
63 |
64 | $(PATH_BIN)/test_tcp: $(LIB_OUT)
65 | $(CXX) $(CXXFLAGS) $(PATH_TESTCASES)/test_tcp.cc -o $@ $(LIB_OUT) $(LIBS) -ldl -pthread
66 |
67 | $(PATH_BIN)/test_client: $(LIB_OUT)
68 | $(CXX) $(CXXFLAGS) $(PATH_TESTCASES)/test_client.cc -o $@ $(LIB_OUT) $(LIBS) -ldl -pthread
69 |
70 | $(PATH_BIN)/test_rpc_client: $(LIB_OUT)
71 | $(CXX) $(CXXFLAGS) $(PATH_TESTCASES)/test_rpc_client.cc $(PATH_TESTCASES)/order.pb.cc -o $@ $(LIB_OUT) $(LIBS) -ldl -pthread
72 |
73 | $(PATH_BIN)/test_rpc_server: $(LIB_OUT)
74 | $(CXX) $(CXXFLAGS) $(PATH_TESTCASES)/test_rpc_server.cc $(PATH_TESTCASES)/order.pb.cc -o $@ $(LIB_OUT) $(LIBS) -ldl -pthread
75 |
76 |
77 | $(LIB_OUT): $(COMM_OBJ) $(NET_OBJ) $(TCP_OBJ) $(CODER_OBJ) $(RPC_OBJ)
78 | cd $(PATH_OBJ) && ar rcv librocket.a *.o && cp librocket.a ../lib/
79 |
80 | $(PATH_OBJ)/%.o : $(PATH_COMM)/%.cc
81 | $(CXX) $(CXXFLAGS) -c $< -o $@
82 |
83 |
84 | $(PATH_OBJ)/%.o : $(PATH_NET)/%.cc
85 | $(CXX) $(CXXFLAGS) -c $< -o $@
86 |
87 | $(PATH_OBJ)/%.o : $(PATH_TCP)/%.cc
88 | $(CXX) $(CXXFLAGS) -c $< -o $@
89 |
90 | $(PATH_OBJ)/%.o : $(PATH_CODER)/%.cc
91 | $(CXX) $(CXXFLAGS) -c $< -o $@
92 |
93 | $(PATH_OBJ)/%.o : $(PATH_RPC)/%.cc
94 | $(CXX) $(CXXFLAGS) -c $< -o $@
95 |
96 | # print something test
97 | # like this: make PRINT-PATH_BIN, and then will print variable PATH_BIN
98 | PRINT-% : ; @echo $* = $($*)
99 |
100 |
101 | # to clean
102 | clean :
103 | rm -f $(COMM_OBJ) $(NET_OBJ) $(TESTCASES) $(TEST_CASE_OUT) $(PATH_LIB)/librocket.a $(PATH_OBJ)/librocket.a $(PATH_OBJ)/*.o
104 |
105 | # install
106 | install:
107 | mkdir -p $(PATH_INSTALL_INC_COMM) $(PATH_INSTALL_INC_NET) $(PATH_INSTALL_INC_TCP) $(PATH_INSTALL_INC_CODER) $(PATH_INSTALL_INC_RPC)\
108 | && cp $(PATH_COMM)/*.h $(PATH_INSTALL_INC_COMM) \
109 | && cp $(PATH_NET)/*.h $(PATH_INSTALL_INC_NET) \
110 | && cp $(PATH_TCP)/*.h $(PATH_INSTALL_INC_TCP) \
111 | && cp $(PATH_CODER)/*.h $(PATH_INSTALL_INC_CODER) \
112 | && cp $(PATH_RPC)/*.h $(PATH_INSTALL_INC_RPC) \
113 | && cp $(LIB_OUT) $(PATH_INSTALL_LIB_ROOT)/
114 |
115 |
116 | # uninstall
117 | uninstall:
118 | rm -rf $(PATH_INSTALL_INC_ROOT)/rocket && rm -f $(PATH_INSTALL_LIB_ROOT)/librocket.a
--------------------------------------------------------------------------------
/rocket/common/config.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include "rocket/common/config.h"
3 |
4 |
5 |
6 | #define READ_XML_NODE(name, parent) \
7 | TiXmlElement* name##_node = parent->FirstChildElement(#name); \
8 | if (!name##_node) { \
9 | printf("Start rocket server error, failed to read node [%s]\n", #name); \
10 | exit(0); \
11 | } \
12 |
13 |
14 |
15 | #define READ_STR_FROM_XML_NODE(name, parent) \
16 | TiXmlElement* name##_node = parent->FirstChildElement(#name); \
17 | if (!name##_node|| !name##_node->GetText()) { \
18 | printf("Start rocket server error, failed to read config file %s\n", #name); \
19 | exit(0); \
20 | } \
21 | std::string name##_str = std::string(name##_node->GetText()); \
22 |
23 |
24 |
25 | namespace rocket {
26 |
27 |
28 | static Config* g_config = NULL;
29 |
30 |
31 | Config* Config::GetGlobalConfig() {
32 | return g_config;
33 | }
34 |
35 | void Config::SetGlobalConfig(const char* xmlfile) {
36 | if (g_config == NULL) {
37 | if (xmlfile != NULL) {
38 | g_config = new Config(xmlfile);
39 | } else {
40 | g_config = new Config();
41 | }
42 |
43 | }
44 | }
45 |
46 | Config::~Config() {
47 | if (m_xml_document) {
48 | delete m_xml_document;
49 | m_xml_document = NULL;
50 | }
51 | }
52 |
53 | Config::Config() {
54 | m_log_level = "DEBUG";
55 |
56 | }
57 |
58 | Config::Config(const char* xmlfile) {
59 | m_xml_document = new TiXmlDocument();
60 |
61 | bool rt = m_xml_document->LoadFile(xmlfile);
62 | if (!rt) {
63 | printf("Start rocket server error, failed to read config file %s, error info[%s] \n", xmlfile, m_xml_document->ErrorDesc());
64 | exit(0);
65 | }
66 |
67 | READ_XML_NODE(root, m_xml_document);
68 | READ_XML_NODE(log, root_node);
69 | READ_XML_NODE(server, root_node);
70 |
71 | READ_STR_FROM_XML_NODE(log_level, log_node);
72 | READ_STR_FROM_XML_NODE(log_file_name, log_node);
73 | READ_STR_FROM_XML_NODE(log_file_path, log_node);
74 | READ_STR_FROM_XML_NODE(log_max_file_size, log_node);
75 | READ_STR_FROM_XML_NODE(log_sync_interval, log_node);
76 |
77 | m_log_level = log_level_str;
78 | m_log_file_name = log_file_name_str;
79 | m_log_file_path = log_file_path_str;
80 | m_log_max_file_size = std::atoi(log_max_file_size_str.c_str()) ;
81 | m_log_sync_inteval = std::atoi(log_sync_interval_str.c_str());
82 |
83 | printf("LOG -- CONFIG LEVEL[%s], FILE_NAME[%s],FILE_PATH[%s] MAX_FILE_SIZE[%d B], SYNC_INTEVAL[%d ms]\n",
84 | m_log_level.c_str(), m_log_file_name.c_str(), m_log_file_path.c_str(), m_log_max_file_size, m_log_sync_inteval);
85 |
86 | READ_STR_FROM_XML_NODE(port, server_node);
87 | READ_STR_FROM_XML_NODE(io_threads, server_node);
88 |
89 | m_port = std::atoi(port_str.c_str());
90 | m_io_threads = std::atoi(io_threads_str.c_str());
91 |
92 |
93 | TiXmlElement* stubs_node = root_node->FirstChildElement("stubs");
94 |
95 | if (stubs_node) {
96 | for (TiXmlElement* node = stubs_node->FirstChildElement("rpc_server"); node; node = node->NextSiblingElement("rpc_server")) {
97 | RpcStub stub;
98 | stub.name = std::string(node->FirstChildElement("name")->GetText());
99 | stub.timeout = std::atoi(node->FirstChildElement("timeout")->GetText());
100 |
101 | std::string ip = std::string(node->FirstChildElement("ip")->GetText());
102 | uint16_t port = std::atoi(node->FirstChildElement("port")->GetText());
103 | stub.addr = std::make_shared(ip, port);
104 |
105 | m_rpc_stubs.insert(std::make_pair(stub.name, stub));
106 | }
107 | }
108 |
109 |
110 |
111 | printf("Server -- PORT[%d], IO Threads[%d]\n", m_port, m_io_threads);
112 |
113 | }
114 |
115 |
116 | }
--------------------------------------------------------------------------------
/rocket/common/config.h:
--------------------------------------------------------------------------------
1 | #ifndef ROCKET_COMMON_CONFIG_H
2 | #define ROCKET_COMMON_CONFIG_H
3 |
4 | #include