def subscribe(self, callback, resource, event): """Subscribe callback for a resource event. The same callback may register for more than one event. :param callback: the callback. It must raise or return a boolean. :param resource: the resource. It must be a valid resource. :param event: the event. It must be a valid event. """ LOG.debug("Subscribe: %(callback)s %(resource)s %(event)s", { 'callback': callback, 'resource': resource, 'event': event }) if resource not in resources.VALID: raise exceptions.Invalid(element='resource', value=resource) if event not in events.VALID: raise exceptions.Invalid(element='event', value=event) callback_id = _get_id(callback) self._callbacks[resource][event][callback_id] = callback # We keep a copy of callbacks to speed the unsubscribe operation. if callback_id not in self._index: self._index[callback_id] = collections.defaultdict(set) self._index[callback_id][resource].add(event)
def unsubscribe(self, callback, resource, event): """Unsubscribe callback from the registry. :param callback: the callback. :param resource: the resource. :param event: the event. """ LOG.debug("Unsubscribe: %(callback)s %(resource)s %(event)s", { 'callback': callback, 'resource': resource, 'event': event }) callback_id = self._find(callback) if not callback_id: LOG.debug("Callback %s not found", callback_id) return if resource and event: del self._callbacks[resource][event][callback_id] self._index[callback_id][resource].discard(event) if not self._index[callback_id][resource]: del self._index[callback_id][resource] if not self._index[callback_id]: del self._index[callback_id] else: value = '%s,%s' % (resource, event) raise exceptions.Invalid(element='resource,event', value=value)
def _validate_resource_type(resource_type): if not resources.is_valid_resource_type(resource_type): raise exceptions.Invalid(element='resource', value=resource_type)