3 from __future__ import print_function
12 from ovs.db.types import StringType, IntegerType, RealType
16 def parseSchema(filename):
17 return ovs.db.schema.IdlSchema.from_json(ovs.json.from_file(filename))
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')
25 def constify(cType, const):
27 and cType.endswith('*') and
28 (cType == 'char **' or not cType.endswith('**'))):
29 return 'const %s' % cType
33 def cMembers(prefix, tableName, columnName, column, const, refTable=True):
39 /* Sets the "%(c)s" column's value from the "%(t)s" table in 'row'
42 * The caller retains ownership of '%(c)s' and everything in it. */""" \
45 return (comment, [{'name': columnName,
46 'type': 'struct smap ',
49 comment = """\n/* Sets the "%s" column from the "%s" table in """\
50 """'row' to\n""" % (columnName, tableName)
52 if type.n_min == 1 and type.n_max == 1:
57 if type.is_optional_pointer():
64 keyName = "key_%s" % columnName
65 valueName = "value_%s" % columnName
67 key = {'name': keyName,
68 'type': constify(type.key.toCType(prefix, refTable) + pointer, const),
70 value = {'name': valueName,
71 'type': constify(type.value.toCType(prefix, refTable) + pointer, const),
75 comment += " * the map with key '%s' and value '%s'\n *" \
76 % (keyName, valueName)
78 comment += " * the map with keys '%s' and values '%s'\n *" \
79 % (keyName, valueName)
80 members = [key, value]
82 m = {'name': columnName,
83 'type': constify(type.key.toCType(prefix, refTable) + pointer, const),
84 'comment': type.cDeclComment()}
87 comment += " * '%s'" % columnName
89 comment += " * the '%s' set" % columnName
92 if not singleton and not type.is_optional_pointer():
93 sizeName = "n_%s" % columnName
95 comment += " with '%s' entries" % sizeName
96 members.append({'name': sizeName,
102 if type.is_optional() and not type.is_optional_pointer():
104 * '%s' may be 0 or 1; if it is 0, then '%s'
105 * may be NULL.\n""" \
106 % ("n_%s" % columnName, columnName)
108 if type.is_optional_pointer():
110 * If "%s" is null, the column will be the empty set,
111 * otherwise it will contain the specified value.\n""" % columnName
113 if type.constraintsToEnglish():
115 * Argument constraints: %s\n""" \
116 % type.constraintsToEnglish(lambda s : '"%s"' % s)
118 comment += " *\n * The caller retains ownership of the arguments. */"
120 return (comment, members)
122 def sorted_columns(table):
123 return sorted(table.columns.items())
125 def printCIDLHeader(schemaFile):
126 schema = parseSchema(schemaFile)
127 prefix = schema.idlPrefix
129 /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */
131 #ifndef %(prefix)sIDL_HEADER
132 #define %(prefix)sIDL_HEADER 1
137 #include "ovsdb-data.h"
138 #include "ovsdb-idl-provider.h"
145 ''' % {'prefix': prefix.upper()})
147 for tableName, table in sorted(schema.tables.items()):
148 structName = "%s%s" % (prefix, tableName.lower())
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)
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()])
168 for columnName in table.columns:
169 print("#define %(s)s_col_%(c)s (%(s)s_columns[%(S)s_COL_%(C)s])" % {
171 'S': structName.upper(),
173 'C': columnName.upper()})
175 print("\nextern struct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (structName, structName.upper()))
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); \\
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; \\
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); \\
197 (ROW) = %(s)s_track_get_next(ROW))
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)
202 return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_MODIFY) == 0;
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)
208 return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_DELETE) > 0;
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); \\
229 (ROW) = %(s)s_index_next(CURSOR))
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()})
237 for columnName, column in sorted_columns(table):
238 print('void %(s)s_verify_%(c)s(const struct %(s)s *);' % {'s': structName, 'c': columnName})
241 for columnName, column in sorted_columns(table):
242 if column.type.value:
243 valueParam = ', enum ovsdb_atomic_type value_type'
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})
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 *']
255 comment, members = cMembers(prefix, tableName, columnName,
257 args = ['%(type)s%(name)s' % member for member in members]
258 print('%s);' % ', '.join(args))
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)})
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 *']
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))
282 print('void %(s)s_set_condition(struct ovsdb_idl *, struct ovsdb_idl_condition *);' % {'s': structName})
287 print("struct %(s)s * %(s)s_index_init_row(struct ovsdb_idl *, const struct ovsdb_idl_table_class *);" % {'s': structName})
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 *']
294 comment, members = cMembers(prefix, tableName, columnName,
296 args = ['%(type)s%(name)s' % member for member in members]
297 print('%s);' % ', '.join(args))
300 printEnum("%stable_id" % prefix.lower(), ["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()])
302 for tableName in schema.tables:
303 print("#define %(p)stable_%(t)s (%(p)stable_classes[%(P)sTABLE_%(T)s])" % {
306 't': tableName.lower(),
307 'T': tableName.upper()})
308 print("\nextern struct ovsdb_idl_table_class %stable_classes[%sN_TABLES];" % (prefix, prefix.upper()))
310 print("\nextern struct ovsdb_idl_class %sidl_class;" % prefix)
312 print("\nconst char * %sget_db_version(void);" % prefix)
317 print("\n#endif /* %(prefix)sIDL_HEADER */" % {'prefix': prefix.upper()})
319 def printEnum(type, members):
320 if len(members) == 0:
323 print("\nenum %s {" % type)
324 for member in members[:-1]:
325 print(" %s," % member)
326 print(" %s" % members[-1])
329 def printCIDLSource(schemaFile):
330 schema = parseSchema(schemaFile)
331 prefix = schema.idlPrefix
333 /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */
338 #include "ovs-thread.h"
339 #include "ovsdb-data.h"
340 #include "ovsdb-error.h"
343 ''' % schema.idlHeader)
346 for tableName, table in sorted(schema.tables.items()):
347 structName = "%s%s" % (prefix, tableName.lower())
349 static struct %(s)s *
350 %(s)s_cast(const struct ovsdb_idl_row *row)
352 return row ? CONTAINER_OF(row, struct %(s)s, header_) : NULL;
354 ''' % {'s': structName})
357 for tableName, table in sorted(schema.tables.items()):
358 structName = "%s%s" % (prefix, tableName.lower())
360 print("/* %s table. */" % (tableName))
363 for columnName, column in sorted_columns(table):
366 %(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum)
368 struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName,
372 keyVar = "row->key_%s" % columnName
373 valueVar = "row->value_%s" % columnName
375 keyVar = "row->%s" % columnName
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);")
385 elif (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer():
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()))
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()))
394 if not type.value.ref_table:
395 print(" %s = datum->values[0].%s;" % (valueVar, type.value.type.to_string()))
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()))
399 print(" %s" % type.key.initCDefault(keyVar, type.n_min == 0))
401 print(" %s" % type.value.initCDefault(valueVar, type.n_min == 0))
404 if type.n_max != sys.maxsize:
405 print(" size_t n = MIN(%d, datum->n);" % type.n_max)
409 print(" %s = NULL;" % keyVar)
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:
416 struct %s%s *keyRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->keys[i].uuid));
420 """ % (prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower()))
423 keySrc = "datum->keys[i].%s" % type.key.type.to_string()
424 if type.value and type.value.ref_table:
426 struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[i].uuid));
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"
433 valueSrc = "datum->values[i].%s" % type.value.type.to_string()
434 print(" if (!row->n_%s) {" % (columnName))
436 print(" %s = xmalloc(%s * sizeof *%s);" % (
437 keyVar, nMax, keyVar))
439 print(" %s = xmalloc(%s * sizeof *%s);" % (
440 valueVar, nMax, valueVar))
442 print(" %s[row->n_%s] = %s;" % (keyVar, columnName, keySrc))
444 print(" %s[row->n_%s] = %s;" % (valueVar, columnName, valueSrc))
445 print(" row->n_%s++;" % columnName)
450 for columnName, column in sorted_columns(table):
452 if type.is_smap() or (type.n_min != 1 or type.n_max != 1) and not type.is_optional_pointer():
455 %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row_)
457 struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName,
461 print(" smap_destroy(&row->%s);" % columnName)
464 keyVar = "row->key_%s" % columnName
465 valueVar = "row->value_%s" % columnName
467 keyVar = "row->%s" % columnName
469 print(" free(%s);" % keyVar)
471 print(" free(%s);" % valueVar)
476 %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row OVS_UNUSED)
479 }''' % {'s': structName, 'c': columnName})
481 # Generic Row Initialization function.
484 %(s)s_init__(struct ovsdb_idl_row *row)
486 %(s)s_init(%(s)s_cast(row));
487 }""" % {'s': structName})
489 # Row Initialization function.
491 /* Clears the contents of 'row' in table "%(t)s". */
493 %(s)s_init(struct %(s)s *row)
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)
506 # First, next functions.
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. */
511 %(s)s_get_for_uuid(const struct ovsdb_idl *idl, const struct uuid *uuid)
513 return %(s)s_cast(ovsdb_idl_get_row_for_uuid(idl, &%(p)stable_%(tl)s, uuid));
516 /* Returns a row in table "%(t)s" in 'idl', or a null pointer if that
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. */
523 %(s)s_first(const struct ovsdb_idl *idl)
525 return %(s)s_cast(ovsdb_idl_first_row(idl, &%(p)stable_%(tl)s));
528 /* Returns a row following 'row' within its table, or a null pointer if 'row'
529 * is the last row in its table. */
531 %(s)s_next(const struct %(s)s *row)
533 return %(s)s_cast(ovsdb_idl_next_row(&row->header_));
536 unsigned int %(s)s_get_seqno(const struct ovsdb_idl *idl)
538 return ovsdb_idl_table_get_seqno(idl, &%(p)stable_%(tl)s);
541 unsigned int %(s)s_row_get_seqno(const struct %(s)s *row, enum ovsdb_idl_change change)
543 return ovsdb_idl_row_get_seqno(&row->header_, change);
547 %(s)s_track_get_first(const struct ovsdb_idl *idl)
549 return %(s)s_cast(ovsdb_idl_track_get_first(idl, &%(p)stable_%(tl)s));
553 *%(s)s_track_get_next(const struct %(s)s *row)
555 return %(s)s_cast(ovsdb_idl_track_get_next(&row->header_));
556 }''' % {'s': structName,
560 'tl': tableName.lower(),
561 'T': tableName.upper()})
565 /* Deletes 'row' from table "%(t)s". 'row' may be freed, so it must not be
566 * accessed afterward.
568 * The caller must have started a transaction with ovsdb_idl_txn_create(). */
570 %(s)s_delete(const struct %(s)s *row)
572 ovsdb_idl_txn_delete(&row->header_);
575 /* Inserts and returns a new row in the table "%(t)s" in the database
576 * with open transaction 'txn'.
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. */
583 %(s)s_insert(struct ovsdb_idl_txn *txn)
585 return %(s)s_cast(ovsdb_idl_txn_insert(txn, &%(p)stable_%(tl)s, NULL));
589 %(s)s_is_updated(const struct %(s)s *row, enum %(s)s_column_id column)
591 return ovsdb_idl_track_is_updated(&row->header_, &%(s)s_columns[column]);
592 }''' % {'s': structName,
596 'tl': tableName.lower(),
597 'T': tableName.upper()})
600 for columnName, column in sorted_columns(table):
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.
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.
612 * In some cases this function reduces to a no-op, because the current value
613 * of "%(c)s" is already known:
615 * - If 'row' is a row created by the current transaction (returned by
618 * - If "%(c)s" has already been modified (with
619 * %(s)s_set_%(c)s()) within the current transaction.
621 * Because of the latter property, always call this function *before*
622 * %(s)s_set_%(c)s() for a given read-modify-write.
624 * The caller must have started a transaction with ovsdb_idl_txn_create(). */
626 %(s)s_verify_%(c)s(const struct %(s)s *row)
628 ovsdb_idl_txn_verify(&row->header_, &%(s)s_col_%(c)s);
629 }''' % {'s': structName,
630 'S': structName.upper(),
632 'C': columnName.upper()})
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()
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"
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.)
655 * The caller must not modify or free the returned value.
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().
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)
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})
675 for columnName, column in sorted_columns(table):
678 comment, members = cMembers(prefix, tableName, columnName,
684 %(s)s_set_%(c)s(const struct %(s)s *row, const struct smap *%(c)s)
686 struct ovsdb_datum datum;
689 ovsdb_datum_from_smap(&datum, %(c)s);
691 ovsdb_datum_init_empty(&datum);
693 ovsdb_idl_txn_write(&row->header_,
697 """ % {'t': tableName,
699 'S': structName.upper(),
701 'C': columnName.upper()})
704 keyVar = members[0]['name']
708 valueVar = members[1]['name']
710 nVar = members[2]['name']
713 nVar = members[1]['name']
718 %(s)s_set_%(c)s(const struct %(s)s *row, %(args)s)
720 struct ovsdb_datum datum;""" % {'s': structName,
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;")
727 print(" union ovsdb_atom value;")
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))
733 print(" datum.values = &value;")
734 print(" "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar))
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;")
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))
746 print(" datum.n = 0;")
747 print(" datum.keys = NULL;")
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;")
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))
759 print(" datum.n = 0;")
760 print(" datum.keys = NULL;")
762 print(" datum.values = NULL;")
763 txn_write_func = "ovsdb_idl_txn_write_clone"
766 print(" datum.n = %s;" % nVar)
767 print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar))
769 print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar)
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))
775 print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar))
778 valueType = type.value.toAtomicType()
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,
785 'S': structName.upper(),
788 # Update/Delete of partial map column functions
789 for columnName, column in sorted_columns(table):
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'.
798 %(s)s_update_%(c)s_setkey(const struct %(s)s *row, %(coltype)snew_key, %(valtype)snew_value)
800 struct ovsdb_datum *datum;
802 datum = xmalloc(sizeof *datum);
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})
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"))
813 ovsdb_idl_txn_write_partial_map(&row->header_,
816 }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix),
817 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper()})
819 /* Deletes an element of the "%(c)s" map column from the "%(t)s" table in 'row'
820 * given the key value 'delete_key'.
824 %(s)s_update_%(c)s_delkey(const struct %(s)s *row, %(coltype)sdelete_key)
826 struct ovsdb_datum *datum;
828 datum = xmalloc(sizeof *datum);
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})
836 print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_key"))
838 ovsdb_idl_txn_delete_partial_map(&row->header_,
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
847 /* Adds the value 'new_value' to the "%(c)s" set column from the "%(t)s" table
852 %(s)s_update_%(c)s_addvalue(const struct %(s)s *row, %(valtype)snew_value)
854 struct ovsdb_datum *datum;
856 datum = xmalloc(sizeof *datum);
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})
863 print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "new_value"))
865 ovsdb_idl_txn_write_partial_set(&row->header_,
868 }''' % {'s': structName, 'c': columnName,'coltype':column.type.key.toCType(prefix),
869 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper()})
871 /* Deletes the value 'delete_value' from the "%(c)s" set column from the
872 * "%(t)s" table in 'row'.
876 %(s)s_update_%(c)s_delvalue(const struct %(s)s *row, %(valtype)sdelete_value)
878 struct ovsdb_datum *datum;
880 datum = xmalloc(sizeof *datum);
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})
888 print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_value"))
890 ovsdb_idl_txn_delete_partial_set(&row->header_,
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
897 # Add clause functions.
898 for columnName, column in sorted_columns(table):
901 comment, members = cMembers(prefix, tableName, columnName,
902 column, True, refTable=False)
907 %(s)s_add_clause_%(c)s(struct ovsdb_idl_condition *cond, enum ovsdb_function function, const struct smap *%(c)s)
909 struct ovsdb_datum datum;
912 ovsdb_datum_from_smap(&datum, %(c)s);
914 ovsdb_datum_init_empty(&datum);
917 ovsdb_idl_condition_add_clause(cond,
922 ovsdb_datum_destroy(&datum, &%(s)s_col_%(c)s.type);
924 """ % {'t': tableName,
925 'tl': tableName.lower(),
926 'T': tableName.upper(),
930 'S': structName.upper(),
934 keyVar = members[0]['name']
938 valueVar = members[1]['name']
940 nVar = members[2]['name']
943 nVar = members[1]['name']
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])})
951 print(" struct ovsdb_datum datum;")
953 if type.n_min == 1 and type.n_max == 1:
954 print(" union ovsdb_atom key;")
956 print(" union ovsdb_atom value;")
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))
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))
965 print(" datum.values = NULL;")
966 elif type.is_optional_pointer():
967 print(" union ovsdb_atom key;")
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))
974 print(" datum.n = 0;")
975 print(" datum.keys = NULL;")
977 print(" datum.values = NULL;")
978 elif type.n_max == 1:
979 print(" union ovsdb_atom key;")
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))
986 print(" datum.n = 0;")
987 print(" datum.keys = NULL;")
989 print(" datum.values = NULL;")
991 print(" datum.n = %s;" % nVar)
992 print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar))
993 free += ['datum.keys']
995 print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar)
996 free += ['datum.values']
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))
1002 print(" " + type.value.assign_c_value_casting_away_const("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar, refTable=False))
1005 valueType = type.value.toAtomicType()
1007 valueType = "OVSDB_TYPE_VOID"
1008 print(" ovsdb_datum_sort_unique(&datum, %s, %s);" % (
1009 type.key.toAtomicType(), valueType))
1011 print(""" ovsdb_idl_condition_add_clause(cond,
1015 """ % {'tl': tableName.lower(),
1016 'T': tableName.upper(),
1018 'P': prefix.upper(),
1020 'S': structName.upper(),
1023 print(" free(%s);" % var)
1026 # Index table related functions
1028 /* Destroy 'row' of kind "%(t)s". The row must have been
1029 * created with ovsdb_idl_index_init_row.
1032 %(s)s_index_destroy_row(const struct %(s)s *row)
1034 ovsdb_idl_index_destroy_row__(&row->header_);
1036 """ % { 's' : structName, 't': tableName })
1038 /* Creates a new row of kind "%(t)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})
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})
1055 print("""%(s)s_index_compare(struct ovsdb_idl_index_cursor *cursor, const struct %(s)s *const_data1, const struct %(s)s *const_data2)
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 })
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)
1067 return %(s)s_cast(ovsdb_idl_index_first(cursor));
1068 }""" % { 's' : structName })
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)
1075 return %(s)s_cast(ovsdb_idl_index_next(cursor));
1076 }""" % { 's' : structName })
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)
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 })
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)
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 })
1100 /* This function is used to get the data of the row in the current position pointed by the cursor in
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)
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()):
1112 comment, members = cMembers(prefix, tableName, columnName,
1118 %(s)s_index_set_%(c)s(const struct %(s)s *row, const struct smap *%(c)s)
1120 struct ovsdb_datum *datum = xmalloc(sizeof(struct ovsdb_datum));
1123 struct smap_node *node;
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);
1131 SMAP_FOR_EACH (node, %(c)s) {
1132 datum->keys[i].string = node->key;
1133 datum->values[i].string = node->value;
1136 ovsdb_datum_sort_unique(datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING);
1138 ovsdb_datum_init_empty(datum);
1140 ovsdb_idl_index_write_(CONST_CAST(struct ovsdb_idl_row *, &row->header_),
1141 &%(s)s_columns[%(S)s_COL_%(C)s],
1143 &%(p)stable_classes[%(P)sTABLE_%(T)s]);
1145 """ % {'t': tableName,
1147 'P': prefix.upper(),
1149 'S': structName.upper(),
1151 'C': columnName.upper(),
1153 'T': tableName.upper()})
1156 keyVar = members[0]['name']
1160 valueVar = members[1]['name']
1161 if len(members) > 2:
1162 nVar = members[2]['name']
1164 if len(members) > 1:
1165 nVar = members[1]['name']
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])})
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));")
1177 print(" union ovsdb_atom *value = xmalloc(sizeof(union ovsdb_atom));")
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))
1183 print(" datum.values = value;")
1184 print(" "+ type.value.assign_c_value_casting_away_const("value->%s" % type.value.type.to_string(), valueVar))
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));")
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))
1196 print(" datum.n = 0;")
1197 print(" datum.keys = NULL;")
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));")
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))
1209 print(" datum.n = 0;")
1210 print(" datum.keys = NULL;")
1212 print(" datum.values = NULL;")
1213 txn_write_func = "ovsdb_idl_index_write_"
1217 print(" datum.n = %s;" % nVar)
1218 print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar))
1220 print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar)
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))
1226 print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar))
1229 valueType = type.value.toAtomicType()
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,
1238 'S': structName.upper(),
1239 'C': columnName.upper(),
1241 'P': prefix.upper(),
1243 'T': tableName.upper()})
1245 # End Index table related functions
1248 print("\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
1249 structName, structName.upper()))
1252 %(s)s_set_condition(struct ovsdb_idl *idl, struct ovsdb_idl_condition *condition)
1254 ovsdb_idl_set_condition(idl, &%(p)stable_%(tl)s, condition);
1255 }""" % {'p': prefix,
1257 'tl': tableName.lower()})
1260 for columnName, column in sorted_columns(table):
1262 x = column.type.cInitType("%s_col_%s" % (tableName, columnName), 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):
1272 type_init = '\n'.join(" " + x
1273 for x in column.type.cInitType("%s_col_%s" % (tableName, columnName), prereqs))
1275 [%(P)s%(T)s_COL_%(C)s] = {
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(),
1286 'C': columnName.upper(),
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())
1301 if table.max_rows == 1:
1302 is_singleton = "true"
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))
1312 print("\nstruct ovsdb_idl_class %sidl_class = {" % prefix)
1313 print(" \"%s\", %stable_classes, ARRAY_SIZE(%stable_classes)" % (
1314 schema.name, prefix, prefix))
1318 /* Return the schema version. The caller must not free the returned value. */
1320 %sget_db_version(void)
1324 """ % (prefix, schema.version))
1328 def ovsdb_escape(string):
1332 raise ovs.db.error.Error("strings may not contain null bytes")
1346 return '\\x%02x' % ord(c)
1347 return re.sub(r'["\\\000-\037]', escape, string)
1351 %(argv0)s: ovsdb schema compiler
1352 usage: %(argv0)s [OPTIONS] COMMAND ARG...
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
1359 The following options are also available:
1360 -h, --help display this help message
1361 -V, --version display version information\
1362 """ % {'argv0': argv0})
1365 if __name__ == "__main__":
1368 options, args = getopt.gnu_getopt(sys.argv[1:], 'C:hV',
1372 except getopt.GetoptError as geo:
1373 sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
1376 for key, value in options:
1377 if key in ['-h', '--help']:
1379 elif key in ['-V', '--version']:
1380 print("ovsdb-idlc (Open vSwitch) @VERSION@")
1381 elif key in ['-C', '--directory']:
1386 optKeys = [key for key, value in options]
1389 sys.stderr.write("%s: missing command argument "
1390 "(use --help for help)\n" % argv0)
1393 commands = {"annotate": (annotateSchema, 2),
1394 "c-idl-header": (printCIDLHeader, 1),
1395 "c-idl-source": (printCIDLSource, 1)}
1397 if not args[0] in commands:
1398 sys.stderr.write("%s: unknown command \"%s\" "
1399 "(use --help for help)\n" % (argv0, args[0]))
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 "
1406 % (argv0, args[0], n_args, len(args) - 1))
1410 except ovs.db.error.Error as e:
1411 sys.stderr.write("%s: %s\n" % (argv0, e))