gen-statistics_items.py.pre.in 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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 os.path.getmtime(filepath) > mtime:
  32. return False
  33. return True
  34. def import_definitions():
  35. global item_list
  36. items_definition_file = srcdir + os.sep + 'statistics_qr_items.def'
  37. item_definition = open(items_definition_file, 'r')
  38. re_splitter = re.compile('\t+')
  39. l = item_list
  40. lp = None
  41. for line in item_definition.readlines():
  42. element = re_splitter.split(line.rstrip())
  43. if element[0] == '':
  44. element.pop(0)
  45. if element[-1] == '=':
  46. l.append({'name': element[0], 'child': [], 'index': element[1],
  47. 'description': element[2], 'parent': lp})
  48. lp = l
  49. l = l[-1]['child']
  50. elif element[-1] == ';':
  51. l = lp
  52. lp = l[-1]['parent']
  53. else:
  54. l.append({'name': element[0], 'child': None, 'index': element[1],
  55. 'description': element[2], 'parent': lp})
  56. item_definition.close()
  57. return os.path.getmtime(items_definition_file)
  58. def generate_specfile(specfile, def_mtime):
  59. global item_list
  60. def convert_list(items, prefix = ''):
  61. spec_list = []
  62. default_map = {}
  63. for item in items:
  64. full_item_name = prefix + item['name']
  65. if item['child'] is None:
  66. default_map[item['name']] = 0
  67. spec_list.append({
  68. 'item_name': item['name'],
  69. 'item_optional': False,
  70. 'item_type': 'integer',
  71. 'item_default': 0,
  72. 'item_title': full_item_name,
  73. 'item_description': item['description'],
  74. })
  75. else:
  76. child_spec_list, child_default_map = \
  77. convert_list(item['child'], full_item_name + '.')
  78. spec_list.append({
  79. 'item_name': item['name'],
  80. 'item_type': 'map',
  81. 'item_optional': False,
  82. 'item_title': full_item_name,
  83. 'item_description': item['description'],
  84. 'item_default': child_default_map,
  85. 'map_item_spec': child_spec_list,
  86. })
  87. default_map[item['name']] = child_default_map
  88. return spec_list, default_map
  89. item_spec_list, item_default_map = convert_list(item_list)
  90. statistics_spec_list = [{
  91. 'item_name': 'zones',
  92. 'item_type': 'named_set',
  93. 'item_optional': False,
  94. 'item_title': 'Zone statistics',
  95. 'item_description':
  96. 'Zone statistics items. ' +
  97. "Items for all zones are stored in '_SERVER_'.",
  98. 'item_default': { '_SERVER_': item_default_map },
  99. 'named_set_item_spec': {
  100. 'item_name': 'zone',
  101. 'item_type': 'map',
  102. 'item_optional': False,
  103. 'item_default': {},
  104. 'map_item_spec': item_spec_list,
  105. },
  106. }]
  107. if need_generate(builddir+os.sep+specfile, def_mtime):
  108. stats_pre = open(builddir+os.sep+specfile+pre_suffix, 'r')
  109. stats_pre_json = json.loads(stats_pre.read().replace('@@LOCAL'+'STATEDIR@@',
  110. localstatedir))
  111. stats_pre.close()
  112. stats_pre_json['module_spec']['statistics'] = statistics_spec_list
  113. statistics_spec_json = json.dumps(stats_pre_json, sort_keys = True,
  114. indent = 2)
  115. stats_spec = open(builddir+os.sep+specfile, 'w')
  116. stats_spec.write(statistics_spec_json)
  117. stats_spec.close()
  118. else:
  119. print('skip generating ' + specfile)
  120. return
  121. def generate_docfile(docfile, def_mtime):
  122. global item_list
  123. def convert_list(items, tree, prefix = ''):
  124. for item in items:
  125. full_item_name = prefix + item['name']
  126. if item['child'] is None:
  127. child_element = ElementTree.SubElement(tree, 'varlistentry')
  128. term = ElementTree.SubElement(child_element, 'term')
  129. term.text = full_item_name
  130. list_item = ElementTree.SubElement(child_element, 'listitem')
  131. sim_para = ElementTree.SubElement(list_item, 'simpara')
  132. sim_para.text = ''
  133. prev = None
  134. for word in item['description'].split():
  135. if word == xmldocument_command_name:
  136. command = ElementTree.SubElement(sim_para, 'command')
  137. command.text = word
  138. para_tail = command
  139. command.tail = ' '
  140. prev = command
  141. else:
  142. if prev is None:
  143. sim_para.text += word + ' '
  144. else:
  145. prev.tail += word + ' '
  146. else:
  147. convert_list(item['child'], tree, full_item_name + '.')
  148. return
  149. if need_generate(builddir+os.sep+docfile, def_mtime):
  150. doc_pre = open(srcdir+os.sep+docfile+pre_suffix, 'r')
  151. doc_pre_xml = doc_pre.read().replace('@@LOCAL'+'STATEDIR@@',
  152. localstatedir)
  153. doc_pre.close
  154. variable_tree = ElementTree.Element('variablelist')
  155. convert_list(item_list, variable_tree)
  156. doc = open(builddir+os.sep+docfile, 'w')
  157. doc.write(doc_pre_xml.replace(
  158. '<!-- ### STATISTICS DATA PLACEHOLDER ### -->',
  159. str(ElementTree.tostring(variable_tree))))
  160. doc.close()
  161. else:
  162. print('skip generating ' + docfile)
  163. return
  164. def generate_cxx(itemsfile, ccfile, utfile, def_mtime):
  165. global item_list
  166. qr_counter_types = 'enum QRCounterType {\n'
  167. item_names = []
  168. def convert_list(items, qr_counter_types, item_names_current, item_names):
  169. for item in items:
  170. if item['child'] is None:
  171. qr_counter_types += ' ' + item['index'] + ', ' +\
  172. '///< ' + item['description'] + '\n'
  173. item_names_current.append(' { "' + item['name'] +
  174. '", NULL, ' + item['index'] + ' },\n'
  175. )
  176. else:
  177. item_names_current_ = ['const struct CounterTypeTree ' +
  178. item['index'] + '[] = {\n']
  179. qr_counter_types, item_names_current_, item_names = \
  180. convert_list(item['child'], qr_counter_types,
  181. item_names_current_, item_names)
  182. item_names_current_.append(' { NULL, NULL, -1 }\n' +
  183. '};\n')
  184. item_names.extend(item_names_current_)
  185. item_names_current.append(' { "' + item['name'] + '", ' +
  186. item['index'] + ', -1 },\n')
  187. return qr_counter_types, item_names_current, item_names
  188. qr_counter_types, item_names_current, item_names = \
  189. convert_list(item_list, qr_counter_types, [], item_names)
  190. item_names.append('const struct CounterTypeTree QRCounterTree[] = {\n')
  191. item_names.extend(item_names_current)
  192. item_names.append(' { NULL, NULL, -1 }\n' +
  193. '};\n')
  194. qr_counter_types += \
  195. ' // End of counter types\n' +\
  196. ' QR_COUNTER_TYPES ///< The number of defined counters\n' +\
  197. '};\n'
  198. item_defs = qr_counter_types
  199. item_decls = ''.join(item_names)
  200. if need_generate(builddir+os.sep+itemsfile, def_mtime):
  201. statistics_items_h_pre = open(srcdir+os.sep+itemsfile+pre_suffix, 'r')
  202. items_pre = statistics_items_h_pre.read()
  203. statistics_items_h_pre.close
  204. statistics_items_h = open(builddir+os.sep+itemsfile, 'w')
  205. statistics_items_h.write(items_pre.replace(
  206. '// ### STATISTICS ITEMS DECLARATION ###', item_defs))
  207. statistics_items_h.close()
  208. else:
  209. print('skip generating ' + itemsfile)
  210. if need_generate(builddir+os.sep+ccfile, def_mtime):
  211. statistics_cc_pre = open(srcdir+os.sep+ccfile+pre_suffix, 'r')
  212. items_pre = statistics_cc_pre.read()
  213. statistics_cc_pre.close
  214. statistics_cc = open(builddir+os.sep+ccfile, 'w')
  215. statistics_cc.write(items_pre.replace(
  216. '// ### STATISTICS ITEMS DEFINITION ###', item_decls))
  217. statistics_cc.close()
  218. else:
  219. print('skip generating ' + ccfile)
  220. if need_generate(builddir+os.sep+utfile, def_mtime):
  221. statistics_ut_cc_pre = open(srcdir+os.sep+utfile+pre_suffix, 'r')
  222. items_pre = statistics_ut_cc_pre.read()
  223. statistics_ut_cc_pre.close
  224. statistics_ut_cc = open(builddir+os.sep+utfile, 'w')
  225. statistics_ut_cc.write(items_pre.replace(
  226. '// ### STATISTICS ITEMS DEFINITION ###', item_decls))
  227. statistics_ut_cc.close()
  228. else:
  229. print('skip generating ' + utfile)
  230. return
  231. if __name__ == "__main__":
  232. try:
  233. def_mtime = import_definitions()
  234. generate_specfile('auth.spec', def_mtime)
  235. generate_docfile('b10-auth.xml', def_mtime)
  236. generate_cxx('statistics_items.h',
  237. 'statistics.cc',
  238. 'tests'+os.sep+'statistics_unittest.cc',
  239. def_mtime)
  240. except:
  241. sys.stderr.write('Code generation failed due to exception: %s\n' %
  242. sys.exc_info()[1])
  243. exit(1)