gen-statistics_items.py.pre.in 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #!@PYTHON@
  2. # Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  3. #
  4. # Permission to use, copy, modify, and/or distribute this software for any
  5. # purpose with or without fee is hereby granted, provided that the above
  6. # copyright notice and this permission notice appear in all copies.
  7. #
  8. # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  9. # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10. # AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  13. # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. # PERFORMANCE OF THIS SOFTWARE.
  15. import os
  16. import re
  17. import sys
  18. import json
  19. from xml.etree import ElementTree
  20. item_list = []
  21. localstatedir = '@@LOCALSTATEDIR@@'
  22. builddir = '@builddir@'
  23. srcdir = '@srcdir@'
  24. pre_suffix = '.pre'
  25. xmldocument_command_name = 'b10-auth'
  26. def need_generate(filepath, mtime):
  27. '''Check if we need to generate the specified file.
  28. To avoid unnecessary compilation, we skip (re)generating the file when
  29. the file already exists and newer than the base file.
  30. '''
  31. if os.path.exists(filepath) and\
  32. (os.path.getmtime(filepath) > mtime or
  33. os.path.getmtime(filepath) > os.path.getmtime(filepath+pre_suffix)):
  34. return False
  35. return True
  36. def import_definitions():
  37. global item_list
  38. items_definition_file = srcdir + os.sep + 'statistics_msg_items.def'
  39. item_definition = open(items_definition_file, 'r')
  40. re_splitter = re.compile('\t+')
  41. l = item_list
  42. lp = None
  43. for line in item_definition.readlines():
  44. element = re_splitter.split(line.rstrip())
  45. if element[0] == '':
  46. element.pop(0)
  47. if element[-1] == '=':
  48. l.append({'name': element[0], 'child': [], 'index': element[1],
  49. 'description': element[2], 'parent': lp})
  50. lp = l
  51. l = l[-1]['child']
  52. elif element[-1] == ';':
  53. l = lp
  54. lp = l[-1]['parent']
  55. else:
  56. l.append({'name': element[0], 'child': None, 'index': element[1],
  57. 'description': element[2], 'parent': lp})
  58. item_definition.close()
  59. return os.path.getmtime(items_definition_file)
  60. def generate_specfile(specfile, def_mtime):
  61. global item_list
  62. def convert_list(items, prefix = ''):
  63. spec_list = []
  64. default_map = {}
  65. for item in items:
  66. full_item_name = prefix + item['name']
  67. if item['child'] is None:
  68. default_map[item['name']] = 0
  69. spec_list.append({
  70. 'item_name': item['name'],
  71. 'item_optional': False,
  72. 'item_type': 'integer',
  73. 'item_default': 0,
  74. 'item_title': full_item_name,
  75. 'item_description': item['description'],
  76. })
  77. else:
  78. child_spec_list, child_default_map = \
  79. convert_list(item['child'], full_item_name + '.')
  80. spec_list.append({
  81. 'item_name': item['name'],
  82. 'item_type': 'map',
  83. 'item_optional': False,
  84. 'item_title': full_item_name,
  85. 'item_description': item['description'],
  86. 'item_default': child_default_map,
  87. 'map_item_spec': child_spec_list,
  88. })
  89. default_map[item['name']] = child_default_map
  90. return spec_list, default_map
  91. item_spec_list, item_default_map = convert_list(item_list)
  92. statistics_spec_list = [{
  93. 'item_name': 'zones',
  94. 'item_type': 'named_set',
  95. 'item_optional': False,
  96. 'item_title': 'Zone statistics',
  97. 'item_description':
  98. 'Zone statistics items. ' +
  99. "Items for all zones are stored in '_SERVER_'.",
  100. 'item_default': { '_SERVER_': item_default_map },
  101. 'named_set_item_spec': {
  102. 'item_name': 'zone',
  103. 'item_type': 'map',
  104. 'item_optional': False,
  105. 'item_default': {},
  106. 'map_item_spec': item_spec_list,
  107. },
  108. }]
  109. if need_generate(builddir+os.sep+specfile, def_mtime):
  110. stats_pre = open(builddir+os.sep+specfile+pre_suffix, 'r')
  111. stats_pre_json = json.loads(stats_pre.read().replace('@@LOCAL'+'STATEDIR@@',
  112. localstatedir))
  113. stats_pre.close()
  114. stats_pre_json['module_spec']['statistics'] = statistics_spec_list
  115. statistics_spec_json = json.dumps(stats_pre_json, sort_keys = True,
  116. indent = 2)
  117. stats_spec = open(builddir+os.sep+specfile, 'w')
  118. stats_spec.write(statistics_spec_json)
  119. stats_spec.close()
  120. else:
  121. print('skip generating ' + specfile)
  122. return
  123. def generate_docfile(docfile, def_mtime):
  124. global item_list
  125. def convert_list(items, tree, prefix = ''):
  126. for item in items:
  127. full_item_name = prefix + item['name']
  128. if item['child'] is None:
  129. child_element = ElementTree.SubElement(tree, 'varlistentry')
  130. term = ElementTree.SubElement(child_element, 'term')
  131. term.text = full_item_name
  132. list_item = ElementTree.SubElement(child_element, 'listitem')
  133. sim_para = ElementTree.SubElement(list_item, 'simpara')
  134. sim_para.text = ''
  135. prev = None
  136. for word in item['description'].split():
  137. if word == xmldocument_command_name:
  138. command = ElementTree.SubElement(sim_para, 'command')
  139. command.text = word
  140. para_tail = command
  141. command.tail = ' '
  142. prev = command
  143. else:
  144. if prev is None:
  145. sim_para.text += word + ' '
  146. else:
  147. prev.tail += word + ' '
  148. else:
  149. convert_list(item['child'], tree, full_item_name + '.')
  150. return
  151. if need_generate(builddir+os.sep+docfile, def_mtime):
  152. doc_pre = open(srcdir+os.sep+docfile+pre_suffix, 'r')
  153. doc_pre_xml = doc_pre.read().replace('@@LOCAL'+'STATEDIR@@',
  154. localstatedir)
  155. doc_pre.close
  156. variable_tree = ElementTree.Element('variablelist')
  157. convert_list(item_list, variable_tree)
  158. doc = open(builddir+os.sep+docfile, 'w')
  159. doc.write(doc_pre_xml.replace(
  160. '<!-- ### STATISTICS DATA PLACEHOLDER ### -->',
  161. str(ElementTree.tostring(variable_tree))))
  162. doc.close()
  163. else:
  164. print('skip generating ' + docfile)
  165. return
  166. def generate_cxx(itemsfile, ccfile, utfile, def_mtime):
  167. global item_list
  168. msg_counter_types = 'enum MSGCounterType {\n'
  169. item_names = []
  170. def convert_list(items, msg_counter_types, item_names_current, item_names):
  171. for item in items:
  172. if item['child'] is None:
  173. msg_counter_types += ' ' + item['index'] + ', ' +\
  174. '///< ' + item['description'] + '\n'
  175. item_names_current.append(' { "' + item['name'] +
  176. '", NULL, ' + item['index'] + ' },\n'
  177. )
  178. else:
  179. item_names_current_ = ['const struct CounterTypeTree ' +
  180. item['index'] + '[] = {\n']
  181. msg_counter_types, item_names_current_, item_names = \
  182. convert_list(item['child'], msg_counter_types,
  183. item_names_current_, item_names)
  184. item_names_current_.append(' { NULL, NULL, -1 }\n' +
  185. '};\n')
  186. item_names.extend(item_names_current_)
  187. item_names_current.append(' { "' + item['name'] + '", ' +
  188. item['index'] + ', -1 },\n')
  189. return msg_counter_types, item_names_current, item_names
  190. msg_counter_types, item_names_current, item_names = \
  191. convert_list(item_list, msg_counter_types, [], item_names)
  192. item_names.append('const struct CounterTypeTree MSGCounterTree[] = {\n')
  193. item_names.extend(item_names_current)
  194. item_names.append(' { NULL, NULL, -1 }\n' +
  195. '};\n')
  196. msg_counter_types += \
  197. ' // End of counter types\n' +\
  198. ' MSG_COUNTER_TYPES ///< The number of defined counters\n' +\
  199. '};\n'
  200. item_defs = msg_counter_types
  201. item_decls = ''.join(item_names)
  202. if need_generate(builddir+os.sep+itemsfile, def_mtime):
  203. statistics_items_h_pre = open(srcdir+os.sep+itemsfile+pre_suffix, 'r')
  204. items_pre = statistics_items_h_pre.read()
  205. statistics_items_h_pre.close
  206. statistics_items_h = open(builddir+os.sep+itemsfile, 'w')
  207. statistics_items_h.write(items_pre.replace(
  208. '// ### STATISTICS ITEMS DECLARATION ###', item_defs))
  209. statistics_items_h.close()
  210. else:
  211. print('skip generating ' + itemsfile)
  212. if need_generate(builddir+os.sep+ccfile, def_mtime):
  213. statistics_cc_pre = open(srcdir+os.sep+ccfile+pre_suffix, 'r')
  214. items_pre = statistics_cc_pre.read()
  215. statistics_cc_pre.close
  216. statistics_cc = open(builddir+os.sep+ccfile, 'w')
  217. statistics_cc.write(items_pre.replace(
  218. '// ### STATISTICS ITEMS DEFINITION ###', item_decls))
  219. statistics_cc.close()
  220. else:
  221. print('skip generating ' + ccfile)
  222. if need_generate(builddir+os.sep+utfile, def_mtime):
  223. statistics_ut_cc_pre = open(srcdir+os.sep+utfile+pre_suffix, 'r')
  224. items_pre = statistics_ut_cc_pre.read()
  225. statistics_ut_cc_pre.close
  226. statistics_ut_cc = open(builddir+os.sep+utfile, 'w')
  227. statistics_ut_cc.write(items_pre.replace(
  228. '// ### STATISTICS ITEMS DEFINITION ###', item_decls))
  229. statistics_ut_cc.close()
  230. else:
  231. print('skip generating ' + utfile)
  232. return
  233. if __name__ == "__main__":
  234. try:
  235. def_mtime = import_definitions()
  236. generate_specfile('auth.spec', def_mtime)
  237. generate_docfile('b10-auth.xml', def_mtime)
  238. generate_cxx('statistics_items.h',
  239. 'statistics.cc',
  240. 'tests'+os.sep+'statistics_unittest.cc',
  241. def_mtime)
  242. except:
  243. sys.stderr.write('Code generation failed due to exception: %s\n' %
  244. sys.exc_info()[1])
  245. exit(1)