]>
Commit | Line | Data |
---|---|---|
d879a707 BP |
1 | #! @PYTHON@ |
2 | ||
d34a1cc0 | 3 | from __future__ import print_function |
d879a707 | 4 | import getopt |
00732bf5 | 5 | import os |
d879a707 | 6 | import re |
d879a707 BP |
7 | import sys |
8 | ||
99155935 BP |
9 | import ovs.json |
10 | import ovs.db.error | |
11 | import ovs.db.schema | |
0a8606ee | 12 | from ovs.db.types import StringType, IntegerType, RealType |
d879a707 | 13 | |
89365653 | 14 | argv0 = sys.argv[0] |
45a7de56 | 15 | |
d879a707 | 16 | def parseSchema(filename): |
99155935 | 17 | return ovs.db.schema.IdlSchema.from_json(ovs.json.from_file(filename)) |
00732bf5 BP |
18 | |
19 | def annotateSchema(schemaFile, annotationFile): | |
99155935 | 20 | schemaJson = ovs.json.from_file(schemaFile) |
a4d10a7c | 21 | exec(compile(open(annotationFile, "rb").read(), annotationFile, 'exec'), globals(), {"s": schemaJson}) |
99155935 | 22 | ovs.json.to_stream(schemaJson, sys.stdout) |
292aefc4 | 23 | sys.stdout.write('\n') |
d879a707 | 24 | |
02630ff2 | 25 | def constify(cType, const): |
47058293 RB |
26 | if (const |
27 | and cType.endswith('*') and | |
28 | (cType == 'char **' or not cType.endswith('**'))): | |
02630ff2 BP |
29 | return 'const %s' % cType |
30 | else: | |
31 | return cType | |
32 | ||
4bb7f568 | 33 | def cMembers(prefix, tableName, columnName, column, const, refTable=True): |
7cc398cb | 34 | comment = "" |
475281c0 | 35 | type = column.type |
a699f614 EJ |
36 | |
37 | if type.is_smap(): | |
7cc398cb JP |
38 | comment = """ |
39 | /* Sets the "%(c)s" column's value from the "%(t)s" table in 'row' | |
40 | * to '%(c)s'. | |
41 | * | |
42 | * The caller retains ownership of '%(c)s' and everything in it. */""" \ | |
43 | % {'c': columnName, | |
44 | 't': tableName} | |
45 | return (comment, [{'name': columnName, | |
46 | 'type': 'struct smap ', | |
47 | 'comment': ''}]) | |
48 | ||
49 | comment = """\n/* Sets the "%s" column from the "%s" table in """\ | |
50 | """'row' to\n""" % (columnName, tableName) | |
a699f614 | 51 | |
99155935 | 52 | if type.n_min == 1 and type.n_max == 1: |
475281c0 BP |
53 | singleton = True |
54 | pointer = '' | |
55 | else: | |
56 | singleton = False | |
99155935 | 57 | if type.is_optional_pointer(): |
475281c0 BP |
58 | pointer = '' |
59 | else: | |
60 | pointer = '*' | |
61 | ||
7cc398cb | 62 | |
475281c0 | 63 | if type.value: |
7cc398cb JP |
64 | keyName = "key_%s" % columnName |
65 | valueName = "value_%s" % columnName | |
66 | ||
67 | key = {'name': keyName, | |
4bb7f568 | 68 | 'type': constify(type.key.toCType(prefix, refTable) + pointer, const), |
475281c0 | 69 | 'comment': ''} |
7cc398cb | 70 | value = {'name': valueName, |
4bb7f568 | 71 | 'type': constify(type.value.toCType(prefix, refTable) + pointer, const), |
475281c0 | 72 | 'comment': ''} |
7cc398cb JP |
73 | |
74 | if singleton: | |
75 | comment += " * the map with key '%s' and value '%s'\n *" \ | |
76 | % (keyName, valueName) | |
77 | else: | |
78 | comment += " * the map with keys '%s' and values '%s'\n *" \ | |
79 | % (keyName, valueName) | |
475281c0 BP |
80 | members = [key, value] |
81 | else: | |
82 | m = {'name': columnName, | |
4bb7f568 | 83 | 'type': constify(type.key.toCType(prefix, refTable) + pointer, const), |
bd76d25d | 84 | 'comment': type.cDeclComment()} |
7cc398cb JP |
85 | |
86 | if singleton: | |
87 | comment += " * '%s'" % columnName | |
88 | else: | |
89 | comment += " * the '%s' set" % columnName | |
475281c0 BP |
90 | members = [m] |
91 | ||
99155935 | 92 | if not singleton and not type.is_optional_pointer(): |
7cc398cb JP |
93 | sizeName = "n_%s" % columnName |
94 | ||
95 | comment += " with '%s' entries" % sizeName | |
96 | members.append({'name': sizeName, | |
475281c0 BP |
97 | 'type': 'size_t ', |
98 | 'comment': ''}) | |
7cc398cb JP |
99 | |
100 | comment += ".\n" | |
101 | ||
102 | if type.is_optional() and not type.is_optional_pointer(): | |
103 | comment += """ * | |
104 | * '%s' may be 0 or 1; if it is 0, then '%s' | |
105 | * may be NULL.\n""" \ | |
106 | % ("n_%s" % columnName, columnName) | |
107 | ||
108 | if type.is_optional_pointer(): | |
109 | comment += """ * | |
110 | * If "%s" is null, the column will be the empty set, | |
111 | * otherwise it will contain the specified value.\n""" % columnName | |
112 | ||
113 | if type.constraintsToEnglish(): | |
114 | comment += """ * | |
115 | * Argument constraints: %s\n""" \ | |
116 | % type.constraintsToEnglish(lambda s : '"%s"' % s) | |
117 | ||
118 | comment += " *\n * The caller retains ownership of the arguments. */" | |
119 | ||
120 | return (comment, members) | |
475281c0 | 121 | |
01928c96 BP |
122 | # This is equivalent to sorted(table.columns.items()), except that the |
123 | # sorting includes a topological component: if column B has a | |
124 | # dependency on column A, then A will be sorted before B. | |
e0b1744f | 125 | def sorted_columns(table): |
01928c96 BP |
126 | input = [] |
127 | for name, column in table.columns.items(): | |
128 | dependencies = column.extensions.get('dependencies', []) | |
129 | for d in dependencies: | |
130 | if d not in table.columns: | |
131 | sys.stderr.write("Table %s column %s depends on column %s " | |
132 | "but there is no such column\n" | |
133 | % (table.name, name, d)) | |
134 | sys.exit(1) | |
135 | input += [(name, column, set(dependencies))] | |
136 | ||
137 | output = [] | |
138 | satisfied_dependencies = set() | |
139 | while input: | |
140 | done = [] | |
141 | next = [] | |
142 | for name, column, dependencies in input: | |
143 | if dependencies <= satisfied_dependencies: | |
144 | done += [(name, column)] | |
145 | else: | |
146 | next += [(name, column, dependencies)] | |
147 | ||
148 | if not done: | |
149 | sys.stderr.write("Table %s columns have circular dependencies\n" | |
150 | % table.name) | |
151 | sys.exit(1) | |
152 | ||
153 | for name, column in done: | |
154 | satisfied_dependencies.add(name) | |
155 | output += sorted(done) | |
156 | input = next | |
157 | return output | |
e0b1744f | 158 | |
adb4185d YHW |
159 | # If a column name in the schema is a C or C++ keyword, append an underscore |
160 | # to the column name. | |
161 | def replace_cplusplus_keyword(schema): | |
162 | keywords = {'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', | |
163 | 'bitor', 'bool', 'break', 'case', 'catch', 'char', 'char16_t', | |
164 | 'char32_t', 'class', 'compl', 'concept', 'const', 'const_cast', | |
165 | 'constexpr', 'continue', 'decltype', 'default', 'delete', 'do', | |
166 | 'double', 'dynamic_cast', 'else', 'enum', 'explicit', 'export', | |
167 | 'extern', 'false', 'float', 'for', 'friend', 'goto', 'if', | |
168 | 'inline', 'int', 'long', 'mutable', 'namespace', 'new', | |
169 | 'noexcept', 'not', 'not_eq', 'nullptr', 'operator', 'or', | |
170 | 'or_eq', 'private', 'protected', 'public', 'register', | |
171 | 'reinterpret_cast', 'requires', 'restrict', 'return', 'short', | |
172 | 'signed', 'sizeof', 'static', 'static_assert', 'static_cast', | |
173 | 'struct', 'switch', 'template', 'this', 'thread_local', | |
174 | 'throw', 'true', 'try', 'typedef', 'typeid', 'typename', | |
175 | 'union', 'unsigned', 'using', 'virtual', 'void', 'volatile', | |
176 | 'wchar_t', 'while', 'xor', 'xor_eq'} | |
177 | ||
178 | for tableName, table in schema.tables.items(): | |
179 | for columnName in table.columns: | |
180 | if columnName in keywords: | |
181 | table.columns[columnName + '_'] = table.columns.pop(columnName) | |
182 | ||
00732bf5 BP |
183 | def printCIDLHeader(schemaFile): |
184 | schema = parseSchema(schemaFile) | |
adb4185d | 185 | replace_cplusplus_keyword(schema) |
c3bb4bd7 | 186 | prefix = schema.idlPrefix |
d34a1cc0 | 187 | print('''\ |
d879a707 BP |
188 | /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */ |
189 | ||
190 | #ifndef %(prefix)sIDL_HEADER | |
191 | #define %(prefix)sIDL_HEADER 1 | |
192 | ||
193 | #include <stdbool.h> | |
194 | #include <stddef.h> | |
195 | #include <stdint.h> | |
a6ec9089 | 196 | #include "ovsdb-data.h" |
c3bb4bd7 | 197 | #include "ovsdb-idl-provider.h" |
a699f614 | 198 | #include "smap.h" |
9131abe2 YHW |
199 | #include "uuid.h" |
200 | ||
201 | #ifdef __cplusplus | |
202 | extern "C" { | |
203 | #endif | |
0ea866bb BP |
204 | %(hDecls)s''' % {'prefix': prefix.upper(), |
205 | 'hDecls': schema.hDecls}) | |
979821c0 | 206 | |
4ab66562 | 207 | for tableName, table in sorted(schema.tables.items()): |
c3bb4bd7 | 208 | structName = "%s%s" % (prefix, tableName.lower()) |
979821c0 | 209 | |
d34a1cc0 JW |
210 | print("\f") |
211 | print("/* %s table. */" % tableName) | |
212 | print("struct %s {" % structName) | |
213 | print("\tstruct ovsdb_idl_row header_;") | |
e0b1744f | 214 | for columnName, column in sorted_columns(table): |
d34a1cc0 | 215 | print("\n\t/* %s column. */" % columnName) |
01928c96 BP |
216 | if column.extensions.get("members"): |
217 | print("\t%s" % column.extensions["members"]) | |
218 | continue | |
7cc398cb JP |
219 | comment, members = cMembers(prefix, tableName, |
220 | columnName, column, False) | |
221 | for member in members: | |
d34a1cc0 JW |
222 | print("\t%(type)s%(name)s;%(comment)s" % member) |
223 | print("};") | |
c3bb4bd7 | 224 | |
979821c0 | 225 | # Column indexes. |
32d37ce8 | 226 | printEnum("%s_column_id" % structName.lower(), ["%s_COL_%s" % (structName.upper(), columnName.upper()) |
e0b1744f | 227 | for columnName, column in sorted_columns(table)] |
979821c0 BP |
228 | + ["%s_N_COLUMNS" % structName.upper()]) |
229 | ||
d34a1cc0 | 230 | print("") |
979821c0 | 231 | for columnName in table.columns: |
d34a1cc0 | 232 | print("#define %(s)s_col_%(c)s (%(s)s_columns[%(S)s_COL_%(C)s])" % { |
979821c0 BP |
233 | 's': structName, |
234 | 'S': structName.upper(), | |
235 | 'c': columnName, | |
d34a1cc0 | 236 | 'C': columnName.upper()}) |
979821c0 | 237 | |
d34a1cc0 | 238 | print("\nextern struct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (structName, structName.upper())) |
979821c0 | 239 | |
d34a1cc0 | 240 | print(''' |
8c6cf7b8 | 241 | const struct %(s)s *%(s)s_get_for_uuid(const struct ovsdb_idl *, const struct uuid *); |
c3bb4bd7 BP |
242 | const struct %(s)s *%(s)s_first(const struct ovsdb_idl *); |
243 | const struct %(s)s *%(s)s_next(const struct %(s)s *); | |
58bc1a52 BP |
244 | #define %(S)s_FOR_EACH(ROW, IDL) \\ |
245 | for ((ROW) = %(s)s_first(IDL); \\ | |
246 | (ROW); \\ | |
247 | (ROW) = %(s)s_next(ROW)) | |
248 | #define %(S)s_FOR_EACH_SAFE(ROW, NEXT, IDL) \\ | |
249 | for ((ROW) = %(s)s_first(IDL); \\ | |
250 | (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\ | |
251 | (ROW) = (NEXT)) | |
475281c0 | 252 | |
932104f4 SA |
253 | unsigned int %(s)s_get_seqno(const struct ovsdb_idl *); |
254 | unsigned int %(s)s_row_get_seqno(const struct %(s)s *row, enum ovsdb_idl_change change); | |
255 | const struct %(s)s *%(s)s_track_get_first(const struct ovsdb_idl *); | |
256 | const struct %(s)s *%(s)s_track_get_next(const struct %(s)s *); | |
257 | #define %(S)s_FOR_EACH_TRACKED(ROW, IDL) \\ | |
258 | for ((ROW) = %(s)s_track_get_first(IDL); \\ | |
259 | (ROW); \\ | |
260 | (ROW) = %(s)s_track_get_next(ROW)) | |
261 | ||
9a33cd70 BP |
262 | /* Returns true if 'row' was inserted since the last change tracking reset. */ |
263 | static inline bool %(s)s_is_new(const struct %(s)s *row) | |
264 | { | |
265 | return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_MODIFY) == 0; | |
266 | } | |
267 | ||
268 | /* Returns true if 'row' was deleted since the last change tracking reset. */ | |
269 | static inline bool %(s)s_is_deleted(const struct %(s)s *row) | |
270 | { | |
271 | return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_DELETE) > 0; | |
272 | } | |
273 | ||
0a8606ee LR |
274 | void %(s)s_index_destroy_row(const struct %(s)s *); |
275 | int %(s)s_index_compare(struct ovsdb_idl_index_cursor *, const struct %(s)s *, const struct %(s)s *); | |
276 | const struct %(s)s *%(s)s_index_first(struct ovsdb_idl_index_cursor *); | |
277 | const struct %(s)s *%(s)s_index_next(struct ovsdb_idl_index_cursor *); | |
278 | const struct %(s)s *%(s)s_index_find(struct ovsdb_idl_index_cursor *, const struct %(s)s *); | |
279 | const struct %(s)s *%(s)s_index_forward_to(struct ovsdb_idl_index_cursor *, const struct %(s)s *); | |
280 | const struct %(s)s *%(s)s_index_get_data(const struct ovsdb_idl_index_cursor *); | |
281 | #define %(S)s_FOR_EACH_RANGE(ROW, CURSOR, FROM, TO) \\ | |
282 | for ((ROW) = %(s)s_index_forward_to(CURSOR, FROM); \\ | |
283 | ((ROW) && %(s)s_index_compare(CURSOR, ROW, TO) <= 0); \\ | |
284 | (ROW) = %(s)s_index_next(CURSOR)) | |
285 | #define %(S)s_FOR_EACH_EQUAL(ROW, CURSOR, KEY) \\ | |
286 | for ((ROW) = %(s)s_index_find(CURSOR, KEY); \\ | |
287 | ((ROW) && %(s)s_index_compare(CURSOR, ROW, KEY) == 0); \\ | |
288 | (ROW) = %(s)s_index_next(CURSOR)) | |
289 | #define %(S)s_FOR_EACH_BYINDEX(ROW, CURSOR) \\ | |
290 | for ((ROW) = %(s)s_index_first(CURSOR); \\ | |
291 | (ROW); \\ | |
292 | (ROW) = %(s)s_index_next(CURSOR)) | |
293 | ||
a699f614 | 294 | void %(s)s_init(struct %(s)s *); |
475281c0 BP |
295 | void %(s)s_delete(const struct %(s)s *); |
296 | struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); | |
32d37ce8 | 297 | bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id); |
d34a1cc0 | 298 | ''' % {'s': structName, 'S': structName.upper()}) |
475281c0 | 299 | |
e0b1744f | 300 | for columnName, column in sorted_columns(table): |
01928c96 BP |
301 | if column.extensions.get('synthetic'): |
302 | continue | |
d34a1cc0 | 303 | print('void %(s)s_verify_%(c)s(const struct %(s)s *);' % {'s': structName, 'c': columnName}) |
475281c0 | 304 | |
d34a1cc0 | 305 | print("") |
e0b1744f | 306 | for columnName, column in sorted_columns(table): |
01928c96 BP |
307 | if column.extensions.get('synthetic'): |
308 | continue | |
a6ec9089 BP |
309 | if column.type.value: |
310 | valueParam = ', enum ovsdb_atomic_type value_type' | |
311 | else: | |
312 | valueParam = '' | |
d34a1cc0 JW |
313 | print('const struct ovsdb_datum *%(s)s_get_%(c)s(const struct %(s)s *, enum ovsdb_atomic_type key_type%(v)s);' % { |
314 | 's': structName, 'c': columnName, 'v': valueParam}) | |
a6ec9089 | 315 | |
d34a1cc0 | 316 | print("") |
e0b1744f | 317 | for columnName, column in sorted_columns(table): |
01928c96 BP |
318 | if column.extensions.get('synthetic'): |
319 | continue | |
d34a1cc0 | 320 | print('void %(s)s_set_%(c)s(const struct %(s)s *,' % {'s': structName, 'c': columnName}, end=' ') |
a699f614 EJ |
321 | if column.type.is_smap(): |
322 | args = ['const struct smap *'] | |
323 | else: | |
7cc398cb JP |
324 | comment, members = cMembers(prefix, tableName, columnName, |
325 | column, True) | |
326 | args = ['%(type)s%(name)s' % member for member in members] | |
d34a1cc0 | 327 | print('%s);' % ', '.join(args)) |
475281c0 | 328 | |
d34a1cc0 | 329 | print("") |
e0b1744f | 330 | for columnName, column in sorted_columns(table): |
01928c96 BP |
331 | if column.extensions.get('synthetic'): |
332 | continue | |
16ebb90e | 333 | if column.type.is_map(): |
d34a1cc0 JW |
334 | print('void %(s)s_update_%(c)s_setkey(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') |
335 | print('%(coltype)s, %(valtype)s);' % {'coltype':column.type.key.to_const_c_type(prefix), 'valtype':column.type.value.to_const_c_type(prefix)}) | |
336 | print('void %(s)s_update_%(c)s_delkey(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') | |
337 | print('%(coltype)s);' % {'coltype':column.type.key.to_const_c_type(prefix)}) | |
f1ab6e06 | 338 | if column.type.is_set(): |
d34a1cc0 JW |
339 | print('void %(s)s_update_%(c)s_addvalue(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') |
340 | print('%(valtype)s);' % {'valtype':column.type.key.to_const_c_type(prefix)}) | |
341 | print('void %(s)s_update_%(c)s_delvalue(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') | |
342 | print('%(valtype)s);' % {'valtype':column.type.key.to_const_c_type(prefix)}) | |
16ebb90e | 343 | |
d34a1cc0 | 344 | print('void %(s)s_add_clause_%(c)s(struct ovsdb_idl_condition *, enum ovsdb_function function,' % {'s': structName, 'c': columnName}, end=' ') |
16ebb90e LS |
345 | if column.type.is_smap(): |
346 | args = ['const struct smap *'] | |
347 | else: | |
348 | comment, members = cMembers(prefix, tableName, columnName, | |
4bb7f568 | 349 | column, True, refTable=False) |
16ebb90e | 350 | args = ['%(type)s%(name)s' % member for member in members] |
d34a1cc0 | 351 | print('%s);' % ', '.join(args)) |
16ebb90e | 352 | |
d34a1cc0 | 353 | print('void %(s)s_set_condition(struct ovsdb_idl *, struct ovsdb_idl_condition *);' % {'s': structName}) |
16ebb90e | 354 | |
d34a1cc0 | 355 | print("") |
f67f1354 | 356 | |
979821c0 | 357 | # Table indexes. |
0a8606ee LR |
358 | print("struct %(s)s * %(s)s_index_init_row(struct ovsdb_idl *, const struct ovsdb_idl_table_class *);" % {'s': structName}) |
359 | ||
81068700 | 360 | for columnName, column in sorted(table.columns.items()): |
0a8606ee LR |
361 | print('void %(s)s_index_set_%(c)s(const struct %(s)s *,' % {'s': structName, 'c': columnName}) |
362 | if column.type.is_smap(): | |
363 | args = ['const struct smap *'] | |
364 | else: | |
365 | comment, members = cMembers(prefix, tableName, columnName, | |
366 | column, True) | |
367 | args = ['%(type)s%(name)s' % member for member in members] | |
368 | print('%s);' % ', '.join(args)) | |
369 | ||
370 | ||
32d37ce8 | 371 | printEnum("%stable_id" % prefix.lower(), ["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()]) |
d34a1cc0 | 372 | print("") |
979821c0 | 373 | for tableName in schema.tables: |
d34a1cc0 | 374 | print("#define %(p)stable_%(t)s (%(p)stable_classes[%(P)sTABLE_%(T)s])" % { |
979821c0 BP |
375 | 'p': prefix, |
376 | 'P': prefix.upper(), | |
377 | 't': tableName.lower(), | |
d34a1cc0 JW |
378 | 'T': tableName.upper()}) |
379 | print("\nextern struct ovsdb_idl_table_class %stable_classes[%sN_TABLES];" % (prefix, prefix.upper())) | |
979821c0 | 380 | |
d34a1cc0 | 381 | print("\nextern struct ovsdb_idl_class %sidl_class;" % prefix) |
87412f02 | 382 | |
d34a1cc0 | 383 | print("\nconst char * %sget_db_version(void);" % prefix) |
9131abe2 YHW |
384 | print(''' |
385 | #ifdef __cplusplus | |
386 | } | |
387 | #endif''') | |
d34a1cc0 | 388 | print("\n#endif /* %(prefix)sIDL_HEADER */" % {'prefix': prefix.upper()}) |
c3bb4bd7 | 389 | |
32d37ce8 | 390 | def printEnum(type, members): |
c3bb4bd7 BP |
391 | if len(members) == 0: |
392 | return | |
393 | ||
d34a1cc0 | 394 | print("\nenum %s {" % type) |
c3bb4bd7 | 395 | for member in members[:-1]: |
d34a1cc0 JW |
396 | print(" %s," % member) |
397 | print(" %s" % members[-1]) | |
398 | print("};") | |
c3bb4bd7 | 399 | |
00732bf5 BP |
400 | def printCIDLSource(schemaFile): |
401 | schema = parseSchema(schemaFile) | |
adb4185d | 402 | replace_cplusplus_keyword(schema) |
c3bb4bd7 | 403 | prefix = schema.idlPrefix |
d34a1cc0 | 404 | print('''\ |
c3bb4bd7 BP |
405 | /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */ |
406 | ||
407 | #include <config.h> | |
0ea866bb | 408 | #include %(header)s |
c3bb4bd7 | 409 | #include <limits.h> |
558103f0 | 410 | #include "ovs-thread.h" |
bd76d25d BP |
411 | #include "ovsdb-data.h" |
412 | #include "ovsdb-error.h" | |
cb22974d | 413 | #include "util.h" |
bd76d25d | 414 | |
0ea866bb BP |
415 | %(cDecls)s |
416 | ||
417 | ''' % {'header': schema.idlHeader, | |
418 | 'cDecls': schema.cDecls}) | |
c3bb4bd7 | 419 | |
66095e15 | 420 | # Cast functions. |
4ab66562 | 421 | for tableName, table in sorted(schema.tables.items()): |
66095e15 | 422 | structName = "%s%s" % (prefix, tableName.lower()) |
d34a1cc0 | 423 | print(''' |
66095e15 | 424 | static struct %(s)s * |
979821c0 | 425 | %(s)s_cast(const struct ovsdb_idl_row *row) |
66095e15 BP |
426 | { |
427 | return row ? CONTAINER_OF(row, struct %(s)s, header_) : NULL; | |
428 | }\ | |
d34a1cc0 | 429 | ''' % {'s': structName}) |
66095e15 BP |
430 | |
431 | ||
4ab66562 | 432 | for tableName, table in sorted(schema.tables.items()): |
c3bb4bd7 | 433 | structName = "%s%s" % (prefix, tableName.lower()) |
d34a1cc0 JW |
434 | print("\f") |
435 | print("/* %s table. */" % (tableName)) | |
c3bb4bd7 | 436 | |
979821c0 | 437 | # Parse functions. |
e0b1744f | 438 | for columnName, column in sorted_columns(table): |
01928c96 BP |
439 | if 'parse' in column.extensions: |
440 | print(''' | |
441 | static void | |
442 | %(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum OVS_UNUSED) | |
443 | { | |
444 | struct %(s)s *row = %(s)s_cast(row_);\ | |
445 | ''' % {'s': structName, 'c': columnName}) | |
446 | print(column.extensions["parse"]) | |
447 | print("}") | |
448 | continue | |
449 | if column.extensions.get('synthetic'): | |
450 | # Synthetic columns aren't parsed from a datum. | |
451 | unused = " OVS_UNUSED" | |
452 | else: | |
453 | unused = "" | |
d34a1cc0 | 454 | print(''' |
c3bb4bd7 | 455 | static void |
979821c0 | 456 | %(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum) |
c3bb4bd7 | 457 | { |
979821c0 | 458 | struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName, |
d34a1cc0 | 459 | 'c': columnName}) |
c3bb4bd7 | 460 | type = column.type |
01928c96 BP |
461 | if 'parse' in column.extensions: |
462 | print(column.extensions["parse"]) | |
463 | print("}") | |
464 | continue | |
c3bb4bd7 BP |
465 | if type.value: |
466 | keyVar = "row->key_%s" % columnName | |
467 | valueVar = "row->value_%s" % columnName | |
468 | else: | |
469 | keyVar = "row->%s" % columnName | |
470 | valueVar = None | |
471 | ||
a699f614 | 472 | if type.is_smap(): |
d34a1cc0 JW |
473 | print(" smap_init(&row->%s);" % columnName) |
474 | print(" for (size_t i = 0; i < datum->n; i++) {") | |
475 | print(" smap_add(&row->%s," % columnName) | |
476 | print(" datum->keys[i].string,") | |
477 | print(" datum->values[i].string);") | |
478 | print(" }") | |
a699f614 | 479 | elif (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer(): |
d34a1cc0 JW |
480 | print("") |
481 | print(" if (datum->n >= 1) {") | |
99155935 | 482 | if not type.key.ref_table: |
d34a1cc0 | 483 | print(" %s = datum->keys[0].%s;" % (keyVar, type.key.type.to_string())) |
c3bb4bd7 | 484 | else: |
d34a1cc0 | 485 | print(" %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->keys[0].uuid));" % (keyVar, prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower())) |
c3bb4bd7 BP |
486 | |
487 | if valueVar: | |
ae661470 | 488 | if not type.value.ref_table: |
d34a1cc0 | 489 | print(" %s = datum->values[0].%s;" % (valueVar, type.value.type.to_string())) |
c3bb4bd7 | 490 | else: |
d34a1cc0 JW |
491 | print(" %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[0].uuid));" % (valueVar, prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower())) |
492 | print(" } else {") | |
493 | print(" %s" % type.key.initCDefault(keyVar, type.n_min == 0)) | |
979821c0 | 494 | if valueVar: |
d34a1cc0 JW |
495 | print(" %s" % type.value.initCDefault(valueVar, type.n_min == 0)) |
496 | print(" }") | |
c3bb4bd7 | 497 | else: |
fa145f1a | 498 | if type.n_max != sys.maxsize: |
d34a1cc0 | 499 | print(" size_t n = MIN(%d, datum->n);" % type.n_max) |
979821c0 | 500 | nMax = "n" |
c3bb4bd7 BP |
501 | else: |
502 | nMax = "datum->n" | |
d34a1cc0 | 503 | print(" %s = NULL;" % keyVar) |
979821c0 | 504 | if valueVar: |
d34a1cc0 JW |
505 | print(" %s = NULL;" % valueVar) |
506 | print(" row->n_%s = 0;" % columnName) | |
507 | print(" for (size_t i = 0; i < %s; i++) {" % nMax) | |
99155935 | 508 | if type.key.ref_table: |
d34a1cc0 | 509 | print("""\ |
9478f52f | 510 | struct %s%s *keyRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->keys[i].uuid)); |
cff5afcf BP |
511 | if (!keyRow) { |
512 | continue; | |
513 | }\ | |
d34a1cc0 | 514 | """ % (prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower())) |
c3bb4bd7 | 515 | keySrc = "keyRow" |
c3bb4bd7 | 516 | else: |
99155935 BP |
517 | keySrc = "datum->keys[i].%s" % type.key.type.to_string() |
518 | if type.value and type.value.ref_table: | |
d34a1cc0 | 519 | print("""\ |
9478f52f | 520 | struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[i].uuid)); |
cff5afcf BP |
521 | if (!valueRow) { |
522 | continue; | |
523 | }\ | |
d34a1cc0 | 524 | """ % (prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower())) |
c3bb4bd7 | 525 | valueSrc = "valueRow" |
c3bb4bd7 | 526 | elif valueVar: |
99155935 | 527 | valueSrc = "datum->values[i].%s" % type.value.type.to_string() |
d34a1cc0 | 528 | print(" if (!row->n_%s) {" % (columnName)) |
1bf2c909 | 529 | |
d34a1cc0 JW |
530 | print(" %s = xmalloc(%s * sizeof *%s);" % ( |
531 | keyVar, nMax, keyVar)) | |
c3bb4bd7 | 532 | if valueVar: |
d34a1cc0 JW |
533 | print(" %s = xmalloc(%s * sizeof *%s);" % ( |
534 | valueVar, nMax, valueVar)) | |
535 | print(" }") | |
536 | print(" %s[row->n_%s] = %s;" % (keyVar, columnName, keySrc)) | |
c3bb4bd7 | 537 | if valueVar: |
d34a1cc0 JW |
538 | print(" %s[row->n_%s] = %s;" % (valueVar, columnName, valueSrc)) |
539 | print(" row->n_%s++;" % columnName) | |
540 | print(" }") | |
541 | print("}") | |
c3bb4bd7 | 542 | |
979821c0 | 543 | # Unparse functions. |
e0b1744f | 544 | for columnName, column in sorted_columns(table): |
c3bb4bd7 | 545 | type = column.type |
01928c96 | 546 | if (type.is_smap() or (type.n_min != 1 or type.n_max != 1) and not type.is_optional_pointer()) or 'unparse' in column.extensions: |
d34a1cc0 | 547 | print(''' |
c3bb4bd7 | 548 | static void |
979821c0 | 549 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row_) |
c3bb4bd7 | 550 | { |
74e98efd | 551 | struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName, |
d34a1cc0 | 552 | 'c': columnName}) |
01928c96 BP |
553 | if 'unparse' in column.extensions: |
554 | print(column.extensions["unparse"]) | |
555 | elif type.is_smap(): | |
d34a1cc0 | 556 | print(" smap_destroy(&row->%s);" % columnName) |
c3bb4bd7 | 557 | else: |
a699f614 EJ |
558 | if type.value: |
559 | keyVar = "row->key_%s" % columnName | |
560 | valueVar = "row->value_%s" % columnName | |
561 | else: | |
562 | keyVar = "row->%s" % columnName | |
563 | valueVar = None | |
d34a1cc0 | 564 | print(" free(%s);" % keyVar) |
a699f614 | 565 | if valueVar: |
d34a1cc0 JW |
566 | print(" free(%s);" % valueVar) |
567 | print('}') | |
979821c0 | 568 | else: |
d34a1cc0 | 569 | print(''' |
c3bb4bd7 | 570 | static void |
c69ee87c | 571 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row OVS_UNUSED) |
979821c0 BP |
572 | { |
573 | /* Nothing to do. */ | |
d34a1cc0 | 574 | }''' % {'s': structName, 'c': columnName}) |
c5c7c7c5 | 575 | |
a699f614 | 576 | # Generic Row Initialization function. |
d34a1cc0 | 577 | print(""" |
a699f614 EJ |
578 | static void |
579 | %(s)s_init__(struct ovsdb_idl_row *row) | |
580 | { | |
581 | %(s)s_init(%(s)s_cast(row)); | |
d34a1cc0 | 582 | }""" % {'s': structName}) |
a699f614 EJ |
583 | |
584 | # Row Initialization function. | |
d34a1cc0 | 585 | print(""" |
d797877d | 586 | /* Clears the contents of 'row' in table "%(t)s". */ |
a699f614 EJ |
587 | void |
588 | %(s)s_init(struct %(s)s *row) | |
589 | { | |
d34a1cc0 | 590 | memset(row, 0, sizeof *row); """ % {'s': structName, 't': tableName}) |
e0b1744f | 591 | for columnName, column in sorted_columns(table): |
a699f614 | 592 | if column.type.is_smap(): |
d34a1cc0 | 593 | print(" smap_init(&row->%s);" % columnName) |
5a98d741 BP |
594 | elif (column.type.n_min == 1 and |
595 | column.type.n_max == 1 and | |
596 | column.type.key.type == ovs.db.types.StringType and | |
597 | not column.type.value): | |
d34a1cc0 JW |
598 | print(" row->%s = \"\";" % columnName) |
599 | print("}") | |
a699f614 | 600 | |
c3bb4bd7 | 601 | # First, next functions. |
d34a1cc0 | 602 | print(''' |
d797877d JP |
603 | /* Searches table "%(t)s" in 'idl' for a row with UUID 'uuid'. Returns |
604 | * a pointer to the row if there is one, otherwise a null pointer. */ | |
8c6cf7b8 BP |
605 | const struct %(s)s * |
606 | %(s)s_get_for_uuid(const struct ovsdb_idl *idl, const struct uuid *uuid) | |
607 | { | |
9478f52f | 608 | return %(s)s_cast(ovsdb_idl_get_row_for_uuid(idl, &%(p)stable_%(tl)s, uuid)); |
8c6cf7b8 BP |
609 | } |
610 | ||
d797877d JP |
611 | /* Returns a row in table "%(t)s" in 'idl', or a null pointer if that |
612 | * table is empty. | |
613 | * | |
614 | * Database tables are internally maintained as hash tables, so adding or | |
615 | * removing rows while traversing the same table can cause some rows to be | |
616 | * visited twice or not at apply. */ | |
66095e15 BP |
617 | const struct %(s)s * |
618 | %(s)s_first(const struct ovsdb_idl *idl) | |
c3bb4bd7 | 619 | { |
9478f52f | 620 | return %(s)s_cast(ovsdb_idl_first_row(idl, &%(p)stable_%(tl)s)); |
c3bb4bd7 BP |
621 | } |
622 | ||
d797877d JP |
623 | /* Returns a row following 'row' within its table, or a null pointer if 'row' |
624 | * is the last row in its table. */ | |
66095e15 BP |
625 | const struct %(s)s * |
626 | %(s)s_next(const struct %(s)s *row) | |
c3bb4bd7 | 627 | { |
66095e15 | 628 | return %(s)s_cast(ovsdb_idl_next_row(&row->header_)); |
932104f4 SA |
629 | } |
630 | ||
631 | unsigned int %(s)s_get_seqno(const struct ovsdb_idl *idl) | |
632 | { | |
9478f52f | 633 | return ovsdb_idl_table_get_seqno(idl, &%(p)stable_%(tl)s); |
932104f4 SA |
634 | } |
635 | ||
636 | unsigned int %(s)s_row_get_seqno(const struct %(s)s *row, enum ovsdb_idl_change change) | |
637 | { | |
638 | return ovsdb_idl_row_get_seqno(&row->header_, change); | |
639 | } | |
640 | ||
641 | const struct %(s)s * | |
642 | %(s)s_track_get_first(const struct ovsdb_idl *idl) | |
643 | { | |
9478f52f | 644 | return %(s)s_cast(ovsdb_idl_track_get_first(idl, &%(p)stable_%(tl)s)); |
932104f4 SA |
645 | } |
646 | ||
647 | const struct %(s)s | |
648 | *%(s)s_track_get_next(const struct %(s)s *row) | |
649 | { | |
650 | return %(s)s_cast(ovsdb_idl_track_get_next(&row->header_)); | |
475281c0 BP |
651 | }''' % {'s': structName, |
652 | 'p': prefix, | |
653 | 'P': prefix.upper(), | |
d797877d | 654 | 't': tableName, |
9478f52f | 655 | 'tl': tableName.lower(), |
d34a1cc0 | 656 | 'T': tableName.upper()}) |
475281c0 | 657 | |
d34a1cc0 | 658 | print(''' |
932104f4 | 659 | |
d797877d JP |
660 | /* Deletes 'row' from table "%(t)s". 'row' may be freed, so it must not be |
661 | * accessed afterward. | |
662 | * | |
663 | * The caller must have started a transaction with ovsdb_idl_txn_create(). */ | |
475281c0 | 664 | void |
9e336f49 | 665 | %(s)s_delete(const struct %(s)s *row) |
475281c0 | 666 | { |
475281c0 BP |
667 | ovsdb_idl_txn_delete(&row->header_); |
668 | } | |
669 | ||
d797877d JP |
670 | /* Inserts and returns a new row in the table "%(t)s" in the database |
671 | * with open transaction 'txn'. | |
672 | * | |
673 | * The new row is assigned a randomly generated provisional UUID. | |
674 | * ovsdb-server will assign a different UUID when 'txn' is committed, | |
675 | * but the IDL will replace any uses of the provisional UUID in the | |
676 | * data to be to be committed by the UUID assigned by ovsdb-server. */ | |
475281c0 BP |
677 | struct %(s)s * |
678 | %(s)s_insert(struct ovsdb_idl_txn *txn) | |
679 | { | |
9478f52f | 680 | return %(s)s_cast(ovsdb_idl_txn_insert(txn, &%(p)stable_%(tl)s, NULL)); |
32d37ce8 SA |
681 | } |
682 | ||
683 | bool | |
684 | %(s)s_is_updated(const struct %(s)s *row, enum %(s)s_column_id column) | |
685 | { | |
686 | return ovsdb_idl_track_is_updated(&row->header_, &%(s)s_columns[column]); | |
d797877d JP |
687 | }''' % {'s': structName, |
688 | 'p': prefix, | |
689 | 'P': prefix.upper(), | |
690 | 't': tableName, | |
9478f52f | 691 | 'tl': tableName.lower(), |
d34a1cc0 | 692 | 'T': tableName.upper()}) |
475281c0 BP |
693 | |
694 | # Verify functions. | |
e0b1744f | 695 | for columnName, column in sorted_columns(table): |
01928c96 BP |
696 | if column.extensions.get('synthetic'): |
697 | continue | |
d34a1cc0 | 698 | print(''' |
d797877d JP |
699 | /* Causes the original contents of column "%(c)s" in 'row' to be |
700 | * verified as a prerequisite to completing the transaction. That is, if | |
701 | * "%(c)s" in 'row' changed (or if 'row' was deleted) between the | |
702 | * time that the IDL originally read its contents and the time that the | |
b17c8228 | 703 | * transaction aborts and ovsdb_idl_txn_commit() returns TXN_TRY_AGAIN. |
d797877d JP |
704 | * |
705 | * The intention is that, to ensure that no transaction commits based on dirty | |
706 | * reads, an application should call this function any time "%(c)s" is | |
707 | * read as part of a read-modify-write operation. | |
708 | * | |
709 | * In some cases this function reduces to a no-op, because the current value | |
710 | * of "%(c)s" is already known: | |
711 | * | |
712 | * - If 'row' is a row created by the current transaction (returned by | |
713 | * %(s)s_insert()). | |
714 | * | |
715 | * - If "%(c)s" has already been modified (with | |
716 | * %(s)s_set_%(c)s()) within the current transaction. | |
717 | * | |
718 | * Because of the latter property, always call this function *before* | |
719 | * %(s)s_set_%(c)s() for a given read-modify-write. | |
720 | * | |
721 | * The caller must have started a transaction with ovsdb_idl_txn_create(). */ | |
475281c0 BP |
722 | void |
723 | %(s)s_verify_%(c)s(const struct %(s)s *row) | |
724 | { | |
1f2d2557 | 725 | ovsdb_idl_txn_verify(&row->header_, &%(s)s_col_%(c)s); |
475281c0 BP |
726 | }''' % {'s': structName, |
727 | 'S': structName.upper(), | |
728 | 'c': columnName, | |
d34a1cc0 | 729 | 'C': columnName.upper()}) |
475281c0 | 730 | |
a6ec9089 | 731 | # Get functions. |
e0b1744f | 732 | for columnName, column in sorted_columns(table): |
01928c96 BP |
733 | if column.extensions.get('synthetic'): |
734 | continue | |
a6ec9089 BP |
735 | if column.type.value: |
736 | valueParam = ',\n\tenum ovsdb_atomic_type value_type OVS_UNUSED' | |
cb22974d | 737 | valueType = '\n ovs_assert(value_type == %s);' % column.type.value.toAtomicType() |
a6ec9089 BP |
738 | valueComment = "\n * 'value_type' must be %s." % column.type.value.toAtomicType() |
739 | else: | |
740 | valueParam = '' | |
741 | valueType = '' | |
742 | valueComment = '' | |
d34a1cc0 | 743 | print(""" |
d797877d JP |
744 | /* Returns the "%(c)s" column's value from the "%(t)s" table in 'row' |
745 | * as a struct ovsdb_datum. This is useful occasionally: for example, | |
746 | * ovsdb_datum_find_key() is an easier and more efficient way to search | |
747 | * for a given key than implementing the same operation on the "cooked" | |
748 | * form in 'row'. | |
a6ec9089 BP |
749 | * |
750 | * 'key_type' must be %(kt)s.%(vc)s | |
751 | * (This helps to avoid silent bugs if someone changes %(c)s's | |
752 | * type without updating the caller.) | |
753 | * | |
754 | * The caller must not modify or free the returned value. | |
755 | * | |
756 | * Various kinds of changes can invalidate the returned value: modifying | |
757 | * 'column' within 'row', deleting 'row', or completing an ongoing transaction. | |
758 | * If the returned value is needed for a long time, it is best to make a copy | |
d797877d JP |
759 | * of it with ovsdb_datum_clone(). |
760 | * | |
761 | * This function is rarely useful, since it is easier to access the value | |
762 | * directly through the "%(c)s" member in %(s)s. */ | |
a6ec9089 BP |
763 | const struct ovsdb_datum * |
764 | %(s)s_get_%(c)s(const struct %(s)s *row, | |
765 | \tenum ovsdb_atomic_type key_type OVS_UNUSED%(v)s) | |
766 | { | |
cb22974d | 767 | ovs_assert(key_type == %(kt)s);%(vt)s |
a6ec9089 | 768 | return ovsdb_idl_read(&row->header_, &%(s)s_col_%(c)s); |
d797877d | 769 | }""" % {'t': tableName, 's': structName, 'c': columnName, |
a6ec9089 | 770 | 'kt': column.type.key.toAtomicType(), |
d34a1cc0 | 771 | 'v': valueParam, 'vt': valueType, 'vc': valueComment}) |
a6ec9089 | 772 | |
475281c0 | 773 | # Set functions. |
e0b1744f | 774 | for columnName, column in sorted_columns(table): |
01928c96 BP |
775 | if column.extensions.get('synthetic'): |
776 | continue | |
475281c0 | 777 | type = column.type |
a699f614 | 778 | |
7cc398cb JP |
779 | comment, members = cMembers(prefix, tableName, columnName, |
780 | column, True) | |
781 | ||
a699f614 | 782 | if type.is_smap(): |
d34a1cc0 JW |
783 | print(comment) |
784 | print("""void | |
4946b41d | 785 | %(s)s_set_%(c)s(const struct %(s)s *row, const struct smap *%(c)s) |
a699f614 EJ |
786 | { |
787 | struct ovsdb_datum datum; | |
788 | ||
4946b41d | 789 | if (%(c)s) { |
9b03e59d | 790 | ovsdb_datum_from_smap(&datum, %(c)s); |
a699f614 EJ |
791 | } else { |
792 | ovsdb_datum_init_empty(&datum); | |
793 | } | |
794 | ovsdb_idl_txn_write(&row->header_, | |
1f2d2557 | 795 | &%(s)s_col_%(c)s, |
a699f614 EJ |
796 | &datum); |
797 | } | |
7cc398cb JP |
798 | """ % {'t': tableName, |
799 | 's': structName, | |
a699f614 EJ |
800 | 'S': structName.upper(), |
801 | 'c': columnName, | |
d34a1cc0 | 802 | 'C': columnName.upper()}) |
a699f614 EJ |
803 | continue |
804 | ||
475281c0 BP |
805 | keyVar = members[0]['name'] |
806 | nVar = None | |
807 | valueVar = None | |
808 | if type.value: | |
809 | valueVar = members[1]['name'] | |
810 | if len(members) > 2: | |
811 | nVar = members[2]['name'] | |
812 | else: | |
813 | if len(members) > 1: | |
814 | nVar = members[1]['name'] | |
7cc398cb | 815 | |
d34a1cc0 JW |
816 | print(comment) |
817 | print("""\ | |
cad9a996 BP |
818 | void |
819 | %(s)s_set_%(c)s(const struct %(s)s *row, %(args)s) | |
820 | { | |
cad9a996 | 821 | struct ovsdb_datum datum;""" % {'s': structName, |
74e98efd BP |
822 | 'c': columnName, |
823 | 'args': ', '.join(['%(type)s%(name)s' | |
d34a1cc0 | 824 | % m for m in members])}) |
99155935 | 825 | if type.n_min == 1 and type.n_max == 1: |
d34a1cc0 | 826 | print(" union ovsdb_atom key;") |
fe19569a | 827 | if type.value: |
d34a1cc0 JW |
828 | print(" union ovsdb_atom value;") |
829 | print("") | |
830 | print(" datum.n = 1;") | |
831 | print(" datum.keys = &key;") | |
832 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)) | |
475281c0 | 833 | if type.value: |
d34a1cc0 JW |
834 | print(" datum.values = &value;") |
835 | print(" "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar)) | |
475281c0 | 836 | else: |
d34a1cc0 | 837 | print(" datum.values = NULL;") |
fe19569a | 838 | txn_write_func = "ovsdb_idl_txn_write_clone" |
99155935 | 839 | elif type.is_optional_pointer(): |
d34a1cc0 JW |
840 | print(" union ovsdb_atom key;") |
841 | print("") | |
842 | print(" if (%s) {" % keyVar) | |
843 | print(" datum.n = 1;") | |
844 | print(" datum.keys = &key;") | |
845 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)) | |
846 | print(" } else {") | |
847 | print(" datum.n = 0;") | |
848 | print(" datum.keys = NULL;") | |
849 | print(" }") | |
850 | print(" datum.values = NULL;") | |
fe19569a BP |
851 | txn_write_func = "ovsdb_idl_txn_write_clone" |
852 | elif type.n_max == 1: | |
d34a1cc0 JW |
853 | print(" union ovsdb_atom key;") |
854 | print("") | |
855 | print(" if (%s) {" % nVar) | |
856 | print(" datum.n = 1;") | |
857 | print(" datum.keys = &key;") | |
858 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar)) | |
859 | print(" } else {") | |
860 | print(" datum.n = 0;") | |
861 | print(" datum.keys = NULL;") | |
862 | print(" }") | |
863 | print(" datum.values = NULL;") | |
fe19569a | 864 | txn_write_func = "ovsdb_idl_txn_write_clone" |
475281c0 | 865 | else: |
d34a1cc0 JW |
866 | print("") |
867 | print(" datum.n = %s;" % nVar) | |
868 | print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)) | |
475281c0 | 869 | if type.value: |
d34a1cc0 | 870 | print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar) |
475281c0 | 871 | else: |
d34a1cc0 JW |
872 | print(" datum.values = NULL;") |
873 | print(" for (size_t i = 0; i < %s; i++) {" % nVar) | |
874 | print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)) | |
475281c0 | 875 | if type.value: |
d34a1cc0 JW |
876 | print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)) |
877 | print(" }") | |
a1ec42a3 BP |
878 | if type.value: |
879 | valueType = type.value.toAtomicType() | |
880 | else: | |
881 | valueType = "OVSDB_TYPE_VOID" | |
fe19569a | 882 | txn_write_func = "ovsdb_idl_txn_write" |
d34a1cc0 | 883 | print(" %(f)s(&row->header_, &%(s)s_col_%(c)s, &datum);" \ |
fe19569a BP |
884 | % {'f': txn_write_func, |
885 | 's': structName, | |
475281c0 | 886 | 'S': structName.upper(), |
d34a1cc0 JW |
887 | 'c': columnName}) |
888 | print("}") | |
010fe7ae | 889 | # Update/Delete of partial map column functions |
e0b1744f | 890 | for columnName, column in sorted_columns(table): |
01928c96 BP |
891 | if column.extensions.get('synthetic'): |
892 | continue | |
010fe7ae EA |
893 | type = column.type |
894 | if type.is_map(): | |
d34a1cc0 | 895 | print(''' |
010fe7ae EA |
896 | /* Sets an element of the "%(c)s" map column from the "%(t)s" table in 'row' |
897 | * to 'new_value' given the key value 'new_key'. | |
898 | * | |
899 | */ | |
900 | void | |
901 | %(s)s_update_%(c)s_setkey(const struct %(s)s *row, %(coltype)snew_key, %(valtype)snew_value) | |
902 | { | |
903 | struct ovsdb_datum *datum; | |
904 | ||
010fe7ae EA |
905 | datum = xmalloc(sizeof *datum); |
906 | datum->n = 1; | |
907 | datum->keys = xmalloc(datum->n * sizeof *datum->keys); | |
908 | datum->values = xmalloc(datum->n * sizeof *datum->values); | |
05ba459f BP |
909 | ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), |
910 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(), | |
d34a1cc0 | 911 | 'C': columnName.upper(), 't': tableName}) |
010fe7ae | 912 | |
d34a1cc0 JW |
913 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "new_key")) |
914 | print(" "+ type.value.copyCValue("datum->values[0].%s" % type.value.type.to_string(), "new_value")) | |
915 | print(''' | |
010fe7ae | 916 | ovsdb_idl_txn_write_partial_map(&row->header_, |
1f2d2557 | 917 | &%(s)s_col_%(c)s, |
010fe7ae | 918 | datum); |
1f2d2557 | 919 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 JW |
920 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper()}) |
921 | print(''' | |
010fe7ae EA |
922 | /* Deletes an element of the "%(c)s" map column from the "%(t)s" table in 'row' |
923 | * given the key value 'delete_key'. | |
924 | * | |
925 | */ | |
926 | void | |
927 | %(s)s_update_%(c)s_delkey(const struct %(s)s *row, %(coltype)sdelete_key) | |
928 | { | |
929 | struct ovsdb_datum *datum; | |
930 | ||
010fe7ae EA |
931 | datum = xmalloc(sizeof *datum); |
932 | datum->n = 1; | |
933 | datum->keys = xmalloc(datum->n * sizeof *datum->keys); | |
934 | datum->values = NULL; | |
05ba459f BP |
935 | ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), |
936 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(), | |
d34a1cc0 | 937 | 'C': columnName.upper(), 't': tableName}) |
010fe7ae | 938 | |
d34a1cc0 JW |
939 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_key")) |
940 | print(''' | |
010fe7ae | 941 | ovsdb_idl_txn_delete_partial_map(&row->header_, |
1f2d2557 | 942 | &%(s)s_col_%(c)s, |
010fe7ae | 943 | datum); |
1f2d2557 | 944 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 | 945 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper()}) |
010fe7ae | 946 | # End Update/Delete of partial maps |
f1ab6e06 RM |
947 | # Update/Delete of partial set column functions |
948 | if type.is_set(): | |
d34a1cc0 | 949 | print(''' |
f1ab6e06 RM |
950 | /* Adds the value 'new_value' to the "%(c)s" set column from the "%(t)s" table |
951 | * in 'row'. | |
952 | * | |
953 | */ | |
954 | void | |
955 | %(s)s_update_%(c)s_addvalue(const struct %(s)s *row, %(valtype)snew_value) | |
956 | { | |
957 | struct ovsdb_datum *datum; | |
958 | ||
f1ab6e06 RM |
959 | datum = xmalloc(sizeof *datum); |
960 | datum->n = 1; | |
961 | datum->keys = xmalloc(datum->n * sizeof *datum->values); | |
962 | datum->values = NULL; | |
963 | ''' % {'s': structName, 'c': columnName, | |
d34a1cc0 | 964 | 'valtype':column.type.key.to_const_c_type(prefix), 't': tableName}) |
f1ab6e06 | 965 | |
d34a1cc0 JW |
966 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "new_value")) |
967 | print(''' | |
f1ab6e06 | 968 | ovsdb_idl_txn_write_partial_set(&row->header_, |
1f2d2557 | 969 | &%(s)s_col_%(c)s, |
f1ab6e06 | 970 | datum); |
1f2d2557 | 971 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 JW |
972 | 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper()}) |
973 | print(''' | |
f1ab6e06 RM |
974 | /* Deletes the value 'delete_value' from the "%(c)s" set column from the |
975 | * "%(t)s" table in 'row'. | |
976 | * | |
977 | */ | |
978 | void | |
979 | %(s)s_update_%(c)s_delvalue(const struct %(s)s *row, %(valtype)sdelete_value) | |
980 | { | |
981 | struct ovsdb_datum *datum; | |
982 | ||
f1ab6e06 RM |
983 | datum = xmalloc(sizeof *datum); |
984 | datum->n = 1; | |
985 | datum->keys = xmalloc(datum->n * sizeof *datum->values); | |
986 | datum->values = NULL; | |
05ba459f BP |
987 | ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), |
988 | 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper(), | |
d34a1cc0 | 989 | 'C': columnName.upper(), 't': tableName}) |
f1ab6e06 | 990 | |
d34a1cc0 JW |
991 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_value")) |
992 | print(''' | |
f1ab6e06 | 993 | ovsdb_idl_txn_delete_partial_set(&row->header_, |
1f2d2557 | 994 | &%(s)s_col_%(c)s, |
f1ab6e06 | 995 | datum); |
1f2d2557 | 996 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 | 997 | 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper()}) |
f1ab6e06 | 998 | # End Update/Delete of partial set |
c3bb4bd7 | 999 | |
16ebb90e | 1000 | # Add clause functions. |
e0b1744f | 1001 | for columnName, column in sorted_columns(table): |
01928c96 BP |
1002 | if column.extensions.get('synthetic'): |
1003 | continue | |
16ebb90e LS |
1004 | type = column.type |
1005 | ||
1006 | comment, members = cMembers(prefix, tableName, columnName, | |
4bb7f568 | 1007 | column, True, refTable=False) |
16ebb90e LS |
1008 | |
1009 | if type.is_smap(): | |
d34a1cc0 JW |
1010 | print(comment) |
1011 | print("""void | |
0164e367 | 1012 | %(s)s_add_clause_%(c)s(struct ovsdb_idl_condition *cond, enum ovsdb_function function, const struct smap *%(c)s) |
16ebb90e LS |
1013 | { |
1014 | struct ovsdb_datum datum; | |
1015 | ||
16ebb90e | 1016 | if (%(c)s) { |
9b03e59d | 1017 | ovsdb_datum_from_smap(&datum, %(c)s); |
16ebb90e LS |
1018 | } else { |
1019 | ovsdb_datum_init_empty(&datum); | |
1020 | } | |
1021 | ||
0164e367 | 1022 | ovsdb_idl_condition_add_clause(cond, |
16ebb90e | 1023 | function, |
1f2d2557 | 1024 | &%(s)s_col_%(c)s, |
16ebb90e | 1025 | &datum); |
a4e68acd BP |
1026 | |
1027 | ovsdb_datum_destroy(&datum, &%(s)s_col_%(c)s.type); | |
16ebb90e LS |
1028 | } |
1029 | """ % {'t': tableName, | |
9478f52f | 1030 | 'tl': tableName.lower(), |
16ebb90e LS |
1031 | 'T': tableName.upper(), |
1032 | 'p': prefix, | |
1033 | 'P': prefix.upper(), | |
1034 | 's': structName, | |
1035 | 'S': structName.upper(), | |
d34a1cc0 | 1036 | 'c': columnName}) |
16ebb90e LS |
1037 | continue |
1038 | ||
1039 | keyVar = members[0]['name'] | |
1040 | nVar = None | |
1041 | valueVar = None | |
1042 | if type.value: | |
1043 | valueVar = members[1]['name'] | |
1044 | if len(members) > 2: | |
1045 | nVar = members[2]['name'] | |
1046 | else: | |
1047 | if len(members) > 1: | |
1048 | nVar = members[1]['name'] | |
1049 | ||
d34a1cc0 JW |
1050 | print(comment) |
1051 | print('void') | |
1052 | print('%(s)s_add_clause_%(c)s(struct ovsdb_idl_condition *cond, enum ovsdb_function function, %(args)s)' % \ | |
16ebb90e | 1053 | {'s': structName, 'c': columnName, |
d34a1cc0 JW |
1054 | 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}) |
1055 | print("{") | |
1056 | print(" struct ovsdb_datum datum;") | |
a4e68acd | 1057 | free = [] |
16ebb90e | 1058 | if type.n_min == 1 and type.n_max == 1: |
d34a1cc0 | 1059 | print(" union ovsdb_atom key;") |
16ebb90e | 1060 | if type.value: |
d34a1cc0 JW |
1061 | print(" union ovsdb_atom value;") |
1062 | print("") | |
1063 | print(" datum.n = 1;") | |
1064 | print(" datum.keys = &key;") | |
1065 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar, refTable=False)) | |
16ebb90e | 1066 | if type.value: |
d34a1cc0 JW |
1067 | print(" datum.values = &value;") |
1068 | print(" "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar, refTable=False)) | |
16ebb90e | 1069 | else: |
d34a1cc0 | 1070 | print(" datum.values = NULL;") |
16ebb90e | 1071 | elif type.is_optional_pointer(): |
d34a1cc0 JW |
1072 | print(" union ovsdb_atom key;") |
1073 | print("") | |
1074 | print(" if (%s) {" % keyVar) | |
1075 | print(" datum.n = 1;") | |
1076 | print(" datum.keys = &key;") | |
1077 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar, refTable=False)) | |
1078 | print(" } else {") | |
1079 | print(" datum.n = 0;") | |
1080 | print(" datum.keys = NULL;") | |
1081 | print(" }") | |
1082 | print(" datum.values = NULL;") | |
16ebb90e | 1083 | elif type.n_max == 1: |
d34a1cc0 JW |
1084 | print(" union ovsdb_atom key;") |
1085 | print("") | |
1086 | print(" if (%s) {" % nVar) | |
1087 | print(" datum.n = 1;") | |
1088 | print(" datum.keys = &key;") | |
1089 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar, refTable=False)) | |
1090 | print(" } else {") | |
1091 | print(" datum.n = 0;") | |
1092 | print(" datum.keys = NULL;") | |
1093 | print(" }") | |
1094 | print(" datum.values = NULL;") | |
16ebb90e | 1095 | else: |
d34a1cc0 JW |
1096 | print(" datum.n = %s;" % nVar) |
1097 | print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)) | |
a4e68acd | 1098 | free += ['datum.keys'] |
16ebb90e | 1099 | if type.value: |
d34a1cc0 | 1100 | print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar) |
a4e68acd | 1101 | free += ['datum.values'] |
16ebb90e | 1102 | else: |
d34a1cc0 JW |
1103 | print(" datum.values = NULL;") |
1104 | print(" for (size_t i = 0; i < %s; i++) {" % nVar) | |
1105 | print(" " + type.key.assign_c_value_casting_away_const("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar, refTable=False)) | |
16ebb90e | 1106 | if type.value: |
d34a1cc0 JW |
1107 | print(" " + type.value.assign_c_value_casting_away_const("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar, refTable=False)) |
1108 | print(" }") | |
16ebb90e LS |
1109 | if type.value: |
1110 | valueType = type.value.toAtomicType() | |
1111 | else: | |
1112 | valueType = "OVSDB_TYPE_VOID" | |
d34a1cc0 JW |
1113 | print(" ovsdb_datum_sort_unique(&datum, %s, %s);" % ( |
1114 | type.key.toAtomicType(), valueType)) | |
16ebb90e | 1115 | |
d34a1cc0 | 1116 | print(""" ovsdb_idl_condition_add_clause(cond, |
16ebb90e | 1117 | function, |
1f2d2557 | 1118 | &%(s)s_col_%(c)s, |
a4e68acd | 1119 | &datum);\ |
9478f52f | 1120 | """ % {'tl': tableName.lower(), |
16ebb90e LS |
1121 | 'T': tableName.upper(), |
1122 | 'p': prefix, | |
1123 | 'P': prefix.upper(), | |
1124 | 's': structName, | |
1125 | 'S': structName.upper(), | |
d34a1cc0 | 1126 | 'c': columnName}) |
a4e68acd | 1127 | for var in free: |
d34a1cc0 JW |
1128 | print(" free(%s);" % var) |
1129 | print("}") | |
16ebb90e | 1130 | |
0a8606ee LR |
1131 | # Index table related functions |
1132 | print(""" | |
1133 | /* Destroy 'row' of kind "%(t)s". The row must have been | |
1134 | * created with ovsdb_idl_index_init_row. | |
1135 | */ | |
1136 | void | |
1137 | %(s)s_index_destroy_row(const struct %(s)s *row) | |
1138 | { | |
1139 | ovsdb_idl_index_destroy_row__(&row->header_); | |
1140 | } | |
1141 | """ % { 's' : structName, 't': tableName }) | |
1142 | print(""" | |
1143 | /* Creates a new row of kind "%(t)s". */ | |
1144 | struct %(s)s * | |
3eb14233 | 1145 | %(s)s_index_init_row(struct ovsdb_idl *idl, const struct ovsdb_idl_table_class *class_) |
0a8606ee | 1146 | {""" % {'s': structName, 't': tableName}) |
81068700 | 1147 | #for columnName, column in sorted(table.columns.items()): |
0a8606ee LR |
1148 | # if column.type.is_smap(): |
1149 | # print " smap_init(&row->%s);" % columnName | |
3eb14233 | 1150 | print(" return (struct %(s)s *) ovsdb_idl_index_init_row(idl, class_);" % {'s': structName, 't': tableName}) |
0a8606ee LR |
1151 | print("}") |
1152 | ||
1153 | print(""" | |
1154 | /* This function is used to compare "%(s)s" records on table in iteration loops for compound-index operations. | |
1155 | After been called, cursor point to current position in the index | |
1156 | Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate over the indexed data on this table. | |
1157 | const struct "%(s)s" *const_data1, const struct "%(s)s" *const_data2. Data to be compared. | |
1158 | Return value: 0 if both data values are equal, -1 if first parameter is less than second and 1 otherwise. */""" % {'s' : structName}) | |
1159 | print('int') | |
1160 | print("""%(s)s_index_compare(struct ovsdb_idl_index_cursor *cursor, const struct %(s)s *const_data1, const struct %(s)s *const_data2) | |
1161 | { | |
1162 | struct %(s)s *data1 = CONST_CAST(struct %(s)s *, const_data1); | |
1163 | struct %(s)s *data2 = CONST_CAST(struct %(s)s *, const_data2); | |
1164 | return ovsdb_idl_index_compare(cursor, &data1->header_, &data2->header_); | |
1165 | }""" % { 's' : structName }) | |
1166 | print(""" | |
1167 | /* This function is called to position the cursor at the first row in "%(s)s" table on the associated compound-index. | |
1168 | Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate over the indexed data on this table. | |
1169 | Return value: The first row in the corresponding index. */""" % {'s' : structName }) | |
1170 | print("""const struct %(s)s *\n%(s)s_index_first(struct ovsdb_idl_index_cursor *cursor) | |
1171 | { | |
1172 | return %(s)s_cast(ovsdb_idl_index_first(cursor)); | |
1173 | }""" % { 's' : structName }) | |
1174 | print(""" | |
1175 | /* This function is called to position the cursor at the next row in "%(s)s" table on the associated compound-index. | |
1176 | Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate over the indexed data on this table. | |
1177 | Return value: The next row in the corresponding index. */""" % {'s' : structName, 'c' : columnName }) | |
1178 | print("""const struct %(s)s *\n%(s)s_index_next(struct ovsdb_idl_index_cursor *cursor) | |
1179 | { | |
1180 | return %(s)s_cast(ovsdb_idl_index_next(cursor)); | |
1181 | }""" % { 's' : structName }) | |
1182 | print(""" | |
1183 | /* This function is used to find the data of the row in "%(s)s" table that meet criteria with the requested data | |
1184 | associated in the compound-index. | |
1185 | Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate over the indexed data on this table. | |
1186 | const struct %(s)s *const_data. Data to be searched. | |
1187 | Return value: The row in the corresponding index if found or NULL otherwise. */""" % {'s' : structName }) | |
1188 | print("""const struct %(s)s *\n%(s)s_index_find(struct ovsdb_idl_index_cursor *cursor, const struct %(s)s *const_data) | |
1189 | { | |
1190 | struct %(s)s *data = CONST_CAST(struct %(s)s *, const_data); | |
1191 | return %(s)s_cast(ovsdb_idl_index_find(cursor, &data->header_)); | |
1192 | }""" % { 's' : structName }) | |
1193 | print(""" | |
1194 | /* This function is used to set the cursor pointing to the row in "%(s)s" table that meet criteria of the requested data | |
1195 | associated in the compound-index. | |
1196 | Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate over the indexed data on this table. | |
1197 | const struct %(s)s *const_data. Data to be searched. | |
1198 | Return value: The row in the corresponding index closest to the criteria. */""" % {'s' : structName }) | |
1199 | print("""const struct %(s)s *\n%(s)s_index_forward_to(struct ovsdb_idl_index_cursor *cursor, const struct %(s)s *const_data) | |
1200 | { | |
1201 | struct %(s)s *data = CONST_CAST(struct %(s)s *, const_data); | |
1202 | return %(s)s_cast(ovsdb_idl_index_forward_to(cursor, &data->header_)); | |
1203 | }""" % { 's' : structName }) | |
1204 | print(""" | |
1205 | /* This function is used to get the data of the row in the current position pointed by the cursor in | |
1206 | "%(s)s" table. | |
1207 | Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate over the indexed data on this table. | |
1208 | Return value: The row in the corresponding index if found or NULL otherwise. */""" % {'s' : structName, 'c' : columnName }) | |
1209 | print("""const struct %(s)s *\n%(s)s_index_get_data(const struct ovsdb_idl_index_cursor *cursor) | |
1210 | { | |
1211 | return %(s)s_cast(ovsdb_idl_index_data(CONST_CAST(struct ovsdb_idl_index_cursor *, cursor))); | |
1212 | }""" % { 's' : structName }) | |
1213 | # Indexes Set functions | |
81068700 | 1214 | for columnName, column in sorted(table.columns.items()): |
0a8606ee LR |
1215 | type = column.type |
1216 | ||
1217 | comment, members = cMembers(prefix, tableName, columnName, | |
1218 | column, True) | |
1219 | ||
1220 | if type.is_smap(): | |
1221 | print(comment) | |
1222 | print("""void | |
1223 | %(s)s_index_set_%(c)s(const struct %(s)s *row, const struct smap *%(c)s) | |
1224 | { | |
1225 | struct ovsdb_datum *datum = xmalloc(sizeof(struct ovsdb_datum)); | |
1226 | ||
1227 | if (%(c)s) { | |
1228 | struct smap_node *node; | |
1229 | size_t i; | |
1230 | ||
1231 | datum->n = smap_count(%(c)s); | |
1232 | datum->keys = xmalloc(datum->n * sizeof *datum->keys); | |
1233 | datum->values = xmalloc(datum->n * sizeof *datum->values); | |
1234 | ||
1235 | i = 0; | |
1236 | SMAP_FOR_EACH (node, %(c)s) { | |
1237 | datum->keys[i].string = node->key; | |
1238 | datum->values[i].string = node->value; | |
1239 | i++; | |
1240 | } | |
1241 | ovsdb_datum_sort_unique(datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING); | |
1242 | } else { | |
1243 | ovsdb_datum_init_empty(datum); | |
1244 | } | |
1245 | ovsdb_idl_index_write_(CONST_CAST(struct ovsdb_idl_row *, &row->header_), | |
1246 | &%(s)s_columns[%(S)s_COL_%(C)s], | |
1247 | datum, | |
1248 | &%(p)stable_classes[%(P)sTABLE_%(T)s]); | |
1249 | } | |
1250 | """ % {'t': tableName, | |
1251 | 'p': prefix, | |
1252 | 'P': prefix.upper(), | |
1253 | 's': structName, | |
1254 | 'S': structName.upper(), | |
1255 | 'c': columnName, | |
1256 | 'C': columnName.upper(), | |
1257 | 't': tableName, | |
1258 | 'T': tableName.upper()}) | |
1259 | continue | |
1260 | ||
1261 | keyVar = members[0]['name'] | |
1262 | nVar = None | |
1263 | valueVar = None | |
1264 | if type.value: | |
1265 | valueVar = members[1]['name'] | |
1266 | if len(members) > 2: | |
1267 | nVar = members[2]['name'] | |
1268 | else: | |
1269 | if len(members) > 1: | |
1270 | nVar = members[1]['name'] | |
1271 | ||
1272 | print(comment) | |
1273 | print('void') | |
1274 | print('%(s)s_index_set_%(c)s(const struct %(s)s *row, %(args)s)' % \ | |
1275 | {'s': structName, 'c': columnName, | |
1276 | 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}) | |
1277 | print("{") | |
1278 | print(" struct ovsdb_datum datum;") | |
1279 | if type.n_min == 1 and type.n_max == 1: | |
1280 | print(" union ovsdb_atom *key = xmalloc(sizeof(union ovsdb_atom));") | |
1281 | if type.value: | |
1282 | print(" union ovsdb_atom *value = xmalloc(sizeof(union ovsdb_atom));") | |
1283 | print() | |
1284 | print(" datum.n = 1;") | |
1285 | print(" datum.keys = key;") | |
1286 | print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), keyVar)) | |
1287 | if type.value: | |
1288 | print(" datum.values = value;") | |
1289 | print(" "+ type.value.assign_c_value_casting_away_const("value->%s" % type.value.type.to_string(), valueVar)) | |
1290 | else: | |
1291 | print(" datum.values = NULL;") | |
1292 | txn_write_func = "ovsdb_idl_index_write_" | |
1293 | elif type.is_optional_pointer(): | |
1294 | print(" union ovsdb_atom *key = xmalloc(sizeof (union ovsdb_atom));") | |
1295 | print() | |
1296 | print(" if (%s) {" % keyVar) | |
1297 | print(" datum.n = 1;") | |
1298 | print(" datum.keys = key;") | |
1299 | print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), keyVar)) | |
1300 | print(" } else {") | |
1301 | print(" datum.n = 0;") | |
1302 | print(" datum.keys = NULL;") | |
1303 | print(" }") | |
1304 | print(" datum.values = NULL;") | |
1305 | txn_write_func = "ovsdb_idl_index_write_" | |
1306 | elif type.n_max == 1: | |
1307 | print(" union ovsdb_atom *key = xmalloc(sizeof(union ovsdb_atom));") | |
1308 | print() | |
1309 | print(" if (%s) {" % nVar) | |
1310 | print(" datum.n = 1;") | |
1311 | print(" datum.keys = key;") | |
1312 | print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), "*" + keyVar)) | |
1313 | print(" } else {") | |
1314 | print(" datum.n = 0;") | |
1315 | print(" datum.keys = NULL;") | |
1316 | print(" }") | |
1317 | print(" datum.values = NULL;") | |
1318 | txn_write_func = "ovsdb_idl_index_write_" | |
1319 | else: | |
1320 | print(" size_t i;") | |
1321 | print() | |
1322 | print(" datum.n = %s;" % nVar) | |
1323 | print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)) | |
1324 | if type.value: | |
1325 | print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar) | |
1326 | else: | |
1327 | print(" datum.values = NULL;") | |
1328 | print(" for (i = 0; i < %s; i++) {" % nVar) | |
1329 | print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)) | |
1330 | if type.value: | |
1331 | print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)) | |
1332 | print(" }") | |
1333 | if type.value: | |
1334 | valueType = type.value.toAtomicType() | |
1335 | else: | |
1336 | valueType = "OVSDB_TYPE_VOID" | |
1337 | print(" ovsdb_datum_sort_unique(&datum, %s, %s);" % ( | |
1338 | type.key.toAtomicType(), valueType)) | |
1339 | txn_write_func = "ovsdb_idl_index_write_" | |
1340 | print(" %(f)s(CONST_CAST(struct ovsdb_idl_row *, &row->header_), &%(s)s_columns[ %(S)s_COL_%(C)s ], &datum, &%(p)stable_classes[%(P)sTABLE_%(T)s]);" \ | |
1341 | % {'f': txn_write_func, | |
1342 | 's': structName, | |
1343 | 'S': structName.upper(), | |
1344 | 'C': columnName.upper(), | |
1345 | 'p': prefix, | |
1346 | 'P': prefix.upper(), | |
1347 | 't': tableName, | |
1348 | 'T': tableName.upper()}) | |
1349 | print("}") | |
1350 | # End Index table related functions | |
1351 | ||
1352 | # Table columns. | |
1353 | print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % ( | |
1354 | structName, structName.upper())) | |
d34a1cc0 | 1355 | print(""" |
1f2d2557 | 1356 | void |
0164e367 | 1357 | %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition) |
16ebb90e | 1358 | { |
0164e367 BP |
1359 | ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition); |
1360 | }""" % {'p': prefix, | |
1361 | 's': structName, | |
d34a1cc0 | 1362 | 'tl': tableName.lower()}) |
16ebb90e | 1363 | |
c3bb4bd7 | 1364 | # Table columns. |
74e98efd BP |
1365 | for columnName, column in sorted_columns(table): |
1366 | prereqs = [] | |
1367 | x = column.type.cInitType("%s_col_%s" % (tableName, columnName), prereqs) | |
1368 | if prereqs: | |
d34a1cc0 JW |
1369 | print('\n'.join(prereqs)) |
1370 | print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS] = {" % ( | |
1371 | structName, structName.upper())) | |
e0b1744f | 1372 | for columnName, column in sorted_columns(table): |
341c4e59 BP |
1373 | if column.mutable: |
1374 | mutable = "true" | |
1375 | else: | |
1376 | mutable = "false" | |
01928c96 BP |
1377 | if column.extensions.get("synthetic"): |
1378 | synthetic = "true" | |
1379 | else: | |
1380 | synthetic = "false" | |
74e98efd BP |
1381 | type_init = '\n'.join(" " + x |
1382 | for x in column.type.cInitType("%s_col_%s" % (tableName, columnName), prereqs)) | |
d34a1cc0 | 1383 | print("""\ |
74e98efd | 1384 | [%(P)s%(T)s_COL_%(C)s] = { |
adb4185d | 1385 | .name = "%(column_name_in_schema)s", |
74e98efd BP |
1386 | .type = { |
1387 | %(type)s | |
1388 | }, | |
c6e5d064 | 1389 | .is_mutable = %(mutable)s, |
01928c96 | 1390 | .is_synthetic = %(synthetic)s, |
74e98efd BP |
1391 | .parse = %(s)s_parse_%(c)s, |
1392 | .unparse = %(s)s_unparse_%(c)s, | |
1393 | },\n""" % {'P': prefix.upper(), | |
1394 | 'T': tableName.upper(), | |
1395 | 'c': columnName, | |
1396 | 'C': columnName.upper(), | |
1397 | 's': structName, | |
1398 | 'mutable': mutable, | |
01928c96 | 1399 | 'synthetic': synthetic, |
adb4185d YHW |
1400 | 'type': type_init, |
1401 | 'column_name_in_schema': column.name}) | |
d34a1cc0 | 1402 | print("};") |
c3bb4bd7 BP |
1403 | |
1404 | # Table classes. | |
d34a1cc0 JW |
1405 | print("\f") |
1406 | print("struct ovsdb_idl_table_class %stable_classes[%sN_TABLES] = {" % (prefix, prefix.upper())) | |
4ab66562 | 1407 | for tableName, table in sorted(schema.tables.items()): |
c3bb4bd7 | 1408 | structName = "%s%s" % (prefix, tableName.lower()) |
c5f341ab BP |
1409 | if table.is_root: |
1410 | is_root = "true" | |
1411 | else: | |
1412 | is_root = "false" | |
25540a77 BP |
1413 | if table.max_rows == 1: |
1414 | is_singleton = "true" | |
1415 | else: | |
1416 | is_singleton = "false" | |
1417 | print(" {\"%s\", %s, %s," % (tableName, is_root, is_singleton)) | |
d34a1cc0 | 1418 | print(" %s_columns, ARRAY_SIZE(%s_columns)," % ( |
25540a77 | 1419 | structName, structName)) |
d34a1cc0 JW |
1420 | print(" sizeof(struct %s), %s_init__}," % (structName, structName)) |
1421 | print("};") | |
c3bb4bd7 BP |
1422 | |
1423 | # IDL class. | |
d34a1cc0 JW |
1424 | print("\nstruct ovsdb_idl_class %sidl_class = {" % prefix) |
1425 | print(" \"%s\", %stable_classes, ARRAY_SIZE(%stable_classes)" % ( | |
1426 | schema.name, prefix, prefix)) | |
1427 | print("};") | |
d879a707 | 1428 | |
d34a1cc0 | 1429 | print(""" |
87412f02 JP |
1430 | /* Return the schema version. The caller must not free the returned value. */ |
1431 | const char * | |
1432 | %sget_db_version(void) | |
1433 | { | |
1434 | return "%s"; | |
1435 | } | |
d34a1cc0 | 1436 | """ % (prefix, schema.version)) |
87412f02 JP |
1437 | |
1438 | ||
8cdf0349 | 1439 | |
d879a707 BP |
1440 | def ovsdb_escape(string): |
1441 | def escape(match): | |
1442 | c = match.group(0) | |
1443 | if c == '\0': | |
99155935 | 1444 | raise ovs.db.error.Error("strings may not contain null bytes") |
d879a707 BP |
1445 | elif c == '\\': |
1446 | return '\\\\' | |
1447 | elif c == '\n': | |
1448 | return '\\n' | |
1449 | elif c == '\r': | |
1450 | return '\\r' | |
1451 | elif c == '\t': | |
1452 | return '\\t' | |
1453 | elif c == '\b': | |
1454 | return '\\b' | |
1455 | elif c == '\a': | |
1456 | return '\\a' | |
1457 | else: | |
1458 | return '\\x%02x' % ord(c) | |
1459 | return re.sub(r'["\\\000-\037]', escape, string) | |
1460 | ||
d879a707 | 1461 | def usage(): |
d34a1cc0 | 1462 | print("""\ |
d879a707 | 1463 | %(argv0)s: ovsdb schema compiler |
00732bf5 | 1464 | usage: %(argv0)s [OPTIONS] COMMAND ARG... |
d879a707 | 1465 | |
00732bf5 BP |
1466 | The following commands are supported: |
1467 | annotate SCHEMA ANNOTATIONS print SCHEMA combined with ANNOTATIONS | |
1468 | c-idl-header IDL print C header file for IDL | |
1469 | c-idl-source IDL print C source file for IDL implementation | |
d879a707 BP |
1470 | |
1471 | The following options are also available: | |
1472 | -h, --help display this help message | |
1473 | -V, --version display version information\ | |
d34a1cc0 | 1474 | """ % {'argv0': argv0}) |
d879a707 BP |
1475 | sys.exit(0) |
1476 | ||
1477 | if __name__ == "__main__": | |
1478 | try: | |
1479 | try: | |
00732bf5 BP |
1480 | options, args = getopt.gnu_getopt(sys.argv[1:], 'C:hV', |
1481 | ['directory', | |
1482 | 'help', | |
d879a707 | 1483 | 'version']) |
52e4a477 | 1484 | except getopt.GetoptError as geo: |
d879a707 BP |
1485 | sys.stderr.write("%s: %s\n" % (argv0, geo.msg)) |
1486 | sys.exit(1) | |
c5c7c7c5 | 1487 | |
00732bf5 BP |
1488 | for key, value in options: |
1489 | if key in ['-h', '--help']: | |
1490 | usage() | |
1491 | elif key in ['-V', '--version']: | |
d34a1cc0 | 1492 | print("ovsdb-idlc (Open vSwitch) @VERSION@") |
00732bf5 BP |
1493 | elif key in ['-C', '--directory']: |
1494 | os.chdir(value) | |
1495 | else: | |
1496 | sys.exit(0) | |
c5c7c7c5 | 1497 | |
d879a707 | 1498 | optKeys = [key for key, value in options] |
00732bf5 BP |
1499 | |
1500 | if not args: | |
1501 | sys.stderr.write("%s: missing command argument " | |
1502 | "(use --help for help)\n" % argv0) | |
d879a707 BP |
1503 | sys.exit(1) |
1504 | ||
00732bf5 BP |
1505 | commands = {"annotate": (annotateSchema, 2), |
1506 | "c-idl-header": (printCIDLHeader, 1), | |
2c84fdf2 | 1507 | "c-idl-source": (printCIDLSource, 1)} |
00732bf5 BP |
1508 | |
1509 | if not args[0] in commands: | |
1510 | sys.stderr.write("%s: unknown command \"%s\" " | |
1511 | "(use --help for help)\n" % (argv0, args[0])) | |
d879a707 | 1512 | sys.exit(1) |
00732bf5 BP |
1513 | |
1514 | func, n_args = commands[args[0]] | |
1515 | if len(args) - 1 != n_args: | |
1516 | sys.stderr.write("%s: \"%s\" requires %d arguments but %d " | |
1517 | "provided\n" | |
1518 | % (argv0, args[0], n_args, len(args) - 1)) | |
1519 | sys.exit(1) | |
1520 | ||
1521 | func(*args[1:]) | |
52e4a477 | 1522 | except ovs.db.error.Error as e: |
99155935 | 1523 | sys.stderr.write("%s: %s\n" % (argv0, e)) |
d879a707 BP |
1524 | sys.exit(1) |
1525 | ||
1526 | # Local variables: | |
1527 | # mode: python | |
1528 | # End: |