odp-util: Handle ipv6 in set nw action.
[openvswitch] / python / ovs / db / idl.py
index a06e9ec1215dd8e79e5196bd6cf425972294a527..6150a02e10419ce417c6aaa64dc298e1c9c574a3 100644 (file)
@@ -12,7 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
 import uuid
 
 import ovs.jsonrpc
@@ -21,6 +20,9 @@ import ovs.db.schema
 from ovs.db import error
 import ovs.ovsuuid
 import ovs.poller
+import ovs.vlog
+
+vlog = ovs.vlog.Vlog("idl")
 
 __pychecker__ = 'no-classattr no-objattrs'
 
@@ -173,8 +175,8 @@ class Idl:
                     self.__clear()
                     self.__parse_update(msg.result)
                 except error.Error, e:
-                    logging.error("%s: parse error in received schema: %s"
-                                  % (self._session.get_name(), e))
+                    vlog.err("%s: parse error in received schema: %s"
+                              % (self._session.get_name(), e))
                     self.__error()
             elif (msg.type == ovs.jsonrpc.Message.T_REPLY
                   and self._lock_request_id is not None
@@ -200,9 +202,9 @@ class Idl:
             else:
                 # This can happen if a transaction is destroyed before we
                 # receive the reply, so keep the log level low.
-                logging.debug("%s: received unexpected %s message"
-                              % (self._session.get_name(),
-                                 ovs.jsonrpc.Message.type_to_string(msg.type)))
+                vlog.dbg("%s: received unexpected %s message"
+                         % (self._session.get_name(),
+                             ovs.jsonrpc.Message.type_to_string(msg.type)))
 
         return initial_change_seqno != self.change_seqno
 
@@ -319,8 +321,8 @@ class Idl:
         try:
             self.__do_parse_update(update)
         except error.Error, e:
-            logging.error("%s: error parsing update: %s"
-                          % (self._session.get_name(), e))
+            vlog.err("%s: error parsing update: %s"
+                     % (self._session.get_name(), e))
 
     def __do_parse_update(self, table_updates):
         if type(table_updates) != dict:
@@ -374,8 +376,8 @@ class Idl:
                 changed = True
             else:
                 # XXX rate-limit
-                logging.warning("cannot delete missing row %s from table %s"
-                                % (uuid, table.name))
+                vlog.warn("cannot delete missing row %s from table %s"
+                          % (uuid, table.name))
         elif not old:
             # Insert row.
             if not row:
@@ -383,8 +385,8 @@ class Idl:
                 changed = True
             else:
                 # XXX rate-limit
-                logging.warning("cannot add existing row %s to table %s"
-                                % (uuid, table.name))
+                vlog.warn("cannot add existing row %s to table %s"
+                          % (uuid, table.name))
             if self.__row_update(table, row, new):
                 changed = True
         else:
@@ -392,8 +394,8 @@ class Idl:
                 row = self.__create_row(table, uuid)
                 changed = True
                 # XXX rate-limit
-                logging.warning("cannot modify missing row %s in table %s"
-                                % (uuid, table.name))
+                vlog.warn("cannot modify missing row %s in table %s"
+                          % (uuid, table.name))
             if self.__row_update(table, row, new):
                 changed = True
         return changed
@@ -404,16 +406,16 @@ class Idl:
             column = table.columns.get(column_name)
             if not column:
                 # XXX rate-limit
-                logging.warning("unknown column %s updating table %s"
-                                % (column_name, table.name))
+                vlog.warn("unknown column %s updating table %s"
+                          % (column_name, table.name))
                 continue
 
             try:
                 datum = ovs.db.data.Datum.from_json(column.type, datum_json)
             except error.Error, e:
                 # XXX rate-limit
-                logging.warning("error parsing column %s in table %s: %s"
-                                % (column_name, table.name, e))
+                vlog.warn("error parsing column %s in table %s: %s"
+                          % (column_name, table.name, e))
                 continue
 
             if datum != row._data[column_name]:
@@ -439,7 +441,7 @@ class Idl:
     def __txn_abort_all(self):
         while self._outstanding_txns:
             txn = self._outstanding_txns.popitem()[1]
-            txn._status = Transaction.TRY_AGAIN
+            txn._status = Transaction.AGAIN_WAIT
 
     def __txn_process_reply(self, msg):
         txn = self._outstanding_txns.pop(msg.id, None)
@@ -548,8 +550,8 @@ class Row(object):
                                                   _row_to_uuid)
         except error.Error, e:
             # XXX rate-limit
-            logging.error("attempting to write bad value to column %s (%s)"
-                          % (column_name, e))
+            vlog.err("attempting to write bad value to column %s (%s)"
+                     % (column_name, e))
             return
         self._idl.txn._write(self, column, datum)
 
@@ -559,7 +561,9 @@ class Row(object):
         if 'column_name' changed in this row (or if this row was deleted)
         between the time that the IDL originally read its contents and the time
         that the transaction commits, then the transaction aborts and
-        Transaction.commit() returns Transaction.TRY_AGAIN.
+        Transaction.commit() returns Transaction.AGAIN_WAIT or
+        Transaction.AGAIN_NOW (depending on whether the database change has
+        already been received).
 
         The intention is that, to ensure that no transaction commits based on
         dirty reads, an application should call Row.verify() on each data item
@@ -618,9 +622,12 @@ class Transaction(object):
     INCOMPLETE = "incomplete"    # Commit in progress, please wait.
     ABORTED = "aborted"          # ovsdb_idl_txn_abort() called.
     SUCCESS = "success"          # Commit successful.
-    TRY_AGAIN = "try again"      # Commit failed because a "verify" operation
+    AGAIN_WAIT = "wait then try again"
+                                 # Commit failed because a "verify" operation
                                  # reported an inconsistency, due to a network
-                                 # problem, or other transient failure.
+                                 # problem, or other transient failure.  Wait
+                                 # for a change, then try again.
+    AGAIN_NOW = "try again now"  # Same as AGAIN_WAIT but try again right away.
     NOT_LOCKED = "not locked"    # Server hasn't given us the lock yet.
     ERROR = "error"              # Commit failed due to a hard error.
 
@@ -655,6 +662,7 @@ class Transaction(object):
         self._status = Transaction.UNCOMMITTED
         self._error = None
         self._comments = []
+        self._commit_seqno = self.idl.change_seqno
 
         self._inc_table = None
         self._inc_column = None
@@ -825,7 +833,7 @@ class Transaction(object):
                 self.idl._outstanding_txns[self._request_id] = self
                 self._status = Transaction.INCOMPLETE
             else:
-                self._status = Transaction.TRY_AGAIN
+                self._status = Transaction.AGAIN_WAIT
 
         self.__disassemble()
         return self._status
@@ -936,7 +944,7 @@ class Transaction(object):
             self._status = Transaction.ERROR
         elif type(msg.result) not in (list, tuple):
             # XXX rate-limit
-            logging.warning('reply to "transact" is not JSON array')
+            vlog.warn('reply to "transact" is not JSON array')
         else:
             hard_errors = False
             soft_errors = False
@@ -965,8 +973,7 @@ class Transaction(object):
                     hard_errors = True
                     self.__set_error_json(op)
                     # XXX rate-limit
-                    logging.warning("operation reply is not JSON null or "
-                                    "object")
+                    vlog.warn("operation reply is not JSON null or object")
 
             if not soft_errors and not hard_errors and not lock_errors:
                 if self._inc_table and not self.__process_inc_reply(ops):
@@ -981,7 +988,10 @@ class Transaction(object):
             elif lock_errors:
                 self._status = Transaction.NOT_LOCKED
             elif soft_errors:
-                self._status = Transaction.TRY_AGAIN
+                if self._commit_seqno == self.idl.change_seqno:
+                    self._status = Transaction.AGAIN_WAIT
+                else:
+                    self._status = Transaction.AGAIN_NOW
             else:
                 self._status = Transaction.SUCCESS
 
@@ -989,11 +999,11 @@ class Transaction(object):
     def __check_json_type(json, types, name):
         if not json:
             # XXX rate-limit
-            logging.warning("%s is missing" % name)
+            vlog.warn("%s is missing" % name)
             return False
         elif type(json) not in types:
             # XXX rate-limit
-            logging.warning("%s has unexpected type %s" % (name, type(json)))
+            vlog.warn("%s has unexpected type %s" % (name, type(json)))
             return False
         else:
             return True
@@ -1001,9 +1011,9 @@ class Transaction(object):
     def __process_inc_reply(self, ops):
         if self._inc_index + 2 > len(ops):
             # XXX rate-limit
-            logging.warning("reply does not contain enough operations for "
-                            "increment (has %d, needs %d)" %
-                            (len(ops), self._inc_index + 2))
+            vlog.warn("reply does not contain enough operations for "
+                      "increment (has %d, needs %d)" %
+                      (len(ops), self._inc_index + 2))
 
         # We know that this is a JSON object because the loop in
         # __process_reply() already checked.
@@ -1014,8 +1024,7 @@ class Transaction(object):
             return False
         if count != 1:
             # XXX rate-limit
-            logging.warning('"mutate" reply "count" is %d instead of 1'
-                            % count)
+            vlog.warn('"mutate" reply "count" is %d instead of 1' % count)
             return False
 
         select = ops[self._inc_index + 1]
@@ -1025,8 +1034,8 @@ class Transaction(object):
             return False
         if len(rows) != 1:
             # XXX rate-limit
-            logging.warning('"select" reply "rows" has %d elements '
-                            'instead of 1' % len(rows))
+            vlog.warn('"select" reply "rows" has %d elements '
+                      'instead of 1' % len(rows))
             return False
         row = rows[0]
         if not Transaction.__check_json_type(row, (dict,),
@@ -1042,9 +1051,9 @@ class Transaction(object):
     def __process_insert_reply(self, insert, ops):
         if insert.op_index >= len(ops):
             # XXX rate-limit
-            logging.warning("reply does not contain enough operations "
-                            "for insert (has %d, needs %d)"
-                            % (len(ops), insert.op_index))
+            vlog.warn("reply does not contain enough operations "
+                      "for insert (has %d, needs %d)"
+                      % (len(ops), insert.op_index))
             return False
 
         # We know that this is a JSON object because the loop in
@@ -1059,7 +1068,7 @@ class Transaction(object):
             uuid_ = ovs.ovsuuid.from_json(json_uuid)
         except error.Error:
             # XXX rate-limit
-            logging.warning('"insert" reply "uuid" is not a JSON UUID')
+            vlog.warn('"insert" reply "uuid" is not a JSON UUID')
             return False
 
         insert.real = uuid_