Scheduler.py
上传用户:lswyart
上传日期:2008-06-12
资源大小:3441k
文件大小:10k
源码类别:

杀毒

开发平台:

Visual C++

  1. #-----------------------------------------------------------------------------
  2. # Name:        Scheduler.py
  3. # Product:     ClamWin Free Antivirus
  4. #
  5. # Author:      alch [alch at users dot sourceforge dot net]
  6. #
  7. # Created:     2004/19/03
  8. # Copyright:   Copyright alch (c) 2004
  9. # Licence:     
  10. #   This program is free software; you can redistribute it and/or modify
  11. #   it under the terms of the GNU General Public License as published by
  12. #   the Free Software Foundation; either version 2 of the License, or
  13. #   (at your option) any later version.
  14. #   This program is distributed in the hope that it will be useful,
  15. #   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. #   GNU General Public License for more details.
  18. #   You should have received a copy of the GNU General Public License
  19. #   along with this program; if not, write to the Free Software
  20. #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. #-----------------------------------------------------------------------------
  22. #!/usr/bin/env python
  23. import os, tempfile
  24. import sched, time, locale
  25. import types
  26. import threading
  27. class Scheduler(threading.Thread):
  28.     # empty tuple for status_filenames parameter will reuslt in no checking
  29.     # for missed schedules
  30.     def __init__(self, frequency, startTime, weekDay, action, argument=(), 
  31.             status_filenames=(), loopDelay = 0.5):           
  32.         threading.Thread.__init__(self)         
  33.         self._filenames = status_filenames
  34.         self._delay = 0.5
  35.         self._loopDelay = loopDelay
  36.         self._cancelling = False
  37.         self._frequency = frequency                    
  38.         self._weekDay = weekDay
  39.         self._startTime = startTime                             
  40.                 
  41.         self._action = action
  42.         self._argument = argument
  43.         self._lastRun = self._ReadLastRun()                
  44.             
  45.         self._sched = sched.scheduler(time.time, self._DelayFunc)        
  46.         self._missedSchedule = False
  47.         self._id = self._sched.enterabs(self._CalcNextRun(), 0, self._RunTask, ())
  48.         
  49.     def reset(self, frequency, startTime, weekDay, action, argument=(), loopDelay = 0.2):
  50.         self._delay = 1.0
  51.         self._loopDelay = loopDelay
  52.         self._cancelling = False
  53.         self._frequency = frequency                    
  54.         self._weekDay = weekDay
  55.         self._startTime = startTime                             
  56.                 
  57.         self._action = action
  58.         self._argument = argument
  59.         self._lastRun = self._ReadLastRun()
  60.         self._missedSchedule = False
  61.         
  62.         # stop current thread
  63.         self.stop()
  64.         threading.Thread.__init__(self)         
  65.         
  66.         
  67.         # ensure it stopped
  68.         i = 0        
  69.         while self.isAlive() and i < 50:
  70.             time.sleep(0.1)
  71.             i+=1
  72.             
  73.         # recreate scheduled event                                                
  74.         self._id = self._sched.enterabs(self._CalcNextRun(), 0, self._RunTask, ())
  75.                 
  76.         
  77.     def _ReadLastRun(self):        
  78.         # 0 signifies an error  
  79.         t = 0
  80.         # read when the task was run last        
  81.         for filename in self._filenames:
  82.             try:
  83.                 f = file(os.path.join(tempfile.gettempdir(), filename), 'r')
  84.                 t = f.read()
  85.                 f.close()            
  86.             except:
  87.                 t = 0
  88.                 continue
  89.             # check that we have a float
  90.             if not isinstance(t, types.FloatType):
  91.                 t = 0
  92.                 continue
  93.             if time.time() < float(t):                
  94.                 # got time in future, ignore it
  95.                 t = 0
  96.                 continue    
  97.             else:
  98.                 break
  99.                 
  100.         return float(t)        
  101.             
  102.     def _WriteLastRun(self):
  103.         # save time when the task was run for future
  104.         for filename in self._filenames:
  105.             try:                        
  106.                 f = file(os.path.join(tempfile.gettempdir(), filename), 'w')
  107.                 f.write(str(self._lastRun))
  108.                 f.close()                       
  109.             except IOError:            
  110.                 pass
  111.             
  112.     def _AdjustDST(self, t):
  113.         # deal with daylight savings, if we're on the edge        
  114.         dstDiff = time.localtime().tm_isdst - time.localtime(t).tm_isdst
  115.         t += dstDiff * 3600.00
  116.         return t
  117.     # returns time in seconds (as in time.time())
  118.     # when next scheduled run occurs
  119.     def _CalcNextRun(self):
  120.         # calculate when the next task should run
  121.         # depending on last run time, update frequency,
  122.         # task start time and day of the week
  123.         
  124.         # set C locale, otherwise python and wxpython complain
  125.         locale.setlocale(locale.LC_ALL, 'C')            
  126.         # get current time, skip milliseconds
  127.         t = time.time()
  128.         if self._frequency == 'Hourly':                        
  129.             try:
  130.                 # use only MM:SS part of starttime                            
  131.                 schedTime = time.mktime(time.strptime(time.strftime('%d-%m-%Y %H:') + self._startTime.split(':', 1)[1],'%d-%m-%Y %H:%M:%S'))                                
  132.             except ValueError, e:            
  133.                 print "couldn't parse time, self._startTime = %s.n Error: %s" % (self._startTime, str(e))
  134.                 self._missedSchedule = True
  135.                 schedTime = t + 120
  136.             addTime = 3600.0            
  137.         elif self._frequency in ('Weekly', 'Once'):        
  138.             try:
  139.                 lt = time.localtime(t)
  140.                 # use  weekday and HH:MM:SS part of starttime
  141.                 schedTime = time.mktime(time.strptime(str(lt.tm_yday - lt.tm_wday + self._weekDay) + 
  142.                             time.strftime(' %Y ', lt) + self._startTime, '%j %Y %H:%M:%S')) 
  143.             except ValueError, e:
  144.                 print "couldn't parse time, self._startTime = %s. self._weekDay = %in Error: %s" % (self._startTime, self._weekDay, str(e))
  145.                 self._missedSchedule = True
  146.                 schedTime = t + 120
  147.             addTime = 3600.0*24*7                    
  148.         else: #'Daily' or 'Workdays' is default                    
  149.             try:
  150.                 # use HH:MM:SS part of starttime
  151.                 schedTime = time.mktime(time.strptime(time.strftime('%d-%m-%Y ') + self._startTime,'%d-%m-%Y %H:%M:%S'))                                
  152.             except ValueError, e:                
  153.                 self._missedSchedule = True
  154.                 schedTime = t + 120
  155.                 print "couldn't parse time, self._startTime = %s.n Error: %s" % (self._startTime, str(e))
  156.             addTime = 3600.0*24
  157.             
  158.         
  159.         # go to next time interval if it is out
  160.         tmp = schedTime
  161.         while self._AdjustDST(schedTime) < t:            
  162.             schedTime += addTime                 
  163.         
  164.         # move out of the weekend for workdays            
  165.         if self._frequency == 'Workdays':                        
  166.             while time.localtime(self._AdjustDST(schedTime)).tm_wday in (5,6):
  167.                 schedTime += addTime  
  168.             if tmp < schedTime:             
  169.                 addTime = schedTime - tmp
  170.                 
  171.         #don't return for missed schedule if frequency is workdays and it is weekend now
  172.         if self._frequency != 'Workdays' or time.localtime(t).tm_wday not in (5,6):        
  173.             # check if we missed the scheduled run
  174.             # and return now (+ 2 minutes) instead            
  175.             if  self._lastRun != 0 and self._AdjustDST(schedTime) - addTime > self._lastRun:
  176.                 t = t + 120
  177.                 print 'Schedule missed, returning: %s' % time.asctime(time.localtime(t))
  178.                 try:
  179.               print 'LastRun: %s' % time.asctime(time.localtime(self._lastRun))
  180.                 except:
  181.               pass
  182.                 self._missedSchedule = True
  183.                 return t
  184.                 
  185.         schedTime = self._AdjustDST(schedTime)
  186.         print 'Scheduling task for: %s' % time.asctime(time.localtime(schedTime))        
  187.         return schedTime + self._delay
  188.                                   
  189.     def _RunTask(self):
  190.         # get current time        
  191.         if self._cancelling:            
  192.             return 
  193.         # set C locale, otherwise python and wxpython complain
  194.         locale.setlocale(locale.LC_ALL, 'C')
  195.                                            
  196.         t = time.time()
  197.                                 
  198.         # execute the action
  199.         print 'running task on: %s. Frequency is: %sn' % (time.strftime('%d-%m-%y %H:%M:%S', time.localtime(t)), self._frequency)
  200.         void = self._action(*self._argument)
  201.         self._lastRun = t
  202.         self._WriteLastRun()
  203.         
  204.         # schedule next action        
  205.         if self._frequency != 'Once' and not self._missedSchedule:                        
  206.             self._id = self._sched.enterabs(self._CalcNextRun(), 0, self._RunTask, ())               
  207.         
  208.     def _DelayFunc(self, delay):
  209.         start = time.time()
  210.         while not self._cancelling and int(time.time() - start) < int(delay):
  211.             time.sleep(self._loopDelay)                                    
  212.                         
  213.     def run(self):
  214.         self._sched.run()
  215.         print 'Scheduler terminated'
  216.         
  217.     def stop(self):
  218.         try:
  219.            self._sched.cancel(self._id)        
  220.         except:
  221.            pass        
  222.         self._cancelling = True                                        
  223. if __name__ == '__main__':
  224.     import sys
  225.     def action():
  226.         print 'execute'
  227.         
  228.     s = Scheduler('Workdays', '20:20:00', 5, action)
  229.     s.start()
  230.     while sys.stdin.read(1) != 'c':
  231.         time.sleep(0)
  232.     s.stop()    
  233.     s.join(1)
  234.     print 'completed'
  235.     
  236.         
  237.