diff options
Diffstat (limited to 'xlators/experimental/fdl/src/gen_recon.py')
-rwxr-xr-x | xlators/experimental/fdl/src/gen_recon.py | 213 |
1 files changed, 0 insertions, 213 deletions
diff --git a/xlators/experimental/fdl/src/gen_recon.py b/xlators/experimental/fdl/src/gen_recon.py deleted file mode 100755 index 67f9ea9ebd3..00000000000 --- a/xlators/experimental/fdl/src/gen_recon.py +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/python - -import os -import re -import string -import sys - -curdir = os.path.dirname (sys.argv[0]) -gendir = os.path.join (curdir, '../../../../libglusterfs/src') -sys.path.append (gendir) -from generator import ops, fop_subs, cbk_subs, generate - -# See the big header comment at the start of gen_fdl.py to see how the stages -# fit together. The big difference here is that *all* of the C code is in the -# template file as labelled fragments, instead of as Python strings. That -# makes it much easier to edit in one place, with proper syntax highlighting -# and indentation. -# -# Stage 1 uses type-specific fragments to generate FUNCTION_BODY, instead of -# LEN_*_TEMPLATE and SERLZ_*_TEMPLATE to generate LEN_CODE and SER_CODE. -# -# Stage 2 uses the FOP and CASE fragments instead of RECON_TEMPLATE and -# FOP_TEMPLATE. The expanded FOP code (including FUNCTION_BODY substitution -# in the middle of each function) is emitted immediately; the expanded CASE -# code is saved for the next stage. -# -# Stage 3 uses the PROLOG and EPILOG fragments, with the expanded CASE code -# in the middle of EPILOG, to generate the whole output file. -# -# Another way of looking at it is to consider how the fragments appear in -# the final output: -# -# PROLOG -# FOP (expanded for CREATE) -# FOP before FUNCTION_BODY -# LOC, INTEGER, GFID, etc. (one per arg, by type) -# FOP after FUNCTION_BODY -# FOP (expanded for WRITEV) -# FOP before FUNCTION_BODY -# GFID, VECTOR, etc. (one per arg, by type) -# FOP after FUNCTION_BODY -# (more FOPs) -# EPILOG -# EPILOG before CASE -# CASE statements (one per fop) -# EPILOG after CASE - -typemap = { - 'dict_t *': "DICT", - 'fd_t *': "FD", - 'dev_t': "DOUBLE", - 'gf_xattrop_flags_t': "INTEGER", - 'int32_t': "INTEGER", - 'mode_t': "INTEGER", - 'off_t': "DOUBLE", - 'size_t': "DOUBLE", - 'uint32_t': "INTEGER", - 'loc_t *': "LOC", - 'const char *': "STRING", - 'struct iovec *': "VECTOR", - 'struct iatt *': "IATT", - 'struct iobref *': "IOBREF", -} - -def get_special_subs (name, args, fop_type): - code = "" - cleanups = "" - links = "" - s_args = [] - for arg in args: - if arg[0] == 'extra': - code += "\t%s %s;\n\n" % (arg[2], arg[1]) - s_args.append(arg[3]) - continue - if arg[0] == 'link': - links += fragments["LINK"].replace("@INODE_ARG@",arg[1]) \ - .replace("@IATT_ARG@",arg[2]) - continue - if arg[0] != 'fop-arg': - continue - if (name, arg[1]) == ('writev', 'count'): - # Special case: just skip this. We can't mark it as 'nosync' - # because of the way the translator and dumper generators look for - # that after 'stub-name' which we don't define. Instead of adding a - # bunch of generic infrastructure for this one case, just pound it - # here. - continue - recon_type = typemap[arg[2]] - # print "/* %s.%s => %s (%s)*/" % (name, arg[1], recon_type, fop_type) - if (name == "create") and (arg[1] == "fd"): - # Special case: fd for create is new, not looked up. - # print "/* change to NEW_FD */" - recon_type = "NEW_FD" - elif (recon_type == "LOC") and (fop_type == "entry-op"): - # Need to treat this differently for inode vs. entry ops. - # Special case: link source is treated like inode-op. - if (name != "link") or (arg[1] != "oldloc"): - # print "/* change to PARENT_LOC */" - recon_type = "PARENT_LOC" - code += fragments[recon_type].replace("@ARGNAME@",arg[1]) \ - .replace("@ARGTYPE@",arg[2]) - cleanup_key = recon_type + "_CLEANUP" - if fragments.has_key(cleanup_key): - new_frag = fragments[cleanup_key].replace("@ARGNAME@",arg[1]) - # Make sure these get added in *reverse* order. Otherwise, a - # failure for an earlier argument might goto a label that falls - # through to the cleanup code for a variable associated with a - # later argument, but that variable might not even have been - # *declared* (let alone initialized) yet. Consider the following - # case. - # - # process argument A (on failure goto cleanup_A) - # set error label to cleanup_A - # - # declare pointer variable for argument B - # process argument B (on failure goto cleanup_B) - # - # cleanup_A: - # /* whatever */ - # cleanup_B: - # free pointer variable <= "USED BUT NOT SET" error here - # - # By adding these in reverse order, we ensure that cleanup_B is - # actually *before* cleanup_A, and nothing will try to do the free - # until we've actually attempted processing of B. - cleanups = new_frag + cleanups - if 'nosync' in arg[4:]: - code += "\t(void)%s;\n" % arg[1]; - continue - if arg[2] in ("loc_t *", "struct iatt *"): - # These are passed as pointers to the syncop, but they're actual - # structures in the generated code. - s_args.append("&"+arg[1]); - else: - s_args.append(arg[1]) - # We have to handle a couple of special cases here, because some n00b - # defined the syncops with a different argument order than the fops they're - # based on. - if name == 'writev': - # Swap 'flags' and 'iobref'. Also, we need to add the iov count, which - # is not stored in or read from the journal. There are other ways to - # do that, but this is the only place we need anything similar and we - # already have to treat it as a special case so this is simplest. - s_args_str = 'fd, &vector, 1, off, iobref, flags, xdata' - elif name == 'symlink': - # Swap 'linkpath' and 'loc'. - s_args_str = '&loc, linkpath, &iatt, xdata' - else: - s_args_str = string.join (s_args, ", ") - return code, links, s_args_str, cleanups - -# TBD: probably need to generate type-specific cleanup code as well - e.g. -# fd_unref for an fd_t, loc_wipe for a loc_t, and so on. All of these -# generated CLEANUP fragments will go at the end of the function, with goto -# labels. Meanwhile, the error-checking part of each type-specific fragment -# (e.g. LOC or FD) will need to update the indirect label that we jump to when -# an error is detected. This will probably get messy. -def gen_functions (): - code = "" - for name, value in ops.iteritems(): - fop_type = [ x[1] for x in value if x[0] == "journal" ] - if not fop_type: - continue - body, links, syncop_args, cleanups = get_special_subs (name, value, - fop_type[0]) - fop_subs[name]["@FUNCTION_BODY@"] = body - fop_subs[name]["@LINKS@"] = links - fop_subs[name]["@SYNCOP_ARGS@"] = syncop_args - fop_subs[name]["@CLEANUPS@"] = cleanups - if name == "writev": - # Take advantage of the fact that, *during reconciliation*, the - # vector is always a single element. In normal I/O it's not. - fop_subs[name]["@SUCCESS_VALUE@"] = "vector.iov_len" - else: - fop_subs[name]["@SUCCESS_VALUE@"] = "GFAPI_SUCCESS" - # Print the FOP fragment with @FUNCTION_BODY@ in the middle. - code += generate(fragments["FOP"],name,fop_subs) - return code - -def gen_cases (): - code = "" - for name, value in ops.iteritems(): - if "journal" not in [ x[0] for x in value ]: - continue - # Add the CASE fragment for this fop. - code += generate(fragments["CASE"],name,fop_subs) - return code - -def load_fragments (path="recon-tmpl.c"): - pragma_re = re.compile('pragma fragment (.*)') - cur_symbol = None - cur_value = "" - result = {} - for line in open(path,"r").readlines(): - m = pragma_re.search(line) - if m: - if cur_symbol: - result[cur_symbol] = cur_value - cur_symbol = m.group(1) - cur_value = "" - else: - cur_value += line - if cur_symbol: - result[cur_symbol] = cur_value - return result - -if __name__ == "__main__": - fragments = load_fragments(sys.argv[1]) - print "/* BEGIN GENERATED CODE - DO NOT MODIFY */" - print fragments["PROLOG"] - print gen_functions() - print fragments["EPILOG"].replace("@SWITCH_BODY@",gen_cases()) - print "/* END GENERATED CODE */" |