Package flumotion :: Package common :: Module poller
[hide private]

Source Code for Module flumotion.common.poller

  1  # -*- Mode: Python; test-case-name: flumotion.test.test_common -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """cancellable, periodic call to a procedure 
 23  """ 
 24   
 25  from twisted.internet import reactor 
 26  from twisted.internet.defer import maybeDeferred 
 27   
 28  from flumotion.common import log 
 29   
 30  __version__ = "$Rev: 6967 $" 
 31   
 32   
33 -class Poller(object, log.Loggable):
34 """A class representing a cancellable, periodic call to a procedure, 35 which is robust in the face of exceptions raised by the procedure. 36 37 The poller will wait for a specified number of seconds between 38 calls. The time taken for the procedure to complete is not counted 39 in the timeout. If the procedure returns a deferred, rescheduling 40 will be performed after the deferred fires. 41 42 For example, if the timeout is 10 seconds and the procedure returns 43 a deferred which fires 5 seconds later, the next invocation of the 44 procedure will be performed 15 seconds after the previous 45 invocation. 46 """ 47
48 - def __init__(self, proc, timeout, immediately=False, start=True):
49 """ 50 @param proc: a procedure of no arguments 51 @param timeout: float number of seconds to wait between calls 52 @param immediately: whether to immediately call proc, or to wait 53 until one period has passed 54 @param start: whether to start the poller (defaults to True) 55 """ 56 57 self.proc = proc 58 self.logName = 'poller-%s' % proc.__name__ 59 self.timeout = timeout 60 61 self._dc = None 62 self.running = False 63 64 if start: 65 self.start(immediately)
66
67 - def start(self, immediately=False):
68 """Start the poller. 69 70 This procedure is called during __init__, so it is normally not 71 necessary to call it. It will ensure that the poller is running, 72 even after a previous call to stop(). 73 74 @param immediately: whether to immediately invoke the poller, or 75 to wait until one period has passed 76 """ 77 if self.running: 78 self.debug('already running') 79 else: 80 self.running = True 81 self._reschedule(immediately)
82
83 - def _reschedule(self, immediately=False):
84 assert self._dc is None 85 if self.running: 86 if immediately: 87 self.run() 88 else: 89 self._dc = reactor.callLater(self.timeout, self.run) 90 else: 91 self.debug('shutting down, not rescheduling')
92
93 - def run(self):
94 """Run the poller immediately, regardless of when it was last 95 run. 96 """ 97 def reschedule(v): 98 self._reschedule() 99 return v
100 101 if self._dc and self._dc.active(): 102 # we don't get here in the normal periodic case, only for 103 # explicit run() invocations 104 self._dc.cancel() 105 self._dc = None 106 d = maybeDeferred(self.proc) 107 d.addBoth(reschedule)
108
109 - def stop(self):
110 """Stop the poller. 111 112 This procedure ensures that the poller is stopped. It may be 113 called multiple times. 114 """ 115 if self._dc: 116 self._dc.cancel() 117 self._dc = None 118 self.running = False
119