1# Read the source files and output the statistics #defines plus the 2# initialize and refresh code. 3 4import re, string, sys, textwrap 5from dist import compare_srcfile 6 7# Read the source files. 8from stat_data import groups, dsrc_stats, connection_stats, join_stats 9 10def print_struct(title, name, base, stats): 11 '''Print the structures for the stat.h file.''' 12 f.write('/*\n') 13 f.write(' * Statistics entries for ' + title + '.\n') 14 f.write(' */\n') 15 f.write('#define\tWT_' + name.upper() + '_STATS_BASE\t' + str(base) + '\n') 16 f.write('struct __wt_' + name + '_stats {\n') 17 18 for l in stats: 19 f.write('\tint64_t ' + l.name + ';\n') 20 f.write('};\n\n') 21 22# Update the #defines in the stat.h file. 23tmp_file = '__tmp' 24f = open(tmp_file, 'w') 25skip = 0 26for line in open('../src/include/stat.h', 'r'): 27 if not skip: 28 f.write(line) 29 if line.count('Statistics section: END'): 30 f.write(line) 31 skip = 0 32 elif line.count('Statistics section: BEGIN'): 33 f.write('\n') 34 skip = 1 35 print_struct( 36 'connections', 'connection', 1000, connection_stats) 37 print_struct('data sources', 'dsrc', 2000, dsrc_stats) 38 print_struct('join cursors', 'join', 3000, join_stats) 39f.close() 40compare_srcfile(tmp_file, '../src/include/stat.h') 41 42def print_defines_one(capname, base, stats): 43 for v, l in enumerate(stats, base): 44 desc = l.desc 45 if 'cache_walk' in l.flags: 46 desc += \ 47 ', only reported if cache_walk or all statistics are enabled' 48 if 'tree_walk' in l.flags: 49 desc += ', only reported if tree_walk or all statistics are enabled' 50 if len(textwrap.wrap(desc, 70)) > 1: 51 f.write('/*!\n') 52 f.write(' * %s\n' % '\n * '.join(textwrap.wrap(desc, 70))) 53 f.write(' */\n') 54 else: 55 f.write('/*! %s */\n' % desc) 56 #f.write('/*! %s */\n' % '\n * '.join(textwrap.wrap(desc, 70))) 57 f.write('#define\tWT_STAT_' + capname + '_' + l.name.upper() + "\t" * 58 max(1, 6 - int((len('WT_STAT_' + capname + '_' + l.name)) / 8)) + 59 str(v) + '\n') 60 61def print_defines(): 62 '''Print the #defines for the wiredtiger.in file.''' 63 f.write(''' 64/*! 65 * @name Connection statistics 66 * @anchor statistics_keys 67 * @anchor statistics_conn 68 * Statistics are accessed through cursors with \c "statistics:" URIs. 69 * Individual statistics can be queried through the cursor using the following 70 * keys. See @ref data_statistics for more information. 71 * @{ 72 */ 73''') 74 print_defines_one('CONN', 1000, connection_stats) 75 f.write(''' 76/*! 77 * @} 78 * @name Statistics for data sources 79 * @anchor statistics_dsrc 80 * @{ 81 */ 82''') 83 print_defines_one('DSRC', 2000, dsrc_stats) 84 f.write(''' 85/*! 86 * @} 87 * @name Statistics for join cursors 88 * @anchor statistics_join 89 * @{ 90 */ 91''') 92 print_defines_one('JOIN', 3000, join_stats) 93 f.write('/*! @} */\n') 94 95# Update the #defines in the wiredtiger.in file. 96tmp_file = '__tmp' 97f = open(tmp_file, 'w') 98skip = 0 99for line in open('../src/include/wiredtiger.in', 'r'): 100 if not skip: 101 f.write(line) 102 if line.count('Statistics section: END'): 103 f.write(line) 104 skip = 0 105 elif line.count('Statistics section: BEGIN'): 106 f.write(' */\n') 107 skip = 1 108 print_defines() 109 f.write('/*\n') 110f.close() 111compare_srcfile(tmp_file, '../src/include/wiredtiger.in') 112 113def print_func(name, handle, statlist): 114 '''Print the structures/functions for the stat.c file.''' 115 f.write('\n') 116 f.write('static const char * const __stats_' + name + '_desc[] = {\n') 117 for l in statlist: 118 f.write('\t"' + l.desc + '",\n') 119 f.write('};\n') 120 121 f.write(''' 122int 123__wt_stat_''' + name + '''_desc(WT_CURSOR_STAT *cst, int slot, const char **p) 124{ 125\tWT_UNUSED(cst); 126\t*p = __stats_''' + name + '''_desc[slot]; 127\treturn (0); 128} 129''') 130 131 f.write(''' 132void 133__wt_stat_''' + name + '_init_single(WT_' + name.upper() + '''_STATS *stats) 134{ 135\tmemset(stats, 0, sizeof(*stats)); 136} 137''') 138 139 if handle != None: 140 f.write(''' 141int 142__wt_stat_''' + name + '''_init( 143 WT_SESSION_IMPL *session, ''' + handle + ''' *handle) 144{ 145\tint i; 146 147\tWT_RET(__wt_calloc(session, (size_t)WT_COUNTER_SLOTS, 148\t sizeof(*handle->stat_array), &handle->stat_array)); 149 150\tfor (i = 0; i < WT_COUNTER_SLOTS; ++i) { 151\t\thandle->stats[i] = &handle->stat_array[i]; 152\t\t__wt_stat_''' + name + '''_init_single(handle->stats[i]); 153\t} 154\treturn (0); 155} 156 157void 158__wt_stat_''' + name + '''_discard( 159 WT_SESSION_IMPL *session, ''' + handle + ''' *handle) 160{ 161\t__wt_free(session, handle->stat_array); 162} 163''') 164 165 f.write(''' 166void 167__wt_stat_''' + name + '_clear_single(WT_' + name.upper() + '''_STATS *stats) 168{ 169''') 170 for l in statlist: 171 # no_clear: don't clear the value. 172 if 'no_clear' in l.flags: 173 f.write('\t\t/* not clearing ' + l.name + ' */\n') 174 else: 175 f.write('\tstats->' + l.name + ' = 0;\n') 176 f.write('}\n') 177 178 f.write(''' 179void 180__wt_stat_''' + name + '_clear_all(WT_' + name.upper() + '''_STATS **stats) 181{ 182\tu_int i; 183 184\tfor (i = 0; i < WT_COUNTER_SLOTS; ++i) 185\t\t__wt_stat_''' + name + '''_clear_single(stats[i]); 186} 187''') 188 189 # Single structure aggregation is currently only used by data sources. 190 if name == 'dsrc': 191 f.write(''' 192void 193__wt_stat_''' + name + '''_aggregate_single( 194 WT_''' + name.upper() + '_STATS *from, WT_' + name.upper() + '''_STATS *to) 195{ 196''') 197 for l in statlist: 198 if 'max_aggregate' in l.flags: 199 o = '\tif (from->' + l.name + ' > to->' + l.name + ')\n' +\ 200 '\t\tto->' + l.name + ' = from->' + l.name + ';\n' 201 else: 202 o = '\tto->' + l.name + ' += from->' + l.name + ';\n' 203 if len(o) > 72: # Account for the leading tab. 204 o = o.replace(' += ', ' +=\n\t ') 205 f.write(o) 206 f.write('}\n') 207 208 f.write(''' 209void 210__wt_stat_''' + name + '''_aggregate( 211 WT_''' + name.upper() + '_STATS **from, WT_' + name.upper() + '''_STATS *to) 212{ 213''') 214 # Connection level aggregation does not currently have any computation 215 # of a maximum value; I'm leaving in support for it, but don't declare 216 # a temporary variable until it's needed. 217 for l in statlist: 218 if 'max_aggregate' in l.flags: 219 f.write('\tint64_t v;\n\n') 220 break; 221 for l in statlist: 222 if 'max_aggregate' in l.flags: 223 o = '\tif ((v = WT_STAT_READ(from, ' + l.name + ')) > ' +\ 224 'to->' + l.name + ')\n' 225 if len(o) > 72: # Account for the leading tab. 226 o = o.replace(' > ', ' >\n\t ') 227 o +='\t\tto->' + l.name + ' = v;\n' 228 else: 229 o = '\tto->' + l.name + ' += WT_STAT_READ(from, ' + l.name + ');\n' 230 if len(o) > 72: # Account for the leading tab. 231 o = o.replace(' += ', ' +=\n\t ') 232 f.write(o) 233 f.write('}\n') 234 235# Write the stat initialization and refresh routines to the stat.c file. 236f = open(tmp_file, 'w') 237f.write('/* DO NOT EDIT: automatically built by dist/stat.py. */\n\n') 238f.write('#include "wt_internal.h"\n') 239 240print_func('dsrc', 'WT_DATA_HANDLE', dsrc_stats) 241print_func('connection', 'WT_CONNECTION_IMPL', connection_stats) 242print_func('join', None, join_stats) 243f.close() 244compare_srcfile(tmp_file, '../src/support/stat.c') 245