]>
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(''' |
0eb1e37c BP |
241 | const struct %(s)s_table *%(s)s_table_get(const struct ovsdb_idl *); |
242 | const struct %(s)s *%(s)s_table_first(const struct %(s)s_table *); | |
243 | ||
244 | #define %(S)s_TABLE_FOR_EACH(ROW, TABLE) \\ | |
245 | for ((ROW) = %(s)s_table_first(TABLE); \\ | |
246 | (ROW); \\ | |
247 | (ROW) = %(s)s_next(ROW)) | |
248 | #define %(S)s_TABLE_FOR_EACH_SAFE(ROW, NEXT, TABLE) \\ | |
249 | for ((ROW) = %(s)s_table_first(TABLE); \\ | |
250 | (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\ | |
251 | (ROW) = (NEXT)) | |
252 | ||
8c6cf7b8 | 253 | const struct %(s)s *%(s)s_get_for_uuid(const struct ovsdb_idl *, const struct uuid *); |
4b282ad9 | 254 | const struct %(s)s *%(s)s_table_get_for_uuid(const struct %(s)s_table *, const struct uuid *); |
c3bb4bd7 BP |
255 | const struct %(s)s *%(s)s_first(const struct ovsdb_idl *); |
256 | const struct %(s)s *%(s)s_next(const struct %(s)s *); | |
58bc1a52 BP |
257 | #define %(S)s_FOR_EACH(ROW, IDL) \\ |
258 | for ((ROW) = %(s)s_first(IDL); \\ | |
259 | (ROW); \\ | |
260 | (ROW) = %(s)s_next(ROW)) | |
261 | #define %(S)s_FOR_EACH_SAFE(ROW, NEXT, IDL) \\ | |
262 | for ((ROW) = %(s)s_first(IDL); \\ | |
263 | (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\ | |
264 | (ROW) = (NEXT)) | |
475281c0 | 265 | |
932104f4 SA |
266 | unsigned int %(s)s_get_seqno(const struct ovsdb_idl *); |
267 | unsigned int %(s)s_row_get_seqno(const struct %(s)s *row, enum ovsdb_idl_change change); | |
268 | const struct %(s)s *%(s)s_track_get_first(const struct ovsdb_idl *); | |
269 | const struct %(s)s *%(s)s_track_get_next(const struct %(s)s *); | |
270 | #define %(S)s_FOR_EACH_TRACKED(ROW, IDL) \\ | |
271 | for ((ROW) = %(s)s_track_get_first(IDL); \\ | |
272 | (ROW); \\ | |
273 | (ROW) = %(s)s_track_get_next(ROW)) | |
274 | ||
4b282ad9 HZ |
275 | const struct %(s)s *%(s)s_table_track_get_first(const struct %(s)s_table *); |
276 | #define %(S)s_TABLE_FOR_EACH_TRACKED(ROW, TABLE) \\ | |
277 | for ((ROW) = %(s)s_table_track_get_first(TABLE); \\ | |
278 | (ROW); \\ | |
279 | (ROW) = %(s)s_track_get_next(ROW)) | |
280 | ||
281 | ||
9a33cd70 BP |
282 | /* Returns true if 'row' was inserted since the last change tracking reset. */ |
283 | static inline bool %(s)s_is_new(const struct %(s)s *row) | |
284 | { | |
285 | return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_MODIFY) == 0; | |
286 | } | |
287 | ||
288 | /* Returns true if 'row' was deleted since the last change tracking reset. */ | |
289 | static inline bool %(s)s_is_deleted(const struct %(s)s *row) | |
290 | { | |
291 | return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_DELETE) > 0; | |
292 | } | |
293 | ||
0a8606ee | 294 | void %(s)s_index_destroy_row(const struct %(s)s *); |
d14e007c BP |
295 | |
296 | struct %(s)s *%(s)s_index_find(struct ovsdb_idl_index *, const struct %(s)s *); | |
297 | ||
298 | int %(s)s_index_compare( | |
299 | struct ovsdb_idl_index *, | |
300 | const struct %(s)s *, | |
301 | const struct %(s)s *); | |
302 | struct ovsdb_idl_cursor %(s)s_cursor_first(struct ovsdb_idl_index *); | |
303 | struct ovsdb_idl_cursor %(s)s_cursor_first_eq( | |
304 | struct ovsdb_idl_index *, const struct %(s)s *); | |
305 | struct ovsdb_idl_cursor %(s)s_cursor_first_ge( | |
306 | struct ovsdb_idl_index *, const struct %(s)s *); | |
307 | ||
308 | struct %(s)s *%(s)s_cursor_data(struct ovsdb_idl_cursor *); | |
309 | ||
310 | #define %(S)s_FOR_EACH_RANGE(ROW, FROM, TO, INDEX) \\ | |
311 | for (struct ovsdb_idl_cursor cursor__ = %(s)s_cursor_first_ge(INDEX, FROM); \\ | |
312 | (cursor__.position \\ | |
313 | && ((ROW) = %(s)s_cursor_data(&cursor__), \\ | |
314 | !(TO) || %(s)s_index_compare(INDEX, ROW, TO) <= 0)); \\ | |
315 | ovsdb_idl_cursor_next(&cursor__)) | |
316 | #define %(S)s_FOR_EACH_EQUAL(ROW, KEY, INDEX) \\ | |
317 | for (struct ovsdb_idl_cursor cursor__ = %(s)s_cursor_first_eq(INDEX, KEY); \\ | |
318 | (cursor__.position \\ | |
319 | ? ((ROW) = %(s)s_cursor_data(&cursor__), \\ | |
320 | ovsdb_idl_cursor_next_eq(&cursor__), \\ | |
321 | true) \\ | |
322 | : false); \\ | |
323 | ) | |
324 | #define %(S)s_FOR_EACH_BYINDEX(ROW, INDEX) \\ | |
325 | for (struct ovsdb_idl_cursor cursor__ = %(s)s_cursor_first(INDEX); \\ | |
326 | (cursor__.position \\ | |
327 | ? ((ROW) = %(s)s_cursor_data(&cursor__), \\ | |
328 | ovsdb_idl_cursor_next(&cursor__), \\ | |
329 | true) \\ | |
330 | : false); \\ | |
331 | ) | |
0a8606ee | 332 | |
a699f614 | 333 | void %(s)s_init(struct %(s)s *); |
475281c0 BP |
334 | void %(s)s_delete(const struct %(s)s *); |
335 | struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); | |
32d37ce8 | 336 | bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id); |
d34a1cc0 | 337 | ''' % {'s': structName, 'S': structName.upper()}) |
475281c0 | 338 | |
e0b1744f | 339 | for columnName, column in sorted_columns(table): |
01928c96 BP |
340 | if column.extensions.get('synthetic'): |
341 | continue | |
d34a1cc0 | 342 | print('void %(s)s_verify_%(c)s(const struct %(s)s *);' % {'s': structName, 'c': columnName}) |
475281c0 | 343 | |
d34a1cc0 | 344 | print("") |
e0b1744f | 345 | for columnName, column in sorted_columns(table): |
01928c96 BP |
346 | if column.extensions.get('synthetic'): |
347 | continue | |
a6ec9089 BP |
348 | if column.type.value: |
349 | valueParam = ', enum ovsdb_atomic_type value_type' | |
350 | else: | |
351 | valueParam = '' | |
d34a1cc0 JW |
352 | print('const struct ovsdb_datum *%(s)s_get_%(c)s(const struct %(s)s *, enum ovsdb_atomic_type key_type%(v)s);' % { |
353 | 's': structName, 'c': columnName, 'v': valueParam}) | |
a6ec9089 | 354 | |
d34a1cc0 | 355 | print("") |
e0b1744f | 356 | for columnName, column in sorted_columns(table): |
01928c96 BP |
357 | if column.extensions.get('synthetic'): |
358 | continue | |
d34a1cc0 | 359 | print('void %(s)s_set_%(c)s(const struct %(s)s *,' % {'s': structName, 'c': columnName}, end=' ') |
a699f614 EJ |
360 | if column.type.is_smap(): |
361 | args = ['const struct smap *'] | |
362 | else: | |
7cc398cb JP |
363 | comment, members = cMembers(prefix, tableName, columnName, |
364 | column, True) | |
365 | args = ['%(type)s%(name)s' % member for member in members] | |
d34a1cc0 | 366 | print('%s);' % ', '.join(args)) |
475281c0 | 367 | |
d34a1cc0 | 368 | print("") |
e0b1744f | 369 | for columnName, column in sorted_columns(table): |
01928c96 BP |
370 | if column.extensions.get('synthetic'): |
371 | continue | |
16ebb90e | 372 | if column.type.is_map(): |
d34a1cc0 JW |
373 | print('void %(s)s_update_%(c)s_setkey(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') |
374 | print('%(coltype)s, %(valtype)s);' % {'coltype':column.type.key.to_const_c_type(prefix), 'valtype':column.type.value.to_const_c_type(prefix)}) | |
375 | print('void %(s)s_update_%(c)s_delkey(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') | |
376 | print('%(coltype)s);' % {'coltype':column.type.key.to_const_c_type(prefix)}) | |
f1ab6e06 | 377 | if column.type.is_set(): |
d34a1cc0 JW |
378 | print('void %(s)s_update_%(c)s_addvalue(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') |
379 | print('%(valtype)s);' % {'valtype':column.type.key.to_const_c_type(prefix)}) | |
380 | print('void %(s)s_update_%(c)s_delvalue(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ') | |
381 | print('%(valtype)s);' % {'valtype':column.type.key.to_const_c_type(prefix)}) | |
16ebb90e | 382 | |
d34a1cc0 | 383 | print('void %(s)s_add_clause_%(c)s(struct ovsdb_idl_condition *, enum ovsdb_function function,' % {'s': structName, 'c': columnName}, end=' ') |
16ebb90e LS |
384 | if column.type.is_smap(): |
385 | args = ['const struct smap *'] | |
386 | else: | |
387 | comment, members = cMembers(prefix, tableName, columnName, | |
4bb7f568 | 388 | column, True, refTable=False) |
16ebb90e | 389 | args = ['%(type)s%(name)s' % member for member in members] |
d34a1cc0 | 390 | print('%s);' % ', '.join(args)) |
16ebb90e | 391 | |
d34a1cc0 | 392 | print('void %(s)s_set_condition(struct ovsdb_idl *, struct ovsdb_idl_condition *);' % {'s': structName}) |
16ebb90e | 393 | |
d34a1cc0 | 394 | print("") |
f67f1354 | 395 | |
979821c0 | 396 | # Table indexes. |
d14e007c | 397 | print("struct %(s)s *%(s)s_index_init_row(struct ovsdb_idl_index *);" % {'s': structName}) |
0a8606ee | 398 | |
81068700 | 399 | for columnName, column in sorted(table.columns.items()): |
0a8606ee LR |
400 | print('void %(s)s_index_set_%(c)s(const struct %(s)s *,' % {'s': structName, 'c': columnName}) |
401 | if column.type.is_smap(): | |
402 | args = ['const struct smap *'] | |
403 | else: | |
404 | comment, members = cMembers(prefix, tableName, columnName, | |
405 | column, True) | |
406 | args = ['%(type)s%(name)s' % member for member in members] | |
407 | print('%s);' % ', '.join(args)) | |
408 | ||
409 | ||
32d37ce8 | 410 | printEnum("%stable_id" % prefix.lower(), ["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()]) |
d34a1cc0 | 411 | print("") |
979821c0 | 412 | for tableName in schema.tables: |
d34a1cc0 | 413 | print("#define %(p)stable_%(t)s (%(p)stable_classes[%(P)sTABLE_%(T)s])" % { |
979821c0 BP |
414 | 'p': prefix, |
415 | 'P': prefix.upper(), | |
416 | 't': tableName.lower(), | |
d34a1cc0 JW |
417 | 'T': tableName.upper()}) |
418 | print("\nextern struct ovsdb_idl_table_class %stable_classes[%sN_TABLES];" % (prefix, prefix.upper())) | |
979821c0 | 419 | |
d34a1cc0 | 420 | print("\nextern struct ovsdb_idl_class %sidl_class;" % prefix) |
87412f02 | 421 | |
d34a1cc0 | 422 | print("\nconst char * %sget_db_version(void);" % prefix) |
9131abe2 YHW |
423 | print(''' |
424 | #ifdef __cplusplus | |
425 | } | |
426 | #endif''') | |
d34a1cc0 | 427 | print("\n#endif /* %(prefix)sIDL_HEADER */" % {'prefix': prefix.upper()}) |
c3bb4bd7 | 428 | |
fa37affa | 429 | |
32d37ce8 | 430 | def printEnum(type, members): |
c3bb4bd7 BP |
431 | if len(members) == 0: |
432 | return | |
433 | ||
d34a1cc0 | 434 | print("\nenum %s {" % type) |
c3bb4bd7 | 435 | for member in members[:-1]: |
d34a1cc0 JW |
436 | print(" %s," % member) |
437 | print(" %s" % members[-1]) | |
438 | print("};") | |
c3bb4bd7 | 439 | |
00732bf5 BP |
440 | def printCIDLSource(schemaFile): |
441 | schema = parseSchema(schemaFile) | |
adb4185d | 442 | replace_cplusplus_keyword(schema) |
c3bb4bd7 | 443 | prefix = schema.idlPrefix |
d34a1cc0 | 444 | print('''\ |
c3bb4bd7 BP |
445 | /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */ |
446 | ||
447 | #include <config.h> | |
0ea866bb | 448 | #include %(header)s |
c3bb4bd7 | 449 | #include <limits.h> |
558103f0 | 450 | #include "ovs-thread.h" |
bd76d25d BP |
451 | #include "ovsdb-data.h" |
452 | #include "ovsdb-error.h" | |
cb22974d | 453 | #include "util.h" |
bd76d25d | 454 | |
0ea866bb BP |
455 | %(cDecls)s |
456 | ||
457 | ''' % {'header': schema.idlHeader, | |
458 | 'cDecls': schema.cDecls}) | |
c3bb4bd7 | 459 | |
66095e15 | 460 | # Cast functions. |
4ab66562 | 461 | for tableName, table in sorted(schema.tables.items()): |
66095e15 | 462 | structName = "%s%s" % (prefix, tableName.lower()) |
d34a1cc0 | 463 | print(''' |
66095e15 | 464 | static struct %(s)s * |
979821c0 | 465 | %(s)s_cast(const struct ovsdb_idl_row *row) |
66095e15 BP |
466 | { |
467 | return row ? CONTAINER_OF(row, struct %(s)s, header_) : NULL; | |
468 | }\ | |
d34a1cc0 | 469 | ''' % {'s': structName}) |
66095e15 BP |
470 | |
471 | ||
4ab66562 | 472 | for tableName, table in sorted(schema.tables.items()): |
c3bb4bd7 | 473 | structName = "%s%s" % (prefix, tableName.lower()) |
d34a1cc0 JW |
474 | print("\f") |
475 | print("/* %s table. */" % (tableName)) | |
c3bb4bd7 | 476 | |
0eb1e37c BP |
477 | print(''' |
478 | const struct %(s)s_table * | |
479 | %(s)s_table_get(const struct ovsdb_idl *idl) | |
480 | { | |
481 | return (const struct %(s)s_table *) idl; | |
482 | } | |
483 | ||
484 | const struct %(s)s * | |
485 | %(s)s_table_first(const struct %(s)s_table *table) | |
486 | { | |
487 | const struct ovsdb_idl *idl = (const struct ovsdb_idl *) table; | |
488 | return %(s)s_first(idl); | |
489 | } | |
4b282ad9 HZ |
490 | |
491 | ||
492 | const struct %(s)s * | |
493 | %(s)s_table_track_get_first(const struct %(s)s_table *table) | |
494 | { | |
495 | const struct ovsdb_idl *idl = (const struct ovsdb_idl *) table; | |
496 | return %(s)s_track_get_first(idl); | |
497 | } | |
0eb1e37c BP |
498 | ''' % {'s': structName}) |
499 | ||
979821c0 | 500 | # Parse functions. |
e0b1744f | 501 | for columnName, column in sorted_columns(table): |
01928c96 BP |
502 | if 'parse' in column.extensions: |
503 | print(''' | |
504 | static void | |
505 | %(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum OVS_UNUSED) | |
506 | { | |
507 | struct %(s)s *row = %(s)s_cast(row_);\ | |
508 | ''' % {'s': structName, 'c': columnName}) | |
509 | print(column.extensions["parse"]) | |
510 | print("}") | |
511 | continue | |
512 | if column.extensions.get('synthetic'): | |
513 | # Synthetic columns aren't parsed from a datum. | |
514 | unused = " OVS_UNUSED" | |
515 | else: | |
516 | unused = "" | |
d34a1cc0 | 517 | print(''' |
c3bb4bd7 | 518 | static void |
979821c0 | 519 | %(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum) |
c3bb4bd7 | 520 | { |
979821c0 | 521 | struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName, |
d34a1cc0 | 522 | 'c': columnName}) |
c3bb4bd7 | 523 | type = column.type |
01928c96 BP |
524 | if 'parse' in column.extensions: |
525 | print(column.extensions["parse"]) | |
526 | print("}") | |
527 | continue | |
c3bb4bd7 BP |
528 | if type.value: |
529 | keyVar = "row->key_%s" % columnName | |
530 | valueVar = "row->value_%s" % columnName | |
531 | else: | |
532 | keyVar = "row->%s" % columnName | |
533 | valueVar = None | |
534 | ||
a699f614 | 535 | if type.is_smap(): |
d34a1cc0 JW |
536 | print(" smap_init(&row->%s);" % columnName) |
537 | print(" for (size_t i = 0; i < datum->n; i++) {") | |
538 | print(" smap_add(&row->%s," % columnName) | |
539 | print(" datum->keys[i].string,") | |
540 | print(" datum->values[i].string);") | |
541 | print(" }") | |
a699f614 | 542 | elif (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer(): |
d34a1cc0 JW |
543 | print("") |
544 | print(" if (datum->n >= 1) {") | |
99155935 | 545 | if not type.key.ref_table: |
d34a1cc0 | 546 | print(" %s = datum->keys[0].%s;" % (keyVar, type.key.type.to_string())) |
c3bb4bd7 | 547 | else: |
d34a1cc0 | 548 | 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 |
549 | |
550 | if valueVar: | |
ae661470 | 551 | if not type.value.ref_table: |
d34a1cc0 | 552 | print(" %s = datum->values[0].%s;" % (valueVar, type.value.type.to_string())) |
c3bb4bd7 | 553 | else: |
d34a1cc0 JW |
554 | 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())) |
555 | print(" } else {") | |
556 | print(" %s" % type.key.initCDefault(keyVar, type.n_min == 0)) | |
979821c0 | 557 | if valueVar: |
d34a1cc0 JW |
558 | print(" %s" % type.value.initCDefault(valueVar, type.n_min == 0)) |
559 | print(" }") | |
c3bb4bd7 | 560 | else: |
fa145f1a | 561 | if type.n_max != sys.maxsize: |
d34a1cc0 | 562 | print(" size_t n = MIN(%d, datum->n);" % type.n_max) |
979821c0 | 563 | nMax = "n" |
c3bb4bd7 BP |
564 | else: |
565 | nMax = "datum->n" | |
d34a1cc0 | 566 | print(" %s = NULL;" % keyVar) |
979821c0 | 567 | if valueVar: |
d34a1cc0 JW |
568 | print(" %s = NULL;" % valueVar) |
569 | print(" row->n_%s = 0;" % columnName) | |
570 | print(" for (size_t i = 0; i < %s; i++) {" % nMax) | |
99155935 | 571 | if type.key.ref_table: |
d34a1cc0 | 572 | print("""\ |
9478f52f | 573 | struct %s%s *keyRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->keys[i].uuid)); |
cff5afcf BP |
574 | if (!keyRow) { |
575 | continue; | |
576 | }\ | |
d34a1cc0 | 577 | """ % (prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower())) |
c3bb4bd7 | 578 | keySrc = "keyRow" |
c3bb4bd7 | 579 | else: |
99155935 BP |
580 | keySrc = "datum->keys[i].%s" % type.key.type.to_string() |
581 | if type.value and type.value.ref_table: | |
d34a1cc0 | 582 | print("""\ |
9478f52f | 583 | struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[i].uuid)); |
cff5afcf BP |
584 | if (!valueRow) { |
585 | continue; | |
586 | }\ | |
d34a1cc0 | 587 | """ % (prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower())) |
c3bb4bd7 | 588 | valueSrc = "valueRow" |
c3bb4bd7 | 589 | elif valueVar: |
99155935 | 590 | valueSrc = "datum->values[i].%s" % type.value.type.to_string() |
d34a1cc0 | 591 | print(" if (!row->n_%s) {" % (columnName)) |
1bf2c909 | 592 | |
d34a1cc0 JW |
593 | print(" %s = xmalloc(%s * sizeof *%s);" % ( |
594 | keyVar, nMax, keyVar)) | |
c3bb4bd7 | 595 | if valueVar: |
d34a1cc0 JW |
596 | print(" %s = xmalloc(%s * sizeof *%s);" % ( |
597 | valueVar, nMax, valueVar)) | |
598 | print(" }") | |
599 | print(" %s[row->n_%s] = %s;" % (keyVar, columnName, keySrc)) | |
c3bb4bd7 | 600 | if valueVar: |
d34a1cc0 JW |
601 | print(" %s[row->n_%s] = %s;" % (valueVar, columnName, valueSrc)) |
602 | print(" row->n_%s++;" % columnName) | |
603 | print(" }") | |
604 | print("}") | |
c3bb4bd7 | 605 | |
979821c0 | 606 | # Unparse functions. |
e0b1744f | 607 | for columnName, column in sorted_columns(table): |
c3bb4bd7 | 608 | type = column.type |
01928c96 | 609 | 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 | 610 | print(''' |
c3bb4bd7 | 611 | static void |
979821c0 | 612 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row_) |
c3bb4bd7 | 613 | { |
74e98efd | 614 | struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName, |
d34a1cc0 | 615 | 'c': columnName}) |
01928c96 BP |
616 | if 'unparse' in column.extensions: |
617 | print(column.extensions["unparse"]) | |
618 | elif type.is_smap(): | |
d34a1cc0 | 619 | print(" smap_destroy(&row->%s);" % columnName) |
c3bb4bd7 | 620 | else: |
a699f614 EJ |
621 | if type.value: |
622 | keyVar = "row->key_%s" % columnName | |
623 | valueVar = "row->value_%s" % columnName | |
624 | else: | |
625 | keyVar = "row->%s" % columnName | |
626 | valueVar = None | |
d34a1cc0 | 627 | print(" free(%s);" % keyVar) |
a699f614 | 628 | if valueVar: |
d34a1cc0 JW |
629 | print(" free(%s);" % valueVar) |
630 | print('}') | |
979821c0 | 631 | else: |
d34a1cc0 | 632 | print(''' |
c3bb4bd7 | 633 | static void |
c69ee87c | 634 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row OVS_UNUSED) |
979821c0 BP |
635 | { |
636 | /* Nothing to do. */ | |
d34a1cc0 | 637 | }''' % {'s': structName, 'c': columnName}) |
c5c7c7c5 | 638 | |
a699f614 | 639 | # Generic Row Initialization function. |
d34a1cc0 | 640 | print(""" |
a699f614 EJ |
641 | static void |
642 | %(s)s_init__(struct ovsdb_idl_row *row) | |
643 | { | |
644 | %(s)s_init(%(s)s_cast(row)); | |
d34a1cc0 | 645 | }""" % {'s': structName}) |
a699f614 EJ |
646 | |
647 | # Row Initialization function. | |
d34a1cc0 | 648 | print(""" |
d797877d | 649 | /* Clears the contents of 'row' in table "%(t)s". */ |
a699f614 EJ |
650 | void |
651 | %(s)s_init(struct %(s)s *row) | |
652 | { | |
d34a1cc0 | 653 | memset(row, 0, sizeof *row); """ % {'s': structName, 't': tableName}) |
e0b1744f | 654 | for columnName, column in sorted_columns(table): |
a699f614 | 655 | if column.type.is_smap(): |
d34a1cc0 | 656 | print(" smap_init(&row->%s);" % columnName) |
5a98d741 BP |
657 | elif (column.type.n_min == 1 and |
658 | column.type.n_max == 1 and | |
659 | column.type.key.type == ovs.db.types.StringType and | |
660 | not column.type.value): | |
d34a1cc0 JW |
661 | print(" row->%s = \"\";" % columnName) |
662 | print("}") | |
a699f614 | 663 | |
c3bb4bd7 | 664 | # First, next functions. |
d34a1cc0 | 665 | print(''' |
d797877d JP |
666 | /* Searches table "%(t)s" in 'idl' for a row with UUID 'uuid'. Returns |
667 | * a pointer to the row if there is one, otherwise a null pointer. */ | |
8c6cf7b8 BP |
668 | const struct %(s)s * |
669 | %(s)s_get_for_uuid(const struct ovsdb_idl *idl, const struct uuid *uuid) | |
670 | { | |
9478f52f | 671 | return %(s)s_cast(ovsdb_idl_get_row_for_uuid(idl, &%(p)stable_%(tl)s, uuid)); |
8c6cf7b8 BP |
672 | } |
673 | ||
4b282ad9 HZ |
674 | /* Searches table "%(t)s" for a row with UUID 'uuid'. Returns |
675 | * a pointer to the row if there is one, otherwise a null pointer. */ | |
676 | const struct %(s)s * | |
677 | %(s)s_table_get_for_uuid(const struct %(s)s_table *table, const struct uuid *uuid) | |
678 | { | |
679 | const struct ovsdb_idl *idl = (const struct ovsdb_idl *) table; | |
680 | return %(s)s_get_for_uuid(idl, uuid); | |
681 | } | |
682 | ||
d797877d JP |
683 | /* Returns a row in table "%(t)s" in 'idl', or a null pointer if that |
684 | * table is empty. | |
685 | * | |
686 | * Database tables are internally maintained as hash tables, so adding or | |
687 | * removing rows while traversing the same table can cause some rows to be | |
688 | * visited twice or not at apply. */ | |
66095e15 BP |
689 | const struct %(s)s * |
690 | %(s)s_first(const struct ovsdb_idl *idl) | |
c3bb4bd7 | 691 | { |
9478f52f | 692 | return %(s)s_cast(ovsdb_idl_first_row(idl, &%(p)stable_%(tl)s)); |
c3bb4bd7 BP |
693 | } |
694 | ||
d797877d JP |
695 | /* Returns a row following 'row' within its table, or a null pointer if 'row' |
696 | * is the last row in its table. */ | |
66095e15 BP |
697 | const struct %(s)s * |
698 | %(s)s_next(const struct %(s)s *row) | |
c3bb4bd7 | 699 | { |
66095e15 | 700 | return %(s)s_cast(ovsdb_idl_next_row(&row->header_)); |
932104f4 SA |
701 | } |
702 | ||
703 | unsigned int %(s)s_get_seqno(const struct ovsdb_idl *idl) | |
704 | { | |
9478f52f | 705 | return ovsdb_idl_table_get_seqno(idl, &%(p)stable_%(tl)s); |
932104f4 SA |
706 | } |
707 | ||
708 | unsigned int %(s)s_row_get_seqno(const struct %(s)s *row, enum ovsdb_idl_change change) | |
709 | { | |
710 | return ovsdb_idl_row_get_seqno(&row->header_, change); | |
711 | } | |
712 | ||
713 | const struct %(s)s * | |
714 | %(s)s_track_get_first(const struct ovsdb_idl *idl) | |
715 | { | |
9478f52f | 716 | return %(s)s_cast(ovsdb_idl_track_get_first(idl, &%(p)stable_%(tl)s)); |
932104f4 SA |
717 | } |
718 | ||
719 | const struct %(s)s | |
720 | *%(s)s_track_get_next(const struct %(s)s *row) | |
721 | { | |
722 | return %(s)s_cast(ovsdb_idl_track_get_next(&row->header_)); | |
475281c0 BP |
723 | }''' % {'s': structName, |
724 | 'p': prefix, | |
725 | 'P': prefix.upper(), | |
d797877d | 726 | 't': tableName, |
9478f52f | 727 | 'tl': tableName.lower(), |
d34a1cc0 | 728 | 'T': tableName.upper()}) |
475281c0 | 729 | |
d34a1cc0 | 730 | print(''' |
932104f4 | 731 | |
d797877d JP |
732 | /* Deletes 'row' from table "%(t)s". 'row' may be freed, so it must not be |
733 | * accessed afterward. | |
734 | * | |
735 | * The caller must have started a transaction with ovsdb_idl_txn_create(). */ | |
475281c0 | 736 | void |
9e336f49 | 737 | %(s)s_delete(const struct %(s)s *row) |
475281c0 | 738 | { |
475281c0 BP |
739 | ovsdb_idl_txn_delete(&row->header_); |
740 | } | |
741 | ||
d797877d JP |
742 | /* Inserts and returns a new row in the table "%(t)s" in the database |
743 | * with open transaction 'txn'. | |
744 | * | |
745 | * The new row is assigned a randomly generated provisional UUID. | |
746 | * ovsdb-server will assign a different UUID when 'txn' is committed, | |
747 | * but the IDL will replace any uses of the provisional UUID in the | |
748 | * data to be to be committed by the UUID assigned by ovsdb-server. */ | |
475281c0 BP |
749 | struct %(s)s * |
750 | %(s)s_insert(struct ovsdb_idl_txn *txn) | |
751 | { | |
9478f52f | 752 | return %(s)s_cast(ovsdb_idl_txn_insert(txn, &%(p)stable_%(tl)s, NULL)); |
32d37ce8 SA |
753 | } |
754 | ||
755 | bool | |
756 | %(s)s_is_updated(const struct %(s)s *row, enum %(s)s_column_id column) | |
757 | { | |
758 | return ovsdb_idl_track_is_updated(&row->header_, &%(s)s_columns[column]); | |
d797877d JP |
759 | }''' % {'s': structName, |
760 | 'p': prefix, | |
761 | 'P': prefix.upper(), | |
762 | 't': tableName, | |
9478f52f | 763 | 'tl': tableName.lower(), |
d34a1cc0 | 764 | 'T': tableName.upper()}) |
475281c0 BP |
765 | |
766 | # Verify functions. | |
e0b1744f | 767 | for columnName, column in sorted_columns(table): |
01928c96 BP |
768 | if column.extensions.get('synthetic'): |
769 | continue | |
d34a1cc0 | 770 | print(''' |
d797877d JP |
771 | /* Causes the original contents of column "%(c)s" in 'row' to be |
772 | * verified as a prerequisite to completing the transaction. That is, if | |
773 | * "%(c)s" in 'row' changed (or if 'row' was deleted) between the | |
774 | * time that the IDL originally read its contents and the time that the | |
b17c8228 | 775 | * transaction aborts and ovsdb_idl_txn_commit() returns TXN_TRY_AGAIN. |
d797877d JP |
776 | * |
777 | * The intention is that, to ensure that no transaction commits based on dirty | |
778 | * reads, an application should call this function any time "%(c)s" is | |
779 | * read as part of a read-modify-write operation. | |
780 | * | |
781 | * In some cases this function reduces to a no-op, because the current value | |
782 | * of "%(c)s" is already known: | |
783 | * | |
784 | * - If 'row' is a row created by the current transaction (returned by | |
785 | * %(s)s_insert()). | |
786 | * | |
787 | * - If "%(c)s" has already been modified (with | |
788 | * %(s)s_set_%(c)s()) within the current transaction. | |
789 | * | |
790 | * Because of the latter property, always call this function *before* | |
791 | * %(s)s_set_%(c)s() for a given read-modify-write. | |
792 | * | |
793 | * The caller must have started a transaction with ovsdb_idl_txn_create(). */ | |
475281c0 BP |
794 | void |
795 | %(s)s_verify_%(c)s(const struct %(s)s *row) | |
796 | { | |
1f2d2557 | 797 | ovsdb_idl_txn_verify(&row->header_, &%(s)s_col_%(c)s); |
475281c0 BP |
798 | }''' % {'s': structName, |
799 | 'S': structName.upper(), | |
800 | 'c': columnName, | |
d34a1cc0 | 801 | 'C': columnName.upper()}) |
475281c0 | 802 | |
a6ec9089 | 803 | # Get functions. |
e0b1744f | 804 | for columnName, column in sorted_columns(table): |
01928c96 BP |
805 | if column.extensions.get('synthetic'): |
806 | continue | |
a6ec9089 BP |
807 | if column.type.value: |
808 | valueParam = ',\n\tenum ovsdb_atomic_type value_type OVS_UNUSED' | |
cb22974d | 809 | valueType = '\n ovs_assert(value_type == %s);' % column.type.value.toAtomicType() |
a6ec9089 BP |
810 | valueComment = "\n * 'value_type' must be %s." % column.type.value.toAtomicType() |
811 | else: | |
812 | valueParam = '' | |
813 | valueType = '' | |
814 | valueComment = '' | |
d34a1cc0 | 815 | print(""" |
d797877d JP |
816 | /* Returns the "%(c)s" column's value from the "%(t)s" table in 'row' |
817 | * as a struct ovsdb_datum. This is useful occasionally: for example, | |
818 | * ovsdb_datum_find_key() is an easier and more efficient way to search | |
819 | * for a given key than implementing the same operation on the "cooked" | |
820 | * form in 'row'. | |
a6ec9089 BP |
821 | * |
822 | * 'key_type' must be %(kt)s.%(vc)s | |
823 | * (This helps to avoid silent bugs if someone changes %(c)s's | |
824 | * type without updating the caller.) | |
825 | * | |
826 | * The caller must not modify or free the returned value. | |
827 | * | |
828 | * Various kinds of changes can invalidate the returned value: modifying | |
829 | * 'column' within 'row', deleting 'row', or completing an ongoing transaction. | |
830 | * If the returned value is needed for a long time, it is best to make a copy | |
d797877d JP |
831 | * of it with ovsdb_datum_clone(). |
832 | * | |
833 | * This function is rarely useful, since it is easier to access the value | |
834 | * directly through the "%(c)s" member in %(s)s. */ | |
a6ec9089 BP |
835 | const struct ovsdb_datum * |
836 | %(s)s_get_%(c)s(const struct %(s)s *row, | |
837 | \tenum ovsdb_atomic_type key_type OVS_UNUSED%(v)s) | |
838 | { | |
cb22974d | 839 | ovs_assert(key_type == %(kt)s);%(vt)s |
a6ec9089 | 840 | return ovsdb_idl_read(&row->header_, &%(s)s_col_%(c)s); |
d797877d | 841 | }""" % {'t': tableName, 's': structName, 'c': columnName, |
a6ec9089 | 842 | 'kt': column.type.key.toAtomicType(), |
d34a1cc0 | 843 | 'v': valueParam, 'vt': valueType, 'vc': valueComment}) |
a6ec9089 | 844 | |
475281c0 | 845 | # Set functions. |
e0b1744f | 846 | for columnName, column in sorted_columns(table): |
01928c96 BP |
847 | if column.extensions.get('synthetic'): |
848 | continue | |
475281c0 | 849 | type = column.type |
a699f614 | 850 | |
7cc398cb JP |
851 | comment, members = cMembers(prefix, tableName, columnName, |
852 | column, True) | |
853 | ||
a699f614 | 854 | if type.is_smap(): |
d34a1cc0 JW |
855 | print(comment) |
856 | print("""void | |
4946b41d | 857 | %(s)s_set_%(c)s(const struct %(s)s *row, const struct smap *%(c)s) |
a699f614 EJ |
858 | { |
859 | struct ovsdb_datum datum; | |
860 | ||
4946b41d | 861 | if (%(c)s) { |
9b03e59d | 862 | ovsdb_datum_from_smap(&datum, %(c)s); |
a699f614 EJ |
863 | } else { |
864 | ovsdb_datum_init_empty(&datum); | |
865 | } | |
866 | ovsdb_idl_txn_write(&row->header_, | |
1f2d2557 | 867 | &%(s)s_col_%(c)s, |
a699f614 EJ |
868 | &datum); |
869 | } | |
7cc398cb JP |
870 | """ % {'t': tableName, |
871 | 's': structName, | |
a699f614 EJ |
872 | 'S': structName.upper(), |
873 | 'c': columnName, | |
d34a1cc0 | 874 | 'C': columnName.upper()}) |
a699f614 EJ |
875 | continue |
876 | ||
475281c0 BP |
877 | keyVar = members[0]['name'] |
878 | nVar = None | |
879 | valueVar = None | |
880 | if type.value: | |
881 | valueVar = members[1]['name'] | |
882 | if len(members) > 2: | |
883 | nVar = members[2]['name'] | |
884 | else: | |
885 | if len(members) > 1: | |
886 | nVar = members[1]['name'] | |
7cc398cb | 887 | |
d34a1cc0 JW |
888 | print(comment) |
889 | print("""\ | |
cad9a996 BP |
890 | void |
891 | %(s)s_set_%(c)s(const struct %(s)s *row, %(args)s) | |
892 | { | |
cad9a996 | 893 | struct ovsdb_datum datum;""" % {'s': structName, |
74e98efd BP |
894 | 'c': columnName, |
895 | 'args': ', '.join(['%(type)s%(name)s' | |
d34a1cc0 | 896 | % m for m in members])}) |
99155935 | 897 | if type.n_min == 1 and type.n_max == 1: |
d34a1cc0 | 898 | print(" union ovsdb_atom key;") |
fe19569a | 899 | if type.value: |
d34a1cc0 JW |
900 | print(" union ovsdb_atom value;") |
901 | print("") | |
902 | print(" datum.n = 1;") | |
903 | print(" datum.keys = &key;") | |
904 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)) | |
475281c0 | 905 | if type.value: |
d34a1cc0 JW |
906 | print(" datum.values = &value;") |
907 | print(" "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar)) | |
475281c0 | 908 | else: |
d34a1cc0 | 909 | print(" datum.values = NULL;") |
fe19569a | 910 | txn_write_func = "ovsdb_idl_txn_write_clone" |
99155935 | 911 | elif type.is_optional_pointer(): |
d34a1cc0 JW |
912 | print(" union ovsdb_atom key;") |
913 | print("") | |
914 | print(" if (%s) {" % keyVar) | |
915 | print(" datum.n = 1;") | |
916 | print(" datum.keys = &key;") | |
917 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)) | |
918 | print(" } else {") | |
919 | print(" datum.n = 0;") | |
920 | print(" datum.keys = NULL;") | |
921 | print(" }") | |
922 | print(" datum.values = NULL;") | |
fe19569a BP |
923 | txn_write_func = "ovsdb_idl_txn_write_clone" |
924 | elif type.n_max == 1: | |
d34a1cc0 JW |
925 | print(" union ovsdb_atom key;") |
926 | print("") | |
927 | print(" if (%s) {" % nVar) | |
928 | print(" datum.n = 1;") | |
929 | print(" datum.keys = &key;") | |
930 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar)) | |
931 | print(" } else {") | |
932 | print(" datum.n = 0;") | |
933 | print(" datum.keys = NULL;") | |
934 | print(" }") | |
935 | print(" datum.values = NULL;") | |
fe19569a | 936 | txn_write_func = "ovsdb_idl_txn_write_clone" |
475281c0 | 937 | else: |
d34a1cc0 JW |
938 | print("") |
939 | print(" datum.n = %s;" % nVar) | |
940 | print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)) | |
475281c0 | 941 | if type.value: |
d34a1cc0 | 942 | print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar) |
475281c0 | 943 | else: |
d34a1cc0 JW |
944 | print(" datum.values = NULL;") |
945 | print(" for (size_t i = 0; i < %s; i++) {" % nVar) | |
946 | print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)) | |
475281c0 | 947 | if type.value: |
d34a1cc0 JW |
948 | print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)) |
949 | print(" }") | |
a1ec42a3 BP |
950 | if type.value: |
951 | valueType = type.value.toAtomicType() | |
952 | else: | |
953 | valueType = "OVSDB_TYPE_VOID" | |
fe19569a | 954 | txn_write_func = "ovsdb_idl_txn_write" |
d34a1cc0 | 955 | print(" %(f)s(&row->header_, &%(s)s_col_%(c)s, &datum);" \ |
fe19569a BP |
956 | % {'f': txn_write_func, |
957 | 's': structName, | |
475281c0 | 958 | 'S': structName.upper(), |
d34a1cc0 JW |
959 | 'c': columnName}) |
960 | print("}") | |
010fe7ae | 961 | # Update/Delete of partial map column functions |
e0b1744f | 962 | for columnName, column in sorted_columns(table): |
01928c96 BP |
963 | if column.extensions.get('synthetic'): |
964 | continue | |
010fe7ae EA |
965 | type = column.type |
966 | if type.is_map(): | |
d34a1cc0 | 967 | print(''' |
010fe7ae EA |
968 | /* Sets an element of the "%(c)s" map column from the "%(t)s" table in 'row' |
969 | * to 'new_value' given the key value 'new_key'. | |
970 | * | |
971 | */ | |
972 | void | |
973 | %(s)s_update_%(c)s_setkey(const struct %(s)s *row, %(coltype)snew_key, %(valtype)snew_value) | |
974 | { | |
975 | struct ovsdb_datum *datum; | |
976 | ||
010fe7ae EA |
977 | datum = xmalloc(sizeof *datum); |
978 | datum->n = 1; | |
979 | datum->keys = xmalloc(datum->n * sizeof *datum->keys); | |
980 | datum->values = xmalloc(datum->n * sizeof *datum->values); | |
05ba459f BP |
981 | ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), |
982 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(), | |
d34a1cc0 | 983 | 'C': columnName.upper(), 't': tableName}) |
010fe7ae | 984 | |
d34a1cc0 JW |
985 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "new_key")) |
986 | print(" "+ type.value.copyCValue("datum->values[0].%s" % type.value.type.to_string(), "new_value")) | |
987 | print(''' | |
010fe7ae | 988 | ovsdb_idl_txn_write_partial_map(&row->header_, |
1f2d2557 | 989 | &%(s)s_col_%(c)s, |
010fe7ae | 990 | datum); |
1f2d2557 | 991 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 JW |
992 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper()}) |
993 | print(''' | |
010fe7ae EA |
994 | /* Deletes an element of the "%(c)s" map column from the "%(t)s" table in 'row' |
995 | * given the key value 'delete_key'. | |
996 | * | |
997 | */ | |
998 | void | |
999 | %(s)s_update_%(c)s_delkey(const struct %(s)s *row, %(coltype)sdelete_key) | |
1000 | { | |
1001 | struct ovsdb_datum *datum; | |
1002 | ||
010fe7ae EA |
1003 | datum = xmalloc(sizeof *datum); |
1004 | datum->n = 1; | |
1005 | datum->keys = xmalloc(datum->n * sizeof *datum->keys); | |
1006 | datum->values = NULL; | |
05ba459f BP |
1007 | ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), |
1008 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(), | |
d34a1cc0 | 1009 | 'C': columnName.upper(), 't': tableName}) |
010fe7ae | 1010 | |
d34a1cc0 JW |
1011 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_key")) |
1012 | print(''' | |
010fe7ae | 1013 | ovsdb_idl_txn_delete_partial_map(&row->header_, |
1f2d2557 | 1014 | &%(s)s_col_%(c)s, |
010fe7ae | 1015 | datum); |
1f2d2557 | 1016 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 | 1017 | 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper()}) |
010fe7ae | 1018 | # End Update/Delete of partial maps |
f1ab6e06 RM |
1019 | # Update/Delete of partial set column functions |
1020 | if type.is_set(): | |
d34a1cc0 | 1021 | print(''' |
f1ab6e06 RM |
1022 | /* Adds the value 'new_value' to the "%(c)s" set column from the "%(t)s" table |
1023 | * in 'row'. | |
1024 | * | |
1025 | */ | |
1026 | void | |
1027 | %(s)s_update_%(c)s_addvalue(const struct %(s)s *row, %(valtype)snew_value) | |
1028 | { | |
1029 | struct ovsdb_datum *datum; | |
1030 | ||
f1ab6e06 RM |
1031 | datum = xmalloc(sizeof *datum); |
1032 | datum->n = 1; | |
1033 | datum->keys = xmalloc(datum->n * sizeof *datum->values); | |
1034 | datum->values = NULL; | |
1035 | ''' % {'s': structName, 'c': columnName, | |
d34a1cc0 | 1036 | 'valtype':column.type.key.to_const_c_type(prefix), 't': tableName}) |
f1ab6e06 | 1037 | |
d34a1cc0 JW |
1038 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "new_value")) |
1039 | print(''' | |
f1ab6e06 | 1040 | ovsdb_idl_txn_write_partial_set(&row->header_, |
1f2d2557 | 1041 | &%(s)s_col_%(c)s, |
f1ab6e06 | 1042 | datum); |
1f2d2557 | 1043 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 JW |
1044 | 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper()}) |
1045 | print(''' | |
f1ab6e06 RM |
1046 | /* Deletes the value 'delete_value' from the "%(c)s" set column from the |
1047 | * "%(t)s" table in 'row'. | |
1048 | * | |
1049 | */ | |
1050 | void | |
1051 | %(s)s_update_%(c)s_delvalue(const struct %(s)s *row, %(valtype)sdelete_value) | |
1052 | { | |
1053 | struct ovsdb_datum *datum; | |
1054 | ||
f1ab6e06 RM |
1055 | datum = xmalloc(sizeof *datum); |
1056 | datum->n = 1; | |
1057 | datum->keys = xmalloc(datum->n * sizeof *datum->values); | |
1058 | datum->values = NULL; | |
05ba459f BP |
1059 | ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), |
1060 | 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper(), | |
d34a1cc0 | 1061 | 'C': columnName.upper(), 't': tableName}) |
f1ab6e06 | 1062 | |
d34a1cc0 JW |
1063 | print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_value")) |
1064 | print(''' | |
f1ab6e06 | 1065 | ovsdb_idl_txn_delete_partial_set(&row->header_, |
1f2d2557 | 1066 | &%(s)s_col_%(c)s, |
f1ab6e06 | 1067 | datum); |
1f2d2557 | 1068 | }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix), |
d34a1cc0 | 1069 | 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper()}) |
f1ab6e06 | 1070 | # End Update/Delete of partial set |
c3bb4bd7 | 1071 | |
16ebb90e | 1072 | # Add clause functions. |
e0b1744f | 1073 | for columnName, column in sorted_columns(table): |
01928c96 BP |
1074 | if column.extensions.get('synthetic'): |
1075 | continue | |
16ebb90e LS |
1076 | type = column.type |
1077 | ||
1078 | comment, members = cMembers(prefix, tableName, columnName, | |
4bb7f568 | 1079 | column, True, refTable=False) |
16ebb90e LS |
1080 | |
1081 | if type.is_smap(): | |
d34a1cc0 JW |
1082 | print(comment) |
1083 | print("""void | |
0164e367 | 1084 | %(s)s_add_clause_%(c)s(struct ovsdb_idl_condition *cond, enum ovsdb_function function, const struct smap *%(c)s) |
16ebb90e LS |
1085 | { |
1086 | struct ovsdb_datum datum; | |
1087 | ||
16ebb90e | 1088 | if (%(c)s) { |
9b03e59d | 1089 | ovsdb_datum_from_smap(&datum, %(c)s); |
16ebb90e LS |
1090 | } else { |
1091 | ovsdb_datum_init_empty(&datum); | |
1092 | } | |
1093 | ||
0164e367 | 1094 | ovsdb_idl_condition_add_clause(cond, |
16ebb90e | 1095 | function, |
1f2d2557 | 1096 | &%(s)s_col_%(c)s, |
16ebb90e | 1097 | &datum); |
a4e68acd BP |
1098 | |
1099 | ovsdb_datum_destroy(&datum, &%(s)s_col_%(c)s.type); | |
16ebb90e LS |
1100 | } |
1101 | """ % {'t': tableName, | |
9478f52f | 1102 | 'tl': tableName.lower(), |
16ebb90e LS |
1103 | 'T': tableName.upper(), |
1104 | 'p': prefix, | |
1105 | 'P': prefix.upper(), | |
1106 | 's': structName, | |
1107 | 'S': structName.upper(), | |
d34a1cc0 | 1108 | 'c': columnName}) |
16ebb90e LS |
1109 | continue |
1110 | ||
1111 | keyVar = members[0]['name'] | |
1112 | nVar = None | |
1113 | valueVar = None | |
1114 | if type.value: | |
1115 | valueVar = members[1]['name'] | |
1116 | if len(members) > 2: | |
1117 | nVar = members[2]['name'] | |
1118 | else: | |
1119 | if len(members) > 1: | |
1120 | nVar = members[1]['name'] | |
1121 | ||
d34a1cc0 JW |
1122 | print(comment) |
1123 | print('void') | |
1124 | print('%(s)s_add_clause_%(c)s(struct ovsdb_idl_condition *cond, enum ovsdb_function function, %(args)s)' % \ | |
16ebb90e | 1125 | {'s': structName, 'c': columnName, |
d34a1cc0 JW |
1126 | 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}) |
1127 | print("{") | |
1128 | print(" struct ovsdb_datum datum;") | |
a4e68acd | 1129 | free = [] |
16ebb90e | 1130 | if type.n_min == 1 and type.n_max == 1: |
d34a1cc0 | 1131 | print(" union ovsdb_atom key;") |
16ebb90e | 1132 | if type.value: |
d34a1cc0 JW |
1133 | print(" union ovsdb_atom value;") |
1134 | print("") | |
1135 | print(" datum.n = 1;") | |
1136 | print(" datum.keys = &key;") | |
1137 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar, refTable=False)) | |
16ebb90e | 1138 | if type.value: |
d34a1cc0 JW |
1139 | print(" datum.values = &value;") |
1140 | print(" "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar, refTable=False)) | |
16ebb90e | 1141 | else: |
d34a1cc0 | 1142 | print(" datum.values = NULL;") |
16ebb90e | 1143 | elif type.is_optional_pointer(): |
d34a1cc0 JW |
1144 | print(" union ovsdb_atom key;") |
1145 | print("") | |
1146 | print(" if (%s) {" % keyVar) | |
1147 | print(" datum.n = 1;") | |
1148 | print(" datum.keys = &key;") | |
1149 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar, refTable=False)) | |
1150 | print(" } else {") | |
1151 | print(" datum.n = 0;") | |
1152 | print(" datum.keys = NULL;") | |
1153 | print(" }") | |
1154 | print(" datum.values = NULL;") | |
16ebb90e | 1155 | elif type.n_max == 1: |
d34a1cc0 JW |
1156 | print(" union ovsdb_atom key;") |
1157 | print("") | |
1158 | print(" if (%s) {" % nVar) | |
1159 | print(" datum.n = 1;") | |
1160 | print(" datum.keys = &key;") | |
1161 | print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar, refTable=False)) | |
1162 | print(" } else {") | |
1163 | print(" datum.n = 0;") | |
1164 | print(" datum.keys = NULL;") | |
1165 | print(" }") | |
1166 | print(" datum.values = NULL;") | |
16ebb90e | 1167 | else: |
d34a1cc0 JW |
1168 | print(" datum.n = %s;" % nVar) |
1169 | print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)) | |
a4e68acd | 1170 | free += ['datum.keys'] |
16ebb90e | 1171 | if type.value: |
d34a1cc0 | 1172 | print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar) |
a4e68acd | 1173 | free += ['datum.values'] |
16ebb90e | 1174 | else: |
d34a1cc0 JW |
1175 | print(" datum.values = NULL;") |
1176 | print(" for (size_t i = 0; i < %s; i++) {" % nVar) | |
1177 | print(" " + type.key.assign_c_value_casting_away_const("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar, refTable=False)) | |
16ebb90e | 1178 | if type.value: |
d34a1cc0 JW |
1179 | print(" " + type.value.assign_c_value_casting_away_const("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar, refTable=False)) |
1180 | print(" }") | |
16ebb90e LS |
1181 | if type.value: |
1182 | valueType = type.value.toAtomicType() | |
1183 | else: | |
1184 | valueType = "OVSDB_TYPE_VOID" | |
d34a1cc0 JW |
1185 | print(" ovsdb_datum_sort_unique(&datum, %s, %s);" % ( |
1186 | type.key.toAtomicType(), valueType)) | |
16ebb90e | 1187 | |
d34a1cc0 | 1188 | print(""" ovsdb_idl_condition_add_clause(cond, |
16ebb90e | 1189 | function, |
1f2d2557 | 1190 | &%(s)s_col_%(c)s, |
a4e68acd | 1191 | &datum);\ |
9478f52f | 1192 | """ % {'tl': tableName.lower(), |
16ebb90e LS |
1193 | 'T': tableName.upper(), |
1194 | 'p': prefix, | |
1195 | 'P': prefix.upper(), | |
1196 | 's': structName, | |
1197 | 'S': structName.upper(), | |
d34a1cc0 | 1198 | 'c': columnName}) |
a4e68acd | 1199 | for var in free: |
d34a1cc0 JW |
1200 | print(" free(%s);" % var) |
1201 | print("}") | |
16ebb90e | 1202 | |
0a8606ee LR |
1203 | # Index table related functions |
1204 | print(""" | |
1205 | /* Destroy 'row' of kind "%(t)s". The row must have been | |
1206 | * created with ovsdb_idl_index_init_row. | |
1207 | */ | |
1208 | void | |
1209 | %(s)s_index_destroy_row(const struct %(s)s *row) | |
1210 | { | |
d14e007c | 1211 | ovsdb_idl_index_destroy_row(&row->header_); |
0a8606ee LR |
1212 | } |
1213 | """ % { 's' : structName, 't': tableName }) | |
1214 | print(""" | |
1215 | /* Creates a new row of kind "%(t)s". */ | |
1216 | struct %(s)s * | |
d14e007c BP |
1217 | %(s)s_index_init_row(struct ovsdb_idl_index *index) |
1218 | { | |
1219 | ovs_assert(index->table->class_ == &%(p)stable_%(tl)s); | |
491fdb0e | 1220 | return ALIGNED_CAST(struct %(s)s *, ovsdb_idl_index_init_row(index)); |
d14e007c | 1221 | } |
0a8606ee | 1222 | |
d14e007c BP |
1223 | struct %(s)s * |
1224 | %(s)s_index_find(struct ovsdb_idl_index *index, const struct %(s)s *target) | |
0a8606ee | 1225 | { |
d14e007c BP |
1226 | ovs_assert(index->table->class_ == &%(p)stable_%(tl)s); |
1227 | return %(s)s_cast(ovsdb_idl_index_find(index, &target->header_)); | |
1228 | } | |
1229 | ||
1230 | /* Compares 'a' to 'b' and returns a strcmp()-type result. */ | |
1231 | int | |
1232 | %(s)s_index_compare( | |
1233 | struct ovsdb_idl_index *index, | |
1234 | const struct %(s)s *a, | |
1235 | const struct %(s)s *b) | |
0a8606ee | 1236 | { |
d14e007c BP |
1237 | return ovsdb_idl_index_compare(index, &a->header_, &b->header_); |
1238 | } | |
1239 | ||
1240 | struct ovsdb_idl_cursor | |
1241 | %(s)s_cursor_first(struct ovsdb_idl_index *index) | |
0a8606ee | 1242 | { |
d14e007c BP |
1243 | ovs_assert(index->table->class_ == &%(p)stable_%(tl)s); |
1244 | return ovsdb_idl_cursor_first(index); | |
1245 | } | |
1246 | ||
1247 | struct ovsdb_idl_cursor | |
1248 | %(s)s_cursor_first_eq( | |
1249 | struct ovsdb_idl_index *index, const struct %(s)s *target) | |
0a8606ee | 1250 | { |
d14e007c BP |
1251 | ovs_assert(index->table->class_ == &%(p)stable_%(tl)s); |
1252 | return ovsdb_idl_cursor_first_eq(index, &target->header_); | |
1253 | } | |
1254 | ||
1255 | struct ovsdb_idl_cursor | |
1256 | %(s)s_cursor_first_ge( | |
1257 | struct ovsdb_idl_index *index, const struct %(s)s *target) | |
0a8606ee | 1258 | { |
d14e007c BP |
1259 | ovs_assert(index->table->class_ == &%(p)stable_%(tl)s); |
1260 | return ovsdb_idl_cursor_first_ge(index, &target->header_); | |
1261 | } | |
1262 | ||
1263 | struct %(s)s * | |
1264 | %(s)s_cursor_data(struct ovsdb_idl_cursor *cursor) | |
0a8606ee | 1265 | { |
d14e007c BP |
1266 | return %(s)s_cast(ovsdb_idl_cursor_data(cursor)); |
1267 | } | |
1268 | """ % {'s': structName, | |
1269 | 'c': columnName, | |
1270 | 't': tableName, | |
1271 | 'tl': tableName.lower(), | |
1272 | 'p': prefix}) | |
0a8606ee | 1273 | # Indexes Set functions |
81068700 | 1274 | for columnName, column in sorted(table.columns.items()): |
0a8606ee LR |
1275 | type = column.type |
1276 | ||
1277 | comment, members = cMembers(prefix, tableName, columnName, | |
1278 | column, True) | |
1279 | ||
1280 | if type.is_smap(): | |
1281 | print(comment) | |
1282 | print("""void | |
1283 | %(s)s_index_set_%(c)s(const struct %(s)s *row, const struct smap *%(c)s) | |
1284 | { | |
1285 | struct ovsdb_datum *datum = xmalloc(sizeof(struct ovsdb_datum)); | |
1286 | ||
1287 | if (%(c)s) { | |
1288 | struct smap_node *node; | |
1289 | size_t i; | |
1290 | ||
1291 | datum->n = smap_count(%(c)s); | |
1292 | datum->keys = xmalloc(datum->n * sizeof *datum->keys); | |
1293 | datum->values = xmalloc(datum->n * sizeof *datum->values); | |
1294 | ||
1295 | i = 0; | |
1296 | SMAP_FOR_EACH (node, %(c)s) { | |
1297 | datum->keys[i].string = node->key; | |
1298 | datum->values[i].string = node->value; | |
1299 | i++; | |
1300 | } | |
1301 | ovsdb_datum_sort_unique(datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING); | |
1302 | } else { | |
1303 | ovsdb_datum_init_empty(datum); | |
1304 | } | |
d14e007c BP |
1305 | ovsdb_idl_index_write(CONST_CAST(struct ovsdb_idl_row *, &row->header_), |
1306 | &%(s)s_columns[%(S)s_COL_%(C)s], | |
1307 | datum, | |
1308 | &%(p)stable_classes[%(P)sTABLE_%(T)s]); | |
0a8606ee LR |
1309 | } |
1310 | """ % {'t': tableName, | |
1311 | 'p': prefix, | |
1312 | 'P': prefix.upper(), | |
1313 | 's': structName, | |
1314 | 'S': structName.upper(), | |
1315 | 'c': columnName, | |
1316 | 'C': columnName.upper(), | |
1317 | 't': tableName, | |
1318 | 'T': tableName.upper()}) | |
1319 | continue | |
1320 | ||
1321 | keyVar = members[0]['name'] | |
1322 | nVar = None | |
1323 | valueVar = None | |
1324 | if type.value: | |
1325 | valueVar = members[1]['name'] | |
1326 | if len(members) > 2: | |
1327 | nVar = members[2]['name'] | |
1328 | else: | |
1329 | if len(members) > 1: | |
1330 | nVar = members[1]['name'] | |
1331 | ||
1332 | print(comment) | |
1333 | print('void') | |
1334 | print('%(s)s_index_set_%(c)s(const struct %(s)s *row, %(args)s)' % \ | |
1335 | {'s': structName, 'c': columnName, | |
1336 | 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}) | |
1337 | print("{") | |
1338 | print(" struct ovsdb_datum datum;") | |
1339 | if type.n_min == 1 and type.n_max == 1: | |
1340 | print(" union ovsdb_atom *key = xmalloc(sizeof(union ovsdb_atom));") | |
1341 | if type.value: | |
1342 | print(" union ovsdb_atom *value = xmalloc(sizeof(union ovsdb_atom));") | |
1343 | print() | |
1344 | print(" datum.n = 1;") | |
1345 | print(" datum.keys = key;") | |
1346 | print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), keyVar)) | |
1347 | if type.value: | |
1348 | print(" datum.values = value;") | |
1349 | print(" "+ type.value.assign_c_value_casting_away_const("value->%s" % type.value.type.to_string(), valueVar)) | |
1350 | else: | |
1351 | print(" datum.values = NULL;") | |
d14e007c | 1352 | txn_write_func = "ovsdb_idl_index_write" |
0a8606ee LR |
1353 | elif type.is_optional_pointer(): |
1354 | print(" union ovsdb_atom *key = xmalloc(sizeof (union ovsdb_atom));") | |
1355 | print() | |
1356 | print(" if (%s) {" % keyVar) | |
1357 | print(" datum.n = 1;") | |
1358 | print(" datum.keys = key;") | |
1359 | print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), keyVar)) | |
1360 | print(" } else {") | |
1361 | print(" datum.n = 0;") | |
1362 | print(" datum.keys = NULL;") | |
1363 | print(" }") | |
1364 | print(" datum.values = NULL;") | |
d14e007c | 1365 | txn_write_func = "ovsdb_idl_index_write" |
0a8606ee LR |
1366 | elif type.n_max == 1: |
1367 | print(" union ovsdb_atom *key = xmalloc(sizeof(union ovsdb_atom));") | |
1368 | print() | |
1369 | print(" if (%s) {" % nVar) | |
1370 | print(" datum.n = 1;") | |
1371 | print(" datum.keys = key;") | |
1372 | print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), "*" + keyVar)) | |
1373 | print(" } else {") | |
1374 | print(" datum.n = 0;") | |
1375 | print(" datum.keys = NULL;") | |
1376 | print(" }") | |
1377 | print(" datum.values = NULL;") | |
d14e007c | 1378 | txn_write_func = "ovsdb_idl_index_write" |
0a8606ee LR |
1379 | else: |
1380 | print(" size_t i;") | |
1381 | print() | |
1382 | print(" datum.n = %s;" % nVar) | |
1383 | print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)) | |
1384 | if type.value: | |
1385 | print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar) | |
1386 | else: | |
1387 | print(" datum.values = NULL;") | |
1388 | print(" for (i = 0; i < %s; i++) {" % nVar) | |
1389 | print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)) | |
1390 | if type.value: | |
1391 | print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)) | |
1392 | print(" }") | |
1393 | if type.value: | |
1394 | valueType = type.value.toAtomicType() | |
1395 | else: | |
1396 | valueType = "OVSDB_TYPE_VOID" | |
1397 | print(" ovsdb_datum_sort_unique(&datum, %s, %s);" % ( | |
1398 | type.key.toAtomicType(), valueType)) | |
d14e007c | 1399 | txn_write_func = "ovsdb_idl_index_write" |
0a8606ee LR |
1400 | 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]);" \ |
1401 | % {'f': txn_write_func, | |
1402 | 's': structName, | |
1403 | 'S': structName.upper(), | |
1404 | 'C': columnName.upper(), | |
1405 | 'p': prefix, | |
1406 | 'P': prefix.upper(), | |
1407 | 't': tableName, | |
1408 | 'T': tableName.upper()}) | |
1409 | print("}") | |
1410 | # End Index table related functions | |
1411 | ||
1412 | # Table columns. | |
1413 | print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % ( | |
1414 | structName, structName.upper())) | |
d34a1cc0 | 1415 | print(""" |
1f2d2557 | 1416 | void |
0164e367 | 1417 | %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition) |
16ebb90e | 1418 | { |
0164e367 BP |
1419 | ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition); |
1420 | }""" % {'p': prefix, | |
1421 | 's': structName, | |
d34a1cc0 | 1422 | 'tl': tableName.lower()}) |
16ebb90e | 1423 | |
c3bb4bd7 | 1424 | # Table columns. |
74e98efd BP |
1425 | for columnName, column in sorted_columns(table): |
1426 | prereqs = [] | |
1427 | x = column.type.cInitType("%s_col_%s" % (tableName, columnName), prereqs) | |
1428 | if prereqs: | |
d34a1cc0 JW |
1429 | print('\n'.join(prereqs)) |
1430 | print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS] = {" % ( | |
1431 | structName, structName.upper())) | |
e0b1744f | 1432 | for columnName, column in sorted_columns(table): |
341c4e59 BP |
1433 | if column.mutable: |
1434 | mutable = "true" | |
1435 | else: | |
1436 | mutable = "false" | |
01928c96 BP |
1437 | if column.extensions.get("synthetic"): |
1438 | synthetic = "true" | |
1439 | else: | |
1440 | synthetic = "false" | |
74e98efd BP |
1441 | type_init = '\n'.join(" " + x |
1442 | for x in column.type.cInitType("%s_col_%s" % (tableName, columnName), prereqs)) | |
d34a1cc0 | 1443 | print("""\ |
74e98efd | 1444 | [%(P)s%(T)s_COL_%(C)s] = { |
adb4185d | 1445 | .name = "%(column_name_in_schema)s", |
74e98efd BP |
1446 | .type = { |
1447 | %(type)s | |
1448 | }, | |
c6e5d064 | 1449 | .is_mutable = %(mutable)s, |
01928c96 | 1450 | .is_synthetic = %(synthetic)s, |
74e98efd BP |
1451 | .parse = %(s)s_parse_%(c)s, |
1452 | .unparse = %(s)s_unparse_%(c)s, | |
1453 | },\n""" % {'P': prefix.upper(), | |
1454 | 'T': tableName.upper(), | |
1455 | 'c': columnName, | |
1456 | 'C': columnName.upper(), | |
1457 | 's': structName, | |
1458 | 'mutable': mutable, | |
01928c96 | 1459 | 'synthetic': synthetic, |
adb4185d YHW |
1460 | 'type': type_init, |
1461 | 'column_name_in_schema': column.name}) | |
d34a1cc0 | 1462 | print("};") |
c3bb4bd7 BP |
1463 | |
1464 | # Table classes. | |
d34a1cc0 JW |
1465 | print("\f") |
1466 | print("struct ovsdb_idl_table_class %stable_classes[%sN_TABLES] = {" % (prefix, prefix.upper())) | |
4ab66562 | 1467 | for tableName, table in sorted(schema.tables.items()): |
c3bb4bd7 | 1468 | structName = "%s%s" % (prefix, tableName.lower()) |
c5f341ab BP |
1469 | if table.is_root: |
1470 | is_root = "true" | |
1471 | else: | |
1472 | is_root = "false" | |
25540a77 BP |
1473 | if table.max_rows == 1: |
1474 | is_singleton = "true" | |
1475 | else: | |
1476 | is_singleton = "false" | |
1477 | print(" {\"%s\", %s, %s," % (tableName, is_root, is_singleton)) | |
d34a1cc0 | 1478 | print(" %s_columns, ARRAY_SIZE(%s_columns)," % ( |
25540a77 | 1479 | structName, structName)) |
d34a1cc0 JW |
1480 | print(" sizeof(struct %s), %s_init__}," % (structName, structName)) |
1481 | print("};") | |
c3bb4bd7 BP |
1482 | |
1483 | # IDL class. | |
d34a1cc0 JW |
1484 | print("\nstruct ovsdb_idl_class %sidl_class = {" % prefix) |
1485 | print(" \"%s\", %stable_classes, ARRAY_SIZE(%stable_classes)" % ( | |
1486 | schema.name, prefix, prefix)) | |
1487 | print("};") | |
d879a707 | 1488 | |
d34a1cc0 | 1489 | print(""" |
87412f02 JP |
1490 | /* Return the schema version. The caller must not free the returned value. */ |
1491 | const char * | |
1492 | %sget_db_version(void) | |
1493 | { | |
1494 | return "%s"; | |
1495 | } | |
d34a1cc0 | 1496 | """ % (prefix, schema.version)) |
87412f02 JP |
1497 | |
1498 | ||
8cdf0349 | 1499 | |
d879a707 BP |
1500 | def ovsdb_escape(string): |
1501 | def escape(match): | |
1502 | c = match.group(0) | |
1503 | if c == '\0': | |
99155935 | 1504 | raise ovs.db.error.Error("strings may not contain null bytes") |
d879a707 BP |
1505 | elif c == '\\': |
1506 | return '\\\\' | |
1507 | elif c == '\n': | |
1508 | return '\\n' | |
1509 | elif c == '\r': | |
1510 | return '\\r' | |
1511 | elif c == '\t': | |
1512 | return '\\t' | |
1513 | elif c == '\b': | |
1514 | return '\\b' | |
1515 | elif c == '\a': | |
1516 | return '\\a' | |
1517 | else: | |
1518 | return '\\x%02x' % ord(c) | |
1519 | return re.sub(r'["\\\000-\037]', escape, string) | |
1520 | ||
d879a707 | 1521 | def usage(): |
d34a1cc0 | 1522 | print("""\ |
d879a707 | 1523 | %(argv0)s: ovsdb schema compiler |
00732bf5 | 1524 | usage: %(argv0)s [OPTIONS] COMMAND ARG... |
d879a707 | 1525 | |
00732bf5 BP |
1526 | The following commands are supported: |
1527 | annotate SCHEMA ANNOTATIONS print SCHEMA combined with ANNOTATIONS | |
1528 | c-idl-header IDL print C header file for IDL | |
1529 | c-idl-source IDL print C source file for IDL implementation | |
d879a707 BP |
1530 | |
1531 | The following options are also available: | |
1532 | -h, --help display this help message | |
1533 | -V, --version display version information\ | |
d34a1cc0 | 1534 | """ % {'argv0': argv0}) |
d879a707 BP |
1535 | sys.exit(0) |
1536 | ||
1537 | if __name__ == "__main__": | |
1538 | try: | |
1539 | try: | |
00732bf5 BP |
1540 | options, args = getopt.gnu_getopt(sys.argv[1:], 'C:hV', |
1541 | ['directory', | |
1542 | 'help', | |
d879a707 | 1543 | 'version']) |
52e4a477 | 1544 | except getopt.GetoptError as geo: |
d879a707 BP |
1545 | sys.stderr.write("%s: %s\n" % (argv0, geo.msg)) |
1546 | sys.exit(1) | |
c5c7c7c5 | 1547 | |
00732bf5 BP |
1548 | for key, value in options: |
1549 | if key in ['-h', '--help']: | |
1550 | usage() | |
1551 | elif key in ['-V', '--version']: | |
d34a1cc0 | 1552 | print("ovsdb-idlc (Open vSwitch) @VERSION@") |
00732bf5 BP |
1553 | elif key in ['-C', '--directory']: |
1554 | os.chdir(value) | |
1555 | else: | |
1556 | sys.exit(0) | |
c5c7c7c5 | 1557 | |
d879a707 | 1558 | optKeys = [key for key, value in options] |
00732bf5 BP |
1559 | |
1560 | if not args: | |
1561 | sys.stderr.write("%s: missing command argument " | |
1562 | "(use --help for help)\n" % argv0) | |
d879a707 BP |
1563 | sys.exit(1) |
1564 | ||
00732bf5 BP |
1565 | commands = {"annotate": (annotateSchema, 2), |
1566 | "c-idl-header": (printCIDLHeader, 1), | |
2c84fdf2 | 1567 | "c-idl-source": (printCIDLSource, 1)} |
00732bf5 BP |
1568 | |
1569 | if not args[0] in commands: | |
1570 | sys.stderr.write("%s: unknown command \"%s\" " | |
1571 | "(use --help for help)\n" % (argv0, args[0])) | |
d879a707 | 1572 | sys.exit(1) |
00732bf5 BP |
1573 | |
1574 | func, n_args = commands[args[0]] | |
1575 | if len(args) - 1 != n_args: | |
1576 | sys.stderr.write("%s: \"%s\" requires %d arguments but %d " | |
1577 | "provided\n" | |
1578 | % (argv0, args[0], n_args, len(args) - 1)) | |
1579 | sys.exit(1) | |
1580 | ||
1581 | func(*args[1:]) | |
52e4a477 | 1582 | except ovs.db.error.Error as e: |
99155935 | 1583 | sys.stderr.write("%s: %s\n" % (argv0, e)) |
d879a707 BP |
1584 | sys.exit(1) |
1585 | ||
1586 | # Local variables: | |
1587 | # mode: python | |
1588 | # End: |