-# Copyright (c) 2010, 2011 Nicira Networks
+# Copyright (c) 2010, 2011, 2012 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# See the License for the specific language governing permissions and
# limitations under the License.
-import logging
import os
+import ovs.vlog
+import ovs.util
+
# Values returned by Reconnect.run()
CONNECT = 'connect'
DISCONNECT = 'disconnect'
PROBE = 'probe'
-EOF = -1
+EOF = ovs.util.EOF
+vlog = ovs.vlog.Vlog("reconnect")
class Reconnect(object):
@staticmethod
def deadline(fsm):
if fsm.probe_interval:
- base = max(fsm.last_received, fsm.state_entered)
+ base = max(fsm.last_activity, fsm.state_entered)
return base + fsm.probe_interval
return None
@staticmethod
def run(fsm, now):
- logging.debug("%s: idle %d ms, sending inactivity probe"
- % (fsm.name,
- now - max(fsm.last_received, fsm.state_entered)))
+ vlog.dbg("%s: idle %d ms, sending inactivity probe"
+ % (fsm.name,
+ now - max(fsm.last_activity, fsm.state_entered)))
fsm._transition(now, Reconnect.Idle)
return PROBE
@staticmethod
def deadline(fsm):
- return fsm.state_entered + fsm.probe_interval
+ if fsm.probe_interval:
+ return fsm.state_entered + fsm.probe_interval
+ return None
@staticmethod
def run(fsm, now):
- logging.error("%s: no response to inactivity probe after %.3g "
- "seconds, disconnecting"
- % (fsm.name, (now - fsm.state_entered) / 1000.0))
+ vlog.err("%s: no response to inactivity probe after %.3g "
+ "seconds, disconnecting"
+ % (fsm.name, (now - fsm.state_entered) / 1000.0))
return DISCONNECT
class Reconnect(object):
self.max_backoff = 8000
self.probe_interval = 5000
self.passive = False
- self.info_level = logging.info
+ self.info_level = vlog.info
self.state = Reconnect.Void
self.state_entered = now
self.backoff = 0
- self.last_received = now
+ self.last_activity = now
self.last_connected = None
self.last_disconnected = None
self.max_tries = None
This setting has no effect on the log level of debugging, warning, or
error messages."""
if quiet:
- self.info_level = logging.debug
+ self.info_level = vlog.dbg
else:
- self.info_level = logging.info
+ self.info_level = vlog.info
def get_name(self):
return self.name
"""Returns the "probe interval" in milliseconds. If this is zero, it
disables the connection keepalive feature. If it is nonzero, then if
the interval passes while the FSM is connected and without
- self.received() being called, self.run() returns ovs.reconnect.PROBE.
- If the interval passes again without self.received() being called,
+ self.activity() being called, self.run() returns ovs.reconnect.PROBE.
+ If the interval passes again without self.activity() being called,
self.run() returns ovs.reconnect.DISCONNECT."""
return self.probe_interval
"""Sets the "probe interval" to 'probe_interval', in milliseconds. If
this is zero, it disables the connection keepalive feature. If it is
nonzero, then if the interval passes while this FSM is connected and
- without self.received() being called, self.run() returns
+ without self.activity() being called, self.run() returns
ovs.reconnect.PROBE. If the interval passes again without
- self.received() being called, self.run() returns
+ self.activity() being called, self.run() returns
ovs.reconnect.DISCONNECT.
If 'probe_interval' is nonzero, then it will be forced to a value of at
# Report what happened
if self.state in (Reconnect.Active, Reconnect.Idle):
if error > 0:
- logging.warning("%s: connection dropped (%s)"
- % (self.name, os.strerror(error)))
+ vlog.warn("%s: connection dropped (%s)"
+ % (self.name, os.strerror(error)))
elif error == EOF:
self.info_level("%s: connection closed by peer"
% self.name)
self.info_level("%s: connection dropped" % self.name)
elif self.state == Reconnect.Listening:
if error > 0:
- logging.warning("%s: error listening for connections (%s)"
- % (self.name, os.strerror(error)))
+ vlog.warn("%s: error listening for connections (%s)"
+ % (self.name, os.strerror(error)))
else:
self.info_level("%s: error listening for connections"
% self.name)
else:
type_ = "connection"
if error > 0:
- logging.warning("%s: %s attempt failed (%s)"
- % (self.name, type_, os.strerror(error)))
+ vlog.warn("%s: %s attempt failed (%s)"
+ % (self.name, type_, os.strerror(error)))
else:
self.info_level("%s: %s attempt timed out"
% (self.name, type_))
# Back off
if (self.state in (Reconnect.Active, Reconnect.Idle) and
- (self.last_received - self.last_connected >= self.backoff or
+ (self.last_activity - self.last_connected >= self.backoff or
self.passive)):
if self.passive:
self.backoff = 0
"""Tell this FSM that the connection was successful.
The FSM will start the probe interval timer, which is reset by
- self.received(). If the timer expires, a probe will be sent (by
+ self.activity(). If the timer expires, a probe will be sent (by
returning ovs.reconnect.PROBE from self.run(). If the timer expires
again without being reset, the connection will be aborted (by returning
ovs.reconnect.DISCONNECT from self.run()."""
self.connecting(now)
self.disconnected(now, error)
- def received(self, now):
- """Tell this FSM that some data was received. This resets the probe
- interval timer, so that the connection is known not to be idle."""
+ def activity(self, now):
+ """Tell this FSM that some activity occurred on the connection. This
+ resets the probe interval timer, so that the connection is known not to
+ be idle."""
if self.state != Reconnect.Active:
self._transition(now, Reconnect.Active)
- self.last_received = now
+ self.last_activity = now
def _transition(self, now, state):
if self.state == Reconnect.ConnectInProgress:
self.total_connected_duration += now - self.last_connected
self.seqno += 1
- logging.debug("%s: entering %s" % (self.name, state.name))
+ vlog.dbg("%s: entering %s" % (self.name, state.name))
self.state = state
self.state_entered = now
connection is indeed in working order. (This will only be
returned if the "probe interval" is nonzero--see
self.set_probe_interval())."""
- if now >= self.state.deadline(self):
+
+ deadline = self.state.deadline(self)
+ if deadline is not None and now >= deadline:
return self.state.run(self, now)
else:
return None
stats.creation_time = self.creation_time
stats.last_connected = self.last_connected
stats.last_disconnected = self.last_disconnected
- stats.last_received = self.last_received
+ stats.last_activity = self.last_activity
stats.backoff = self.backoff
stats.seqno = self.seqno
stats.is_connected = self.is_connected()