summaryrefslogtreecommitdiff
path: root/ovsdb/ovsdb-idlc.in
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2016-10-07 09:47:43 -0700
committerBen Pfaff <blp@ovn.org>2018-02-16 15:08:08 -0800
commit01928c964f572fb0551c999437557458f326be3e (patch)
treec9eec1da58096529e05cc3a08d3624d108e5e75a /ovsdb/ovsdb-idlc.in
parent00386a6921329d3449a93d536f86a756dedb14b3 (diff)
downloadopenvswitch-01928c964f572fb0551c999437557458f326be3e.tar.gz
ovsdb-idlc: Implement synthetic columns.
A synthetic column is one that is not present in the actual database but instead calculated by code in the client based on columns in the row. This can be useful to avoid repeatedly calculating the same function of a row. Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'ovsdb/ovsdb-idlc.in')
-rwxr-xr-xovsdb/ovsdb-idlc.in89
1 files changed, 85 insertions, 4 deletions
diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index 95bb9f4ca..1ea2115c0 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -119,8 +119,42 @@ def cMembers(prefix, tableName, columnName, column, const, refTable=True):
return (comment, members)
+# This is equivalent to sorted(table.columns.items()), except that the
+# sorting includes a topological component: if column B has a
+# dependency on column A, then A will be sorted before B.
def sorted_columns(table):
- return sorted(table.columns.items())
+ input = []
+ for name, column in table.columns.items():
+ dependencies = column.extensions.get('dependencies', [])
+ for d in dependencies:
+ if d not in table.columns:
+ sys.stderr.write("Table %s column %s depends on column %s "
+ "but there is no such column\n"
+ % (table.name, name, d))
+ sys.exit(1)
+ input += [(name, column, set(dependencies))]
+
+ output = []
+ satisfied_dependencies = set()
+ while input:
+ done = []
+ next = []
+ for name, column, dependencies in input:
+ if dependencies <= satisfied_dependencies:
+ done += [(name, column)]
+ else:
+ next += [(name, column, dependencies)]
+
+ if not done:
+ sys.stderr.write("Table %s columns have circular dependencies\n"
+ % table.name)
+ sys.exit(1)
+
+ for name, column in done:
+ satisfied_dependencies.add(name)
+ output += sorted(done)
+ input = next
+ return output
# If a column name in the schema is a C or C++ keyword, append an underscore
# to the column name.
@@ -179,6 +213,9 @@ extern "C" {
print("\tstruct ovsdb_idl_row header_;")
for columnName, column in sorted_columns(table):
print("\n\t/* %s column. */" % columnName)
+ if column.extensions.get("members"):
+ print("\t%s" % column.extensions["members"])
+ continue
comment, members = cMembers(prefix, tableName,
columnName, column, False)
for member in members:
@@ -261,10 +298,14 @@ bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id);
''' % {'s': structName, 'S': structName.upper()})
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
print('void %(s)s_verify_%(c)s(const struct %(s)s *);' % {'s': structName, 'c': columnName})
print("")
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
if column.type.value:
valueParam = ', enum ovsdb_atomic_type value_type'
else:
@@ -274,6 +315,8 @@ bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id);
print("")
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
print('void %(s)s_set_%(c)s(const struct %(s)s *,' % {'s': structName, 'c': columnName}, end=' ')
if column.type.is_smap():
args = ['const struct smap *']
@@ -285,6 +328,8 @@ bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id);
print("")
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
if column.type.is_map():
print('void %(s)s_update_%(c)s_setkey(const struct %(s)s *, ' % {'s': structName, 'c': columnName}, end=' ')
print('%(coltype)s, %(valtype)s);' % {'coltype':column.type.key.to_const_c_type(prefix), 'valtype':column.type.value.to_const_c_type(prefix)})
@@ -391,6 +436,21 @@ static struct %(s)s *
# Parse functions.
for columnName, column in sorted_columns(table):
+ if 'parse' in column.extensions:
+ print('''
+static void
+%(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum OVS_UNUSED)
+{
+ struct %(s)s *row = %(s)s_cast(row_);\
+''' % {'s': structName, 'c': columnName})
+ print(column.extensions["parse"])
+ print("}")
+ continue
+ if column.extensions.get('synthetic'):
+ # Synthetic columns aren't parsed from a datum.
+ unused = " OVS_UNUSED"
+ else:
+ unused = ""
print('''
static void
%(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum)
@@ -398,6 +458,10 @@ static void
struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName,
'c': columnName})
type = column.type
+ if 'parse' in column.extensions:
+ print(column.extensions["parse"])
+ print("}")
+ continue
if type.value:
keyVar = "row->key_%s" % columnName
valueVar = "row->value_%s" % columnName
@@ -479,15 +543,16 @@ static void
# Unparse functions.
for columnName, column in sorted_columns(table):
type = column.type
- if type.is_smap() or (type.n_min != 1 or type.n_max != 1) and not type.is_optional_pointer():
+ if (type.is_smap() or (type.n_min != 1 or type.n_max != 1) and not type.is_optional_pointer()) or 'unparse' in column.extensions:
print('''
static void
%(s)s_unparse_%(c)s(struct ovsdb_idl_row *row_)
{
struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName,
'c': columnName})
-
- if type.is_smap():
+ if 'unparse' in column.extensions:
+ print(column.extensions["unparse"])
+ elif type.is_smap():
print(" smap_destroy(&row->%s);" % columnName)
else:
if type.value:
@@ -628,6 +693,8 @@ bool
# Verify functions.
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
print('''
/* Causes the original contents of column "%(c)s" in 'row' to be
* verified as a prerequisite to completing the transaction. That is, if
@@ -663,6 +730,8 @@ void
# Get functions.
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
if column.type.value:
valueParam = ',\n\tenum ovsdb_atomic_type value_type OVS_UNUSED'
valueType = '\n ovs_assert(value_type == %s);' % column.type.value.toAtomicType()
@@ -703,6 +772,8 @@ const struct ovsdb_datum *
# Set functions.
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
type = column.type
comment, members = cMembers(prefix, tableName, columnName,
@@ -817,6 +888,8 @@ void
print("}")
# Update/Delete of partial map column functions
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
type = column.type
if type.is_map():
print('''
@@ -926,6 +999,8 @@ void
# Add clause functions.
for columnName, column in sorted_columns(table):
+ if column.extensions.get('synthetic'):
+ continue
type = column.type
comment, members = cMembers(prefix, tableName, columnName,
@@ -1299,6 +1374,10 @@ void
mutable = "true"
else:
mutable = "false"
+ if column.extensions.get("synthetic"):
+ synthetic = "true"
+ else:
+ synthetic = "false"
type_init = '\n'.join(" " + x
for x in column.type.cInitType("%s_col_%s" % (tableName, columnName), prereqs))
print("""\
@@ -1308,6 +1387,7 @@ void
%(type)s
},
.is_mutable = %(mutable)s,
+ .is_synthetic = %(synthetic)s,
.parse = %(s)s_parse_%(c)s,
.unparse = %(s)s_unparse_%(c)s,
},\n""" % {'P': prefix.upper(),
@@ -1316,6 +1396,7 @@ void
'C': columnName.upper(),
's': structName,
'mutable': mutable,
+ 'synthetic': synthetic,
'type': type_init,
'column_name_in_schema': column.name})
print("};")