def _state_loop(self):
     # TODO (NM) Arrange for _running to be set to false and stopping the katcp client
     # if this loop exits a
     is_connected = self.katcp_client.is_connected
     while self._running:
         self._logger.debug('Sending intial state')
         yield self._send_state(connected=is_connected(), synced=False,
                                model_changed=False, data_synced=False)
         try:
             yield self.katcp_client.until_connected()
             self._logger.debug('Sending post-connected  state')
             yield self._send_state(connected=is_connected(), synced=False,
                                    model_changed=False, data_synced=False)
             yield until_any(self.katcp_client.until_protocol(),
                             self._disconnected.until_set())
             if self.initial_inspection:
                 if not is_connected():
                     continue
                 model_changes = yield self.inspect()
                 model_changed = bool(model_changes)
                 synced = not model_changed
                 yield self._send_state(
                     connected=True, synced=False,
                     model_changed=model_changed, data_synced=True,
                     model_changes=model_changes)
             else:
                 self.initial_inspection = True
             if not is_connected():
                 continue
             # We waited for the previous _send_state call (and user callbacks) to
             # complete before we change the state to synced=True
             yield self._send_state(connected=True, synced=True,
                                    model_changed=False, data_synced=True)
             yield until_any(self._interface_changed.until_set(),
                             self._disconnected.until_set())
             self._interface_changed.clear()
             continue
             # Next loop through should cause re-inspection and handle state updates
         except SyncError, e:
             retry_wait_time = self.reconnect_timeout
             self._logger.warn("Error syncing with device : {0!s} "
                               "'Retrying in {1}s.".format(e, retry_wait_time))
             yield katcp.core.until_later(retry_wait_time)
             # TODO (NM) Perhaps maintain count of unsuccessful attempts, and reconnect
             # if too many happen. Perhaps also integrate exponential-backoff stuff
             # here? Or outsource to a user-supplied class or callback?
             continue
         except Exception:
             retry_wait_time = self.reconnect_timeout
             self._logger.exception(
                 'Unhandled exception in client-sync loop. Triggering disconnect and '
                 'Retrying in {}s.'
                 .format(retry_wait_time))
             self.katcp_client.disconnect()
             yield katcp.core.until_later(retry_wait_time)
             continue
Exemple #2
0
    def _state_loop(self):
        # TODO (NM) Arrange for _running to be set to false and stopping the katcp client
        # if this loop exits
        self.resync_delay = ExponentialRandomBackoff(
            self.initial_resync_timeout, self.max_resync_timeout)

        is_connected = self.katcp_client.is_connected
        last_sync_failed = False
        while self._running:
            self._logger.debug('{}: Sending initial state'.format(
                self.bind_address_string))
            yield self._send_state(connected=is_connected(),
                                   synced=False,
                                   model_changed=False,
                                   data_synced=False)
            try:
                yield self.katcp_client.until_connected()
                self._logger.debug('{}: Sending post-connected state'.format(
                    self.bind_address_string))
                yield self._send_state(connected=is_connected(),
                                       synced=False,
                                       model_changed=False,
                                       data_synced=False)
                yield until_any(self.katcp_client.until_protocol(),
                                self._disconnected.until_set())
                # TODO NM 2016-10-21 The naming of this attribute is incredibly
                # confusing, we need to think about what "initial_inspection" is
                # and how it is supposed to be handled
                if self.initial_inspection:
                    if not is_connected():
                        continue
                    model_changes = yield self.inspect()
                    model_changed = bool(model_changes)
                    self._logger.debug('{}: Sending data-synced state'.format(
                        self.bind_address_string))
                    yield self._send_state(connected=True,
                                           synced=False,
                                           model_changed=model_changed,
                                           data_synced=True,
                                           model_changes=model_changes)
                else:
                    self.initial_inspection = True
                if not is_connected():
                    continue

                # TODO NM 2017-07-21 for CB-1466 (async dev handler) we need to
                # check if the device needs a re-sync after the state change
                # callback, since some proxy actions can result in the device
                # issuing an #interface-changed between _send_state() above and
                # here.

                # We waited for the previous _send_state call (and user callbacks) to
                # complete before we change the state to synced=True
                self._logger.debug('{}: Sending synced state'.format(
                    self.bind_address_string))
                yield self._send_state(connected=True,
                                       synced=True,
                                       model_changed=False,
                                       data_synced=True)
                if last_sync_failed:
                    self._logger.warn(
                        'Succesfully resynced with {} after failure'.format(
                            self.bind_address_string))
                    last_sync_failed = False
                yield until_any(self._interface_changed.until_set(),
                                self._disconnected.until_set())
                self._logger.debug(
                    'in _state_loop: interface_changed=%s,'
                    ' is_connected=%s', self._interface_changed.is_set(),
                    self._disconnected.is_set())
                self._interface_changed.clear()
                continue
                # Next loop through should cause re-inspection and handle state updates
            except SyncError, e:
                last_sync_failed = True
                retry_wait_time = self.resync_delay.delay
                self.resync_delay.failed()
                self._logger.warn(
                    "Error syncing with device {}: {!s} 'Retrying in {}s.".
                    format(self.bind_address_string, e, retry_wait_time))
                yield katcp.core.until_later(retry_wait_time)
                # TODO (NM) Perhaps maintain count of unsuccessful attempts, and reconnect
                # if too many happen. Perhaps also integrate exponential-backoff stuff
                # here? Or outsource to a user-supplied class or callback?
                continue
            except Exception:
                last_sync_failed = True
                retry_wait_time = self.resync_delay.delay
                self.resync_delay.failed()
                self._logger.exception(
                    'Unhandled exception in client-sync loop. Triggering disconnect and '
                    'Retrying in {}s.'.format(retry_wait_time))
                self.katcp_client.disconnect()
                yield katcp.core.until_later(retry_wait_time)
                continue
    def _state_loop(self):
        # TODO (NM) Arrange for _running to be set to false and stopping the katcp client
        # if this loop exits
        self.resync_delay = ExponentialRandomBackoff(
            self.initial_resync_timeout, self.max_resync_timeout)

        is_connected = self.katcp_client.is_connected
        last_sync_failed = False
        while self._running:
            self._logger.debug('{}: Sending intial state'
                               .format(self.bind_address_string))
            yield self._send_state(connected=is_connected(), synced=False,
                                   model_changed=False, data_synced=False)
            try:
                yield self.katcp_client.until_connected()
                self._logger.debug('{}: Sending post-connected state'
                                   .format(self.bind_address_string))
                yield self._send_state(connected=is_connected(), synced=False,
                                       model_changed=False, data_synced=False)
                yield until_any(self.katcp_client.until_protocol(),
                                self._disconnected.until_set())
                # TODO NM 2016-10-21 The naming of this attribute is incredibly
                # confusing, we need to think about what "initial_inspection"
                # how supposed to be handled
                if self.initial_inspection:
                    if not is_connected():
                        continue
                    model_changes = yield self.inspect()
                    model_changed = bool(model_changes)
                    self._logger.debug('{}: Sending data-synced state'
                                       .format(self.bind_address_string))
                    yield self._send_state(
                        connected=True, synced=False,
                        model_changed=model_changed, data_synced=True,
                        model_changes=model_changes)
                else:
                    self.initial_inspection = True
                if not is_connected():
                    continue
                # We waited for the previous _send_state call (and user callbacks) to
                # complete before we change the state to synced=True
                self._logger.debug('{}: Sending synced state'
                                   .format(self.bind_address_string))
                yield self._send_state(connected=True, synced=True,
                                       model_changed=False, data_synced=True)
                if last_sync_failed:
                    self._logger.warn(
                        'Succesfully resynced with {} after failure'
                        .format(self.bind_address_string))
                    last_sync_failed = False
                yield until_any(self._interface_changed.until_set(),
                                self._disconnected.until_set())
                self._logger.debug('in _state_loop: interface_changed=%s,'
                        ' is_connected=%s', self._interface_changed.is_set(),
                        self._disconnected.is_set())
                self._interface_changed.clear()
                continue
                # Next loop through should cause re-inspection and handle state updates
            except SyncError, e:
                last_sync_failed = True
                retry_wait_time = self.resync_delay.delay
                self.resync_delay.failed()
                self._logger.warn(
                    "Error syncing with device {}: {!s} 'Retrying in {}s."
                    .format(
                        self.bind_address_string,
                        e, retry_wait_time))
                yield katcp.core.until_later(retry_wait_time)
                # TODO (NM) Perhaps maintain count of unsuccessful attempts, and reconnect
                # if too many happen. Perhaps also integrate exponential-backoff stuff
                # here? Or outsource to a user-supplied class or callback?
                continue
            except Exception:
                last_sync_failed = True
                retry_wait_time = self.resync_delay.delay
                self.resync_delay.failed()
                self._logger.exception(
                    'Unhandled exception in client-sync loop. Triggering disconnect and '
                    'Retrying in {}s.'
                    .format(retry_wait_time))
                self.katcp_client.disconnect()
                yield katcp.core.until_later(retry_wait_time)
                continue