| Trees | Indices | Help |
|
|---|
|
|
1 ###########################################################################
2 #
3 # This program is part of Zenoss Core, an open source monitoring platform.
4 # Copyright (C) 2007, Zenoss Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License version 2 or (at your
8 # option) any later version as published by the Free Software Foundation.
9 #
10 # For complete information please visit: http://www.zenoss.com/oss/
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
38 implements(IUpdateEvent)
39
42 implements(IDeletionEvent)
43
50
53 """
54 Send to all the services that care by firing events.
55 """
56 d = defer.Deferred()
57 # Closure to use as a callback
58 def inner(_ignored):
59 try:
60 if dmd.pauseHubNotifications:
61 log.debug('notifications are currently paused')
62 return
63
64 # Go pull the object out of the database
65 obj = dmd._p_jar[oid]
66 # Don't bother with all the catalog stuff; we're depending on primaryAq
67 # existing anyway, so only deal with it if it actually has primaryAq.
68 if (isinstance(obj, PrimaryPathObjectManager)
69 or isinstance(obj, DeviceComponent)):
70 try:
71 # Try to get the object
72 obj = obj.__of__(dmd).primaryAq()
73 except (AttributeError, KeyError), ex:
74 # Object has been removed from its primary path (i.e. was
75 # deleted), so make a DeletionEvent
76 log.debug("Notifying services that %r has been deleted" % obj)
77 event = DeletionEvent(obj, oid)
78 else:
79 # Object was updated, so make an UpdateEvent
80 log.debug("Notifying services that %r has been updated" % obj)
81 event = UpdateEvent(obj, oid)
82 # Fire the event for all interested services to pick up
83 objectEventNotify(event)
84 # Return the oid, although we don't currently use it
85 return oid
86 finally:
87 queue.remove(ioid)
88 d.addCallback(inner)
89 # Call the deferred in the reactor so we give time to other things
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 # Try pushing it into the queue, which is an IITreeSet. If it inserted
100 # successfully it returns 1, else 0.
101 if queue.insert(ioid):
102 # Get the deferred that does the notification
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 # Create a mutable to store the handler name between the call to
124 # decorator and the call to advisor (simple assignment won't work for
125 # scope reasons)
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 # Log that we've called this listener
135 fname = '.'.join((self.__class__.__name__, f.__name__))
136 log.debug('%s is interested in %r for %r' % (fname, event, obj))
137
138 # Call the original function
139 return f(self, obj, event)
140
141 # Push the name of the function outside the decorator scope so the
142 # class advisor has access when it needs to register handlers.
143 _f[f.__name__] = 1
144
145 # Return the closure to replace the original function.
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 # Set one flag per fname on the class so we don't double-register
155 # when we override in a subclass (once for super, once for sub)
156 fname = _f.keys()[0]
157 cls.__registered = getattr(cls, '__registered', {})
158
159 # Check our flag
160 if fname not in cls.__registered or not issubclass(cls, tuple(cls.__registered[fname])):
161 # Decorator for __init__
162 def registerHandlers(f):
163 def __init__(self, *args, **kwargs):
164 # Call the original constructor; we'll register handlers
165 # afterwards
166 f(self, *args, **kwargs)
167 handler = getattr(self, fname)
168 for t in types:
169 # Register the handler. Here's where we use
170 # eventtype, which was passed in to the outermost
171 # function in this behemoth.
172 provideHandler(handler, (t, eventtype))
173
174 # Return the closure to replace the decorated method
175 return __init__
176
177 # Decorate __init__ so it will register the handlers on
178 # instantiation
179 cls.__init__ = registerHandlers(cls.__init__)
180 # Set the flag for this fname
181 cls.__registered.setdefault(fname, []).append(cls)
182
183
184 # Return the class, which will replace the original class.
185 return cls
186
187 # Add the advisor to the class.
188 addClassAdvisor(advisor)
189
190 # Return the decorator so we get the log message when called
191 return decorator
192
193 return factory
194
195
196 # Create two decorator factories for the two kinds of events.
197 onUpdate = _listener_decorator_factory(IUpdateEvent)
198 onDelete = _listener_decorator_factory(IDeletionEvent)
199
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1.1812 on Tue Oct 11 12:51:42 2011 | http://epydoc.sourceforge.net |