1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#!/usr/bin/python
# This script generates the boilerplate versions of most fops and cbks in the
# server. This allows the details of leadership-status checking, sequencing
# between leader and followers (including fan-out), and basic error checking
# to be centralized one place, with per-operation code kept to a minimum.
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
# We really want the callback argument list, even when we're generating fop
# code, so we propagate here.
# TBD: this should probably be right in generate.py
for k, v in cbk_subs.iteritems():
fop_subs[k]['@ERROR_ARGS@'] = v['@ERROR_ARGS@']
# Stolen from old codegen.py
def load_templates (path):
templates = {}
tmpl_re = re.compile("/\* template-name (.*) \*/")
templates = {}
t_name = None
for line in open(path,"r").readlines():
if not line:
break
m = tmpl_re.match(line)
if m:
if t_name:
templates[t_name] = string.join(t_contents,'')
t_name = m.group(1).strip()
t_contents = []
elif t_name:
t_contents.append(line)
if t_name:
templates[t_name] = string.join(t_contents,'')
return templates
# We need two types of templates. The first, for pure read operations, just
# needs to do a simple am-i-leader check (augmented to allow dirty reads).
# The second, for pure writes, needs to do fan-out to followers between those
# initial checks and local execution. There are other operations that don't
# fit neatly into either category - e.g. lock ops or fsync - so we'll just have
# to handle those manually. The table thus includes entries only for those we
# can categorize. The special cases, plus any new operations we've never even
# heard of, aren't in there.
#
# Various keywords can be used to define/undefine preprocessor symbols used
# in the templates, on a per-function basis. For example, if the keyword here
# is "fsync" (lowercase word or abbreviation) that will cause JBR_CG_FSYNC
# (prefix plus uppercase version) to be defined above all of the generated code
# for that fop.
fop_table = {
"access": "read",
"create": "write",
"discard": "write",
# "entrylk": "read",
"fallocate": "write",
# "fentrylk": "read",
"fgetxattr": "read",
# "finodelk": "read",
# "flush": "read",
"fremovexattr": "write",
"fsetattr": "write",
"fsetxattr": "write",
"fstat": "read",
# "fsync": "read",
# "fsyncdir": "read",
"ftruncate": "write",
"fxattrop": "write",
"getxattr": "read",
# "inodelk": "read",
"link": "write",
# "lk": "read",
# "lookup": "read",
"mkdir": "write",
"mknod": "write",
"open": "write",
"opendir": "read",
"rchecksum": "read",
"readdir": "read",
"readdirp": "read",
"readlink": "read",
"readv": "read",
"removexattr": "write",
"rename": "write",
"rmdir": "write",
"setattr": "write",
"setxattr": "write",
"stat": "read",
"statfs": "read",
"symlink": "write",
"truncate": "write",
"unlink": "write",
"writev": "write,fsync,queue",
"xattrop": "write",
}
# Stolen from gen_fdl.py
def gen_server (templates):
fops_done = []
for name in fop_table.keys():
info = fop_table[name].split(",")
kind = info[0]
flags = info[1:]
if ("fsync" in flags) or ("queue" in flags):
flags.append("need_fd")
for fname in flags:
print "#define JBR_CG_%s" % fname.upper()
print generate(templates[kind+"-complete"],name,cbk_subs)
print generate(templates[kind+"-continue"],name,fop_subs)
print generate(templates[kind+"-fan-in"],name,cbk_subs)
print generate(templates[kind+"-dispatch"],name,fop_subs)
print generate(templates[kind+"-fop"],name,fop_subs)
for fname in flags:
print "#undef JBR_CG_%s" % fname.upper()
fops_done.append(name)
# Just for fun, emit the fops table too.
print("struct xlator_fops fops = {")
for x in fops_done:
print(" .%s = jbr_%s,"%(x,x))
print("};")
tmpl = load_templates(sys.argv[1])
for l in open(sys.argv[2],'r').readlines():
if l.find('#pragma generate') != -1:
print "/* BEGIN GENERATED CODE - DO NOT MODIFY */"
gen_server(tmpl)
print "/* END GENERATED CODE */"
else:
print l[:-1]
|