diff options
author | Eliot Horowitz <eliot@10gen.com> | 2014-11-04 15:46:40 -0500 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2014-11-05 11:21:19 -0500 |
commit | 5ca2daf551a2c631a5f573cb054406f5d49fbef5 (patch) | |
tree | b0a23d34ffdb376bac0b79ed17b5619cfc0d9b47 /src/third_party/wiredtiger/dist/api_config.py | |
parent | 017704acdfc7517efadb3fab167bba06c025c01a (diff) | |
download | mongo-5ca2daf551a2c631a5f573cb054406f5d49fbef5.tar.gz |
SERVER-15953: add wiredtiger to third_party
Diffstat (limited to 'src/third_party/wiredtiger/dist/api_config.py')
-rw-r--r-- | src/third_party/wiredtiger/dist/api_config.py | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/dist/api_config.py b/src/third_party/wiredtiger/dist/api_config.py new file mode 100644 index 00000000000..6ca0275f228 --- /dev/null +++ b/src/third_party/wiredtiger/dist/api_config.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python + +import os, re, sys, textwrap +import api_data +from dist import compare_srcfile + +# Temporary file. +tmp_file = '__tmp' + +##################################################################### +# Update wiredtiger.in with doxygen comments +##################################################################### +f='../src/include/wiredtiger.in' +tfile = open(tmp_file, 'w') + +whitespace_re = re.compile(r'\s+') +cbegin_re = re.compile(r'(\s*\*\s*)@config(?:empty|start)\{(.*?),.*\}') + +def gettype(c): + '''Derive the type of a config item''' + checks = c.flags + ctype = checks.get('type', None) + if not ctype and ('min' in checks or 'max' in checks): + ctype = 'int' + return ctype or 'string' + +def typedesc(c): + '''Descripe what type of value is expected for the given config item''' + checks = c.flags + cmin = str(checks.get('min', '')) + cmax = str(checks.get('max', '')) + choices = checks.get('choices', []) + ctype = gettype(c) + desc = { + 'boolean' : 'a boolean flag', + 'format' : 'a format string', + 'int' : 'an integer', + 'list' : 'a list', + 'category': 'a set of related configuration options defined below', + 'string' : 'a string'}[ctype] + if cmin and cmax: + desc += ' between ' + cmin + ' and ' + cmax + elif cmin: + desc += ' greater than or equal to ' + cmin + elif cmax: + desc += ' no more than ' + cmax + if choices: + if ctype == 'list': + desc += ', with values chosen from the following options: ' + else: + desc += ', chosen from the following options: ' + desc += ', '.join('\\c "' + c + '"' for c in choices) + elif ctype == 'list': + desc += ' of strings' + return desc + +def parseconfig(c, name_indent=''): + ctype = gettype(c) + desc = whitespace_re.sub(' ', c.desc.strip()) + desc = desc.strip('.') + '.' + desc = desc.replace(',', '\\,') + default = '\\c ' + str(c.default) if c.default or ctype == 'int' \ + else 'empty' + name = name_indent + c.name + + tdesc = typedesc(c) + if ctype != 'category': + tdesc += '; default ' + default + else: + name += ' = (' + tdesc += '.' + tdesc = tdesc.replace(',', '\\,') + output = '@config{' + ', '.join((name, desc, tdesc)) + '}\n' + if ctype == 'category': + for subc in sorted(c.subconfig): + output += parseconfig(subc, name_indent + (' ' * 4)) + output += '@config{ ),,}\n' + return output + +def getconfcheck(c): + check = '{ "' + c.name + '", "' + gettype(c) + '",' + cstr = checkstr(c) + sstr = getsubconfigstr(c) + if cstr != 'NULL': + cstr = '"\n\t "'.join(w.wrap(cstr)) + # Manually re-wrap when there is a check string to avoid ugliness + # between string and non-string wrapping + if len(check + ' ' + cstr + ',\n\t ' + sstr + '},') >= 68: + check = check + '\n\t ' + cstr + ',\n\t ' + sstr + ' },' + else: + check = check + ' ' + cstr + ', ' + sstr + ' },' + else: + check = '\n\t '.join( + w.wrap(check + ' ' + cstr + ', ' + sstr + ' },')) + return check + +skip = False +for line in open(f, 'r'): + if skip: + if '@configend' in line: + skip = False + continue + + m = cbegin_re.match(line) + if not m: + tfile.write(line) + continue + + prefix, config_name = m.groups() + if config_name not in api_data.methods: + print >>sys.stderr, "Missing configuration for " + config_name + tfile.write(line) + continue + + skip = ('@configstart' in line) + + if not api_data.methods[config_name].config: + tfile.write(prefix + '@configempty{' + config_name + + ', see dist/api_data.py}\n') + continue + + tfile.write(prefix + '@configstart{' + config_name + + ', see dist/api_data.py}\n') + + w = textwrap.TextWrapper(width=80-len(prefix.expandtabs()), + break_on_hyphens=False, + replace_whitespace=False, + fix_sentence_endings=True) + lastname = None + for c in sorted(api_data.methods[config_name].config): + name = c.name + if '.' in name: + print >>sys.stderr, "Bad config key " + name + + # Deal with duplicates: with complex configurations (like + # WT_SESSION::create), it's simpler to deal with duplicates here than + # manually in api_data.py. + if name == lastname: + continue + lastname = name + if 'undoc' in c.flags: + continue + output = parseconfig(c) + for l in w.wrap(output): + tfile.write(prefix + l.replace('\n', '\n' + prefix) + '\n') + + tfile.write(prefix + '@configend\n') + +tfile.close() +compare_srcfile(tmp_file, f) + +##################################################################### +# Create config_def.c with defaults for each config string +##################################################################### +f='../src/config/config_def.c' +tfile = open(tmp_file, 'w') + +tfile.write('''/* DO NOT EDIT: automatically built by dist/config.py. */ + +#include "wt_internal.h" +''') + +# Make a TextWrapper that can wrap at commas. +w = textwrap.TextWrapper(width=64, break_on_hyphens=False) +w.wordsep_re = w.wordsep_simple_re = re.compile(r'(,)') + +def checkstr(c): + '''Generate the JSON string used by __wt_config_check to validate the + config string''' + checks = c.flags + cmin = str(checks.get('min', '')) + cmax = str(checks.get('max', '')) + choices = checks.get('choices', []) + result = [] + if cmin: + result.append('min=' + cmin) + if cmax: + result.append('max=' + cmax) + if choices: + result.append('choices=' + '[' + + ','.join('\\"' + s + '\\"' for s in choices) + ']') + if result: + return '"' + ','.join(result) + '"' + else: + return 'NULL' + +def get_default(c): + t = gettype(c) + if c.default == 'false': + return '0' + elif t == 'category': + return '(%s)' % (','.join('%s=%s' % (subc.name, get_default(subc)) + for subc in sorted(c.subconfig))) + elif (c.default or t == 'int') and c.default != 'true': + return str(c.default).replace('"', '\\"') + else: + return '' + +created_subconfigs=set() +def add_subconfig(c): + if c.name in created_subconfigs: + return + created_subconfigs.add(c.name) + tfile.write(''' +static const WT_CONFIG_CHECK confchk_%(name)s_subconfigs[] = { +\t%(check)s +\t{ NULL, NULL, NULL, NULL } +}; +''' % { + 'name' : c.name, + 'check' : '\n\t'.join(getconfcheck(subc) for subc in sorted(c.subconfig)), +}) + +def getsubconfigstr(c): + '''Return a string indicating if an item has sub configuration''' + ctype = gettype(c) + if ctype == 'category': + add_subconfig(c) + return 'confchk_' + c.name + '_subconfigs' + else: + return 'NULL' + +# Write structures of arrays of allowable configuration options, including a +# NULL as a terminator for iteration. +for name in sorted(api_data.methods.keys()): + ctype = api_data.methods[name].config + if ctype: + tfile.write(''' +static const WT_CONFIG_CHECK confchk_%(name)s[] = { +\t%(check)s +\t{ NULL, NULL, NULL, NULL } +}; +''' % { + 'name' : name.replace('.', '_'), + 'check' : '\n\t'.join(getconfcheck(c) for c in sorted(ctype)), +}) + +# Write the initialized list of configuration entry structures. +tfile.write('\n') +tfile.write('static const WT_CONFIG_ENTRY config_entries[] = {') + +slot=-1 +config_defines = '' +for name in sorted(api_data.methods.keys()): + ctype = api_data.methods[name].config + slot += 1 + + # Build a list of #defines that reference specific slots in the list (the + # #defines are used to avoid a list search where we know the correct slot). + config_defines +=\ + '#define\tWT_CONFIG_ENTRY_' + name.replace('.', '_') + '\t' * \ + max(1, 6 - (len('WT_CONFIG_ENTRY_' + name) / 8)) + \ + "%2s" % str(slot) + '\n' + + # Write the method name and base. + tfile.write(''' +\t{ "%(name)s", +%(config)s,''' % { + 'config' : '\n'.join('\t "%s"' % line + for line in w.wrap(','.join('%s=%s' % (c.name, get_default(c)) + for c in sorted(ctype))) or [""]), + 'name' : name +}) + + # Write the checks reference, or NULL if no related checks structure. + tfile.write('\n\t ') + if ctype: + tfile.write('confchk_' + name.replace('.', '_')) + else: + tfile.write('NULL') + + tfile.write('\n\t},') + +# Write a NULL as a terminator for iteration. +tfile.write('\n\t{ NULL, NULL, NULL }') +tfile.write('\n};\n') + +# Write the routine that connects the WT_CONNECTION_IMPL structure to the list +# of configuration entry structures. +tfile.write(''' +int +__wt_conn_config_init(WT_SESSION_IMPL *session) +{ +\tWT_CONNECTION_IMPL *conn; +\tconst WT_CONFIG_ENTRY *ep, **epp; + +\tconn = S2C(session); + +\t/* Build a list of pointers to the configuration information. */ +\tWT_RET(__wt_calloc_def(session, +\t sizeof(config_entries) / sizeof(config_entries[0]), &epp)); +\tconn->config_entries = epp; + +\t/* Fill in the list to reference the default information. */ +\tfor (ep = config_entries;;) { +\t\t*epp++ = ep++; +\t\tif (ep->method == NULL) +\t\t\tbreak; +\t} +\treturn (0); +} + +void +__wt_conn_config_discard(WT_SESSION_IMPL *session) +{ +\tWT_CONNECTION_IMPL *conn; + +\tconn = S2C(session); + +\t__wt_free(session, conn->config_entries); +} +''') + +tfile.close() +compare_srcfile(tmp_file, f) + +# Update the config.h file with the #defines for the configuration entries. +tfile = open(tmp_file, 'w') +skip = 0 +for line in open('../src/include/config.h', 'r'): + if skip: + if 'configuration section: END' in line: + tfile.write('/*\n' + line) + skip = 0 + else: + tfile.write(line) + if 'configuration section: BEGIN' in line: + skip = 1 + tfile.write(' */\n') + tfile.write(config_defines) +tfile.close() +compare_srcfile(tmp_file, '../src/include/config.h') |