ovs.db.idl: Fix call to ovs.db.parser.Parser constructor.
[sliver-openvswitch.git] / python / ovs / db / idl.py
index 1ee330e..8f3c810 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2010 Nicira Networks
+# Copyright (c) 2009, 2010, 2011 Nicira Networks
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
 import logging
 
 import ovs.jsonrpc
+import ovs.db.parser
 import ovs.db.schema
 from ovs.db import error
 import ovs.ovsuuid
@@ -185,40 +186,35 @@ class Idl:
         for table_name, table_update in table_updates.iteritems():
             table = self.schema.tables.get(table_name)
             if not table:
-                raise error.Error("<table-updates> includes unknown "
-                                  "table \"%s\"" % table_name)
+                raise error.Error('<table-updates> includes unknown '
+                                  'table "%s"' % table_name)
 
             if type(table_update) != dict:
-                raise error.Error("<table-update> for table \"%s\" is not "
-                                  "an object" % table_name, table_update)
+                raise error.Error('<table-update> for table "%s" is not '
+                                  'an object' % table_name, table_update)
 
             for uuid_string, row_update in table_update.iteritems():
                 if not ovs.ovsuuid.UUID.is_valid_string(uuid_string):
-                    raise error.Error("<table-update> for table \"%s\" "
-                                      "contains bad UUID \"%s\" as member "
-                                      "name" % (table_name, uuid_string),
+                    raise error.Error('<table-update> for table "%s" '
+                                      'contains bad UUID "%s" as member '
+                                      'name' % (table_name, uuid_string),
                                       table_update)
                 uuid = ovs.ovsuuid.UUID.from_string(uuid_string)
 
                 if type(row_update) != dict:
-                    raise error.Error("<table-update> for table \"%s\" "
-                                      "contains <row-update> for %s that "
-                                      "is not an object"
+                    raise error.Error('<table-update> for table "%s" '
+                                      'contains <row-update> for %s that '
+                                      'is not an object'
                                       % (table_name, uuid_string))
 
-                old = row_update.get("old", None)
-                new = row_update.get("new", None)
+                parser = ovs.db.parser.Parser(row_update, "row-update")
+                old = parser.get_optional("old", [dict])
+                new = parser.get_optional("new", [dict])
+                parser.finish()
 
-                if old is not None and type(old) != dict:
-                    raise error.Error("\"old\" <row> is not object", old)
-                if new is not None and type(new) != dict:
-                    raise error.Error("\"new\" <row> is not object", new)
-                if (old is not None) + (new is not None) != len(row_update):
-                    raise error.Error("<row-update> contains unexpected "
-                                      "member", row_update)
                 if not old and not new:
-                    raise error.Error("<row-update> missing \"old\" and "
-                                      "\"new\" members", row_update)
+                    raise error.Error('<row-update> missing "old" and '
+                                      '"new" members', row_update)
 
                 if self.__parse_row_update(table, uuid, old, new):
                     self.change_seqno += 1
@@ -226,32 +222,37 @@ class Idl:
     def __parse_row_update(self, table, uuid, old, new):
         """Returns True if a column changed, False otherwise."""
         row = self.data[table.name].get(uuid)
+        changed = False
         if not new:
             # Delete row.
             if row:
                 del self.data[table.name][uuid]
+                changed = True
             else:
                 # XXX rate-limit
                 logging.warning("cannot delete missing row %s from table %s"
                                 % (uuid, table.name))
-                return False
         elif not old:
             # Insert row.
             if not row:
                 row = self.__create_row(table, uuid)
+                changed = True
             else:
                 # XXX rate-limit
                 logging.warning("cannot add existing row %s to table %s"
                                 % (uuid, table.name))
-            self.__modify_row(table, row, new)
+            if self.__modify_row(table, row, new):
+                changed = True
         else:
             if not row:
                 row = self.__create_row(table, uuid)
+                changed = True
                 # XXX rate-limit
                 logging.warning("cannot modify missing row %s in table %s"
                                 % (uuid, table_name))
-            self.__modify_row(table, row, new)
-        return True
+            if self.__modify_row(table, row, new):
+                changed = True
+        return changed
 
     def __modify_row(self, table, row, row_json):
         changed = False
@@ -292,8 +293,6 @@ class Idl:
             self.data[table_name] = {}
 
     def __create_row(self, table, uuid):
-        class Row(object):
-            pass
         row = self.data[table.name][uuid] = Row()
         for column in table.columns.itervalues():
             setattr(row, column.name, ovs.db.data.Datum.default(column.type))
@@ -303,3 +302,10 @@ class Idl:
         """Forces the IDL to drop its connection to the database and reconnect.
         In the meantime, the contents of the IDL will not change."""
         self.session.force_reconnect()
+
+class Row(object):
+    """A row within an Idl.  Data for each column is stored as an attribute
+    with the same name as the column and using an ovs.db.data.Datum as the
+    value."""
+    pass
+