diff --git a/product/CMFActivity/ActivityTool.py b/product/CMFActivity/ActivityTool.py index e6ff7e8b5dcceb8f3fa0655b666c3063c0e1f02c..b24965caaeb70854d3aecfa6b649759446818ca7 100755 --- a/product/CMFActivity/ActivityTool.py +++ b/product/CMFActivity/ActivityTool.py @@ -61,7 +61,8 @@ except ImportError: active_threads = 0 max_active_threads = 1 # 2 will cause more bug to appear (he he) is_initialized = 0 -tic_lock = threading.Lock() # A RAM based lock +tic_lock = threading.Lock() # A RAM based lock to prevent too many concurrent tic() calls +timerservice_lock = threading.Lock() # A RAM based lock to prevent TimerService spamming when busy first_run = 1 # Activity Registration @@ -416,34 +417,44 @@ class ActivityTool (Folder, UniqueObject): This method is called by TimerService in the interval given in zope.conf. The Default is every 5 seconds. """ - - # get owner of portal_catalog, so normally we should be able to - # have the permission to invoke all activities - user = self.portal_catalog.getOwner() - newSecurityManager(self.REQUEST, user) - - currentNode = self.getCurrentNode() - - # only distribute when we are the distributingNode or if it's empty - if (self.distributingNode == self.getCurrentNode()): - self.distribute(len(self._nodes)) - #LOG('CMFActivity:', INFO, 'self.distribute(node_count=%s)' %len(self._nodes)) - - elif not self.distributingNode: - self.distribute(1) - #LOG('CMFActivity:', INFO, 'distributingNodes empty! Calling distribute(1)') - - # call tic for the current processing_node - # the processing_node numbers are the indices of the elements in the node tuple +1 - # because processing_node starts form 1 - if currentNode in self._nodes: - self.tic(list(self._nodes).index(currentNode)+1) - #LOG('CMFActivity:', INFO, 'self.tic(processing_node=%s)' %str(list(self._nodes).index(currentNode)+1)) - - elif len(self._nodes) == 0: - self.tic(1) - #LOG('CMFActivity:', INFO, 'Node List is empty! Calling tic(1)') + # Prevent TimerService from starting multiple threads in parallel + acquired = timerservice_lock.acquire(0) + if not acquired: + return + + try: + # get owner of portal_catalog, so normally we should be able to + # have the permission to invoke all activities + user = self.portal_catalog.getOwner() + newSecurityManager(self.REQUEST, user) + + currentNode = self.getCurrentNode() + + # only distribute when we are the distributingNode or if it's empty + if (self.distributingNode == self.getCurrentNode()): + self.distribute(len(self._nodes)) + #LOG('CMFActivity:', INFO, 'self.distribute(node_count=%s)' %len(self._nodes)) + + elif not self.distributingNode: + self.distribute(1) + #LOG('CMFActivity:', INFO, 'distributingNodes empty! Calling distribute(1)') + + # call tic for the current processing_node + # the processing_node numbers are the indices of the elements in the node tuple +1 + # because processing_node starts form 1 + if currentNode in self._nodes: + self.tic(list(self._nodes).index(currentNode)+1) + #LOG('CMFActivity:', INFO, 'self.tic(processing_node=%s)' %str(list(self._nodes).index(currentNode)+1)) + + elif len(self._nodes) == 0: + self.tic(1) + #LOG('CMFActivity:', INFO, 'Node List is empty! Calling tic(1)') + except: + timerservice_lock.release() + raise + else: + timerservice_lock.release() security.declarePublic('distribute') def distribute(self, node_count=1): @@ -451,6 +462,7 @@ class ActivityTool (Folder, UniqueObject): Distribute load """ # Initialize if needed + global is_initialized if not is_initialized: self.initialize() # Call distribute on each queue