# # Copyright (c) 2007 Helmut Merz helmutm@cy55.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ Job scheduling. $Id$ """ from time import time from twisted.internet import reactor from twisted.internet.defer import Deferred, succeed from zope.interface import implements from loops.agent.interfaces import IScheduler, IScheduledJob class Scheduler(object): implements(IScheduler) def __init__(self, agent): self.agent = agent self.queue = {} @property def logger(self): return self.agent.logger() def schedule(self, job, startTime=None): if startTime is None: startTime = int(time()) job.startTime = startTime job.scheduler = self while startTime in self.queue: startTime += 1 self.queue[startTime] = job reactor.callLater(startTime-int(time()), job.run) return startTime def getJobsToExecute(startTime=0): return [j for j in self.queue.values() if startTime <= j.startTime] class Job(object): implements(IScheduledJob) scheduler = None whenStarted = lambda self, job: None whenFinished = lambda self, job, result: None def __init__(self, **params): self.startTime = 0 self.params = params self.successors = [] self.repeat = 0 def execute(self): """ Must be overridden by subclass. """ return succeed('OK') def reschedule(self, startTime): return self.scheduler.schedule(self.copy(), startTime) def run(self): d = self.execute() d.addCallback(self.finishRun) d.addErrback(self.logError) self.whenStarted(self) # TODO: logging def finishRun(self, result): # remove from queue del self.scheduler.queue[self.startTime] # run successors for job in self.successors: job.params['result'] = result #job.run() self.scheduler.schedule(job) self.whenFinished(self, result) # TODO: logging # reschedule if necessary if self.repeat: self.reschedule(int(time() + self.repeat)) def logError(self, error): print '*** error on running job:', error def copy(self): newJob = Job() newJob.params = self.params newJob.successors = [s.copy() for s in self.successors] class Stopper(Job): def execute(self): reactor.stop() return succeed('Agent stopped.')