1
2
3
4
5
6
7
8
9
10
11
12
13 import logging
14 log = logging.getLogger('zen.ZenHub')
15
16 from zope.component.event import objectEventNotify
17 from zope.interface import implements
18 from zope.interface.advice import addClassAdvisor
19 from zope.component import provideHandler
20 from zope.component.interfaces import ObjectEvent
21 from ZODB.utils import u64
22 from twisted.internet import defer, reactor
23
24 from Products.ZenModel.Device import Device
25 from Products.ZenModel.DeviceComponent import DeviceComponent
26 from time import time
27 from Products.ZenRelations.PrimaryPathObjectManager import PrimaryPathObjectManager
28 from Products.ZenHub.interfaces import IUpdateEvent, IDeletionEvent
35
39
43
44
45 -def _remove(_ignored, oid, queue):
46 """
47 We don't want bad oids hanging around forever.
48 """
49 queue.remove(oid)
50
53 """
54 Send to all the services that care by firing events.
55 """
56 d = defer.Deferred()
57
58 def inner(_ignored):
59 try:
60 if dmd.pauseHubNotifications:
61 log.debug('notifications are currently paused')
62 return
63
64
65 obj = dmd._p_jar[oid]
66
67
68 if (isinstance(obj, PrimaryPathObjectManager)
69 or isinstance(obj, DeviceComponent)):
70 try:
71
72 obj = obj.__of__(dmd).primaryAq()
73 except (AttributeError, KeyError), ex:
74
75
76 log.debug("Notifying services that %r has been deleted" % obj)
77 event = DeletionEvent(obj, oid)
78 else:
79
80 log.debug("Notifying services that %r has been updated" % obj)
81 event = UpdateEvent(obj, oid)
82
83 objectEventNotify(event)
84
85 return oid
86 finally:
87 queue.remove(ioid)
88 d.addCallback(inner)
89
90 reactor.callLater(0, d.callback, True)
91 return d
92
96 i = 0
97 for i, oid in enumerate(oids):
98 ioid = u64(oid)
99
100
101 if queue.insert(ioid):
102
103 d = _dispatch(dmd, oid, ioid, queue)
104 yield d
105 defer.returnValue(i)
106
109 """
110 Given a particular event interface, returns a decorator factory that may be
111 used to create decorators for methods causing those methods, when bound, to
112 be registered as object event subscribers.
113
114 @param eventtype: The event interface to which the subscribers should
115 listen.
116 """
117 def factory(*types):
118 """
119 The eventtype-specific decorator factory. Calling this factory both
120 produces a decorator and wraps the __init__ of the class of the
121 decorated method with a function that registers the handlers.
122 """
123
124
125
126 _f = {}
127
128 def decorator(f):
129 """
130 The decorator. All it does is print a log message, then call the
131 original function.
132 """
133 def inner(self, obj, event):
134
135 fname = '.'.join((self.__class__.__name__, f.__name__))
136 log.debug('%s is interested in %r for %r' % (fname, event, obj))
137
138
139 return f(self, obj, event)
140
141
142
143 _f[f.__name__] = 1
144
145
146 return inner
147
148 def advisor(cls):
149 """
150 A class advisor that is called after the class is created. We use
151 this to wrap __init__ in a function that registers any handlers
152 created via this factory, which are stored on the class.
153 """
154
155
156 fname = _f.keys()[0]
157 cls.__registered = getattr(cls, '__registered', {})
158
159
160 if fname not in cls.__registered or not issubclass(cls, tuple(cls.__registered[fname])):
161
162 def registerHandlers(f):
163 def __init__(self, *args, **kwargs):
164
165
166 f(self, *args, **kwargs)
167 handler = getattr(self, fname)
168 for t in types:
169
170
171
172 provideHandler(handler, (t, eventtype))
173
174
175 return __init__
176
177
178
179 cls.__init__ = registerHandlers(cls.__init__)
180
181 cls.__registered.setdefault(fname, []).append(cls)
182
183
184
185 return cls
186
187
188 addClassAdvisor(advisor)
189
190
191 return decorator
192
193 return factory
194
195
196
197 onUpdate = _listener_decorator_factory(IUpdateEvent)
198 onDelete = _listener_decorator_factory(IDeletionEvent)
199