summaryrefslogtreecommitdiffstats
path: root/xlators/experimental/fdl/src/gen_recon.py
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/experimental/fdl/src/gen_recon.py')
-rwxr-xr-xxlators/experimental/fdl/src/gen_recon.py213
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 67f9ea9..0000000
--- 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 */"