コード例 #1
0
    def __init__(self, fs, ignore_config=None, monitor_class=None):
        self.listener_map = {}

        self.log = logging.getLogger('ubuntuone.SyncDaemon.EQ')
        self.fs = fs

        if monitor_class is None:
            # use the default class returned by platform
            self.monitor = FilesystemMonitor(self, fs, ignore_config)
        else:
            self.monitor = monitor_class(self, fs, ignore_config)

        self.dispatching = False
        self.dispatch_queue = collections.deque()
        self._have_empty_eq_cback = False
        self.empty_event_queue_callbacks = set()
        self.ignored_base_exception = Exception
コード例 #2
0
class EventQueue(object):
    """Manages the events from different sources and distributes them."""

    def __init__(self, fs, ignore_config=None, monitor_class=None):
        self.listener_map = {}

        self.log = logging.getLogger('ubuntuone.SyncDaemon.EQ')
        self.fs = fs

        if monitor_class is None:
            # use the default class returned by platform
            self.monitor = FilesystemMonitor(self, fs, ignore_config)
        else:
            self.monitor = monitor_class(self, fs, ignore_config)

        self.dispatching = False
        self.dispatch_queue = collections.deque()
        self._have_empty_eq_cback = False
        self.empty_event_queue_callbacks = set()
        self.ignored_base_exception = Exception

    def add_to_mute_filter(self, event, **info):
        """Add info to mute filter in the processor."""
        self.monitor.add_to_mute_filter(event, **info)

    def rm_from_mute_filter(self, event, **info):
        """Remove info to mute filter in the processor."""
        self.monitor.rm_from_mute_filter(event, **info)

    def add_empty_event_queue_callback(self, callback):
        """Add a callback for when the even queue has no more events."""
        self._have_empty_eq_cback = True
        self.empty_event_queue_callbacks.add(callback)
        if not self.dispatching and not self.dispatch_queue:
            if callable(callback):
                callback()

    def remove_empty_event_queue_callback(self, callback):
        """Remove the callback."""
        self.empty_event_queue_callbacks.remove(callback)
        if not self.empty_event_queue_callbacks:
            self._have_empty_eq_cback = False

    @defer.inlineCallbacks
    def shutdown(self):
        """Make the monitor shutdown."""
        yield self.monitor.shutdown()
        # clean up all registered listeners
        if len(self.listener_map.items()) > 0:
            for k, v in self.listener_map.items():
                v.clear()
                del self.listener_map[k]

    def rm_watch(self, dirpath):
        """Remove watch from a dir."""
        self.monitor.rm_watch(dirpath)

    def add_watch(self, dirpath):
        """Add watch to a dir."""
        return self.monitor.add_watch(dirpath)

    def add_watches_to_udf_ancestors(self, volume):
        """Add a inotify watch to volume's ancestors if it's an UDF."""
        # This is a platform dependent operation since there are cases in
        # which the watches do not have to be added (On windows we do not
        # have to add them since we have an opened handle.)
        # finally, check that UDF is ok in disk
        if not access(volume.path):
            # if we cannot access the UDF lets return false and do
            # nothing
            return defer.succeed(False)
        return self.monitor.add_watches_to_udf_ancestors(volume)

    def unsubscribe(self, obj):
        """Remove the callback object from the listener queue.

        @param obj: the callback object to remove from the queue.
        """
        for k, v in self.listener_map.items():
            v.pop(obj, None)
            if not v:
                del self.listener_map[k]

    def subscribe(self, obj):
        """Store the callback object to whom push the events when received.

        @param obj: the callback object to add to the listener queue.

        These objects should provide a 'handle_FOO' to receive the FOO
        events (replace FOO with the desired event).
        """
        for event_name in EVENTS.keys():
            meth_name = "handle_" + event_name
            method = self._get_listener_method(obj, meth_name, event_name)
            if method is not None:
                self.listener_map.setdefault(event_name, {})[obj] = method

    def push(self, event_name, **kwargs):
        """Receives a push for all events.

        The signature for each event is forced on each method, not in this
        'push' arguments.
        """
        log_msg = "push_event: %s, kwargs: %s"
        if event_name.endswith('DELETE'):
            # log every DELETE in INFO level
            self.log.info(log_msg, event_name, kwargs)
        elif event_name == 'SYS_USER_CONNECT':
            self.log.debug(log_msg, event_name, '*')
        else:
            self.log.debug(log_msg, event_name, kwargs)

        # check if we are currently dispatching an event
        self.dispatch_queue.append((event_name, kwargs))
        if not self.dispatching:
            self.dispatching = True
            while True:
                try:
                    event_name, kwargs = self.dispatch_queue.popleft()
                    self._dispatch(event_name, **kwargs)
                except IndexError:
                    self.dispatching = False
                    if self._have_empty_eq_cback:
                        for cback in self.empty_event_queue_callbacks.copy():
                            cback()
                    break

    def _dispatch(self, event_name, **kwargs):
        """ push the event to all listeners. """
        try:
            listeners = self.listener_map[event_name]
        except KeyError:
            # no listener for this
            return

        # check listeners to see if have the proper method, and call it
        for listener, method in listeners.items():
            try:
                method(**kwargs)
            except self.ignored_base_exception:
                self.log.exception("Error encountered while handling: %s "
                                   "in %s", event_name, listener)

    def _get_listener_method(self, listener, method_name, event_name):
        """ returns the method named method_name or hanlde_default from the
        listener. Or None if the methods are not defined in the listener.
        """
        method = getattr(listener, method_name, None)
        if method is None:
            method = getattr(listener, DEFAULT_HANDLER, None)
            if method is not None:
                method = functools.partial(method, event_name)
        return method

    def is_frozen(self):
        """Checks if there's something frozen."""
        return self.monitor.is_frozen()

    def freeze_begin(self, path):
        """Puts in hold all the events for this path."""
        self.monitor.freeze_begin(path)

    def freeze_rollback(self):
        """Unfreezes the frozen path, reseting to idle state."""
        self.monitor.freeze_rollback()

    def freeze_commit(self, events):
        """Unfreezes the frozen path, sending received events if not dirty.

        If events for that path happened:
            - return True
        else:
            - push the here received events, return False
        """
        return self.monitor.freeze_commit(events)