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