X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=python%2Fovs%2Freconnect.py;h=f1da930a7d4dd36e7e4d32d36c3c71040c4a733b;hb=2dc7590de5e0adae1e332ff84c0c8af264f403b9;hp=8817494686678d3d3ff8eddc65d02ccdbfece1a4;hpb=90d9dcfc12cbfa7ac103ea6d0e38797c10598d57;p=openvswitch diff --git a/python/ovs/reconnect.py b/python/ovs/reconnect.py index 88174946..f1da930a 100644 --- a/python/ovs/reconnect.py +++ b/python/ovs/reconnect.py @@ -1,4 +1,4 @@ -# Copyright (c) 2010, 2011 Nicira Networks +# Copyright (c) 2010, 2011, 2012 Nicira Networks # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,15 +12,19 @@ # 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): """A finite-state machine for connecting and reconnecting to a network @@ -96,9 +100,9 @@ class Reconnect(object): @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_received, fsm.state_entered))) fsm._transition(now, Reconnect.Idle) return PROBE @@ -108,13 +112,15 @@ class Reconnect(object): @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): @@ -139,7 +145,7 @@ 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 @@ -160,16 +166,16 @@ class Reconnect(object): debug level, by default keeping them out of log files. This is appropriate if the connection is one that is expected to be short-lived, so that the log messages are merely distracting. - + If 'quiet' is false, this object logs informational messages at info level. This is the default. - + 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 @@ -177,7 +183,7 @@ class Reconnect(object): def set_name(self, name): """Sets this object's name to 'name'. If 'name' is None, then "void" is used instead. - + The name is used in log messages.""" if name is None: self.name = "void" @@ -235,7 +241,7 @@ class Reconnect(object): if (self.state == Reconnect.Backoff and self.backoff > self.max_backoff): self.backoff = self.max_backoff - + def set_probe_interval(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 @@ -260,7 +266,8 @@ class Reconnect(object): def set_passive(self, passive, now): """Configures this FSM for active or passive mode. In active mode (the default), the FSM is attempting to connect to a remote host. In - passive mode, the FSM is listening for connections from a remote host.""" + passive mode, the FSM is listening for connections from a remote + host.""" if self.passive != passive: self.passive = passive @@ -316,8 +323,8 @@ class Reconnect(object): # 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) @@ -325,8 +332,8 @@ class Reconnect(object): 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) @@ -336,8 +343,8 @@ class Reconnect(object): 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_)) @@ -386,15 +393,15 @@ class Reconnect(object): else: self.info_level("%s: connecting..." % self.name) self._transition(now, Reconnect.ConnectInProgress) - + def listening(self, now): """Tell this FSM that the client is listening for connection attempts. This state last indefinitely until the client reports some change. - + The natural progression from this state is for the client to report that a connection has been accepted or is in progress of being accepted, by calling self.connecting() or self.connected(). - + The client may also report that listening failed (e.g. accept() returned an unexpected error such as ENOMEM) by calling self.listen_error(), in which case the FSM will back off and eventually @@ -407,7 +414,7 @@ class Reconnect(object): def listen_error(self, now, error): """Tell this FSM that the client's attempt to accept a connection failed (e.g. accept() returned an unexpected error such as ENOMEM). - + If the FSM is currently listening (self.listening() was called), it will back off and eventually return ovs.reconnect.CONNECT from self.run() to tell the client to try listening again. If there is an @@ -456,54 +463,56 @@ class Reconnect(object): if connected_before: 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 def run(self, now): """Assesses whether any action should be taken on this FSM. The return value is one of: - + - None: The client need not take any action. - + - Active client, ovs.reconnect.CONNECT: The client should start a connection attempt and indicate this by calling self.connecting(). If the connection attempt has definitely succeeded, it should call self.connected(). If the connection attempt has definitely failed, it should call self.connect_failed(). - + The FSM is smart enough to back off correctly after successful connections that quickly abort, so it is OK to call self.connected() after a low-level successful connection (e.g. connect()) even if the connection might soon abort due to a failure at a high-level (e.g. SSL negotiation failure). - + - Passive client, ovs.reconnect.CONNECT: The client should try to listen for a connection, if it is not already listening. It should call self.listening() if successful, otherwise self.connecting() or reconnected_connect_failed() if the attempt is in progress or definitely failed, respectively. - + A listening passive client should constantly attempt to accept a new connection and report an accepted connection with self.connected(). - + - ovs.reconnect.DISCONNECT: The client should abort the current connection or connection attempt or listen attempt and call self.disconnected() or self.connect_failed() to indicate it. - + - ovs.reconnect.PROBE: The client should send some kind of request to the peer that will elicit a response, to ensure that the 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 - + def wait(self, poller, now): """Causes the next call to poller.block() to wake up when self.run() should be called.""" @@ -560,7 +569,8 @@ class Reconnect(object): stats.msec_since_disconnect = self.get_last_disconnect_elapsed(now) stats.total_connected_duration = self.total_connected_duration if self.is_connected(): - stats.total_connected_duration += self.get_last_connect_elapsed(now) + stats.total_connected_duration += ( + self.get_last_connect_elapsed(now)) stats.n_attempted_connections = self.n_attempted_connections stats.n_successful_connections = self.n_successful_connections stats.state = self.state.name