File: scheduler.py

package info (click to toggle)
python-jtoolkit 0.7.8-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 1,436 kB
  • ctags: 2,536
  • sloc: python: 15,143; makefile: 20
file content (144 lines) | stat: -rwxr-xr-x 6,242 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""simple scheduler class that scheduler programs can use"""

# Copyright 2004 St James Software
# 
# This file is part of jToolkit.
#
# jToolkit 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.
# 
# jToolkit 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 jToolkit; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import datetime
import threading
import time
from jToolkit import errors
from jToolkit import prefs
from jToolkit import tail

class Scheduler:
    WEEKDAYS = [
        "monday",
        "tuesday",
        "wednesday",
        "thursday",
        "friday",
        "saturday",
        "sunday"]    

    def __init__(self, errorhandler=None):
        if errorhandler is None:
            self.errorhandler = errors.ConsoleErrorHandler()
        else:
            self.errorhandler = errorhandler

        self.runLock = threading.Lock()        
        
    def MainLoop(self):
        # runLock is acquired means the scheduler should keep running
        # if it is released the scheduler should stop running
        try:
            self.runLock.acquire()
            instartup = True
            while not self.runLock.acquire(False):
                try:
                    time.sleep(1)
                except KeyboardInterrupt:
                    self.errorhandler.logtrace(self.name+" manually stopped at following traceback...")
                    self.errorhandler.logtrace(self.errorhandler.traceback_str())
                    self.errorhandler.logtrace(self.name+" shutting down...")
                    self.runLock.release()
                    continue
                except Exception:
                    # this will make it restart...
                    continue
                # run any events that are scheduled for now...
                if not self.RunScheduledEvent(instartup):
                  print "RunScheduledEvent returned a False value!"
                  break
                instartup = False
            print "finished loop..."
        finally:
            print "in finally", self.runLock.locked()
            if self.runLock.locked():
                self.runLock.release()
            if hasattr(self, "mailerrorhandler"):
                self.mailerrorhandler.shutdown()

    def RunScheduledEvent(self, instartup=False):
        raise NotImplementedError("RunScheduledEvent in jToolkit/Scheduler")

    def MaintainLogfiles(self, logmaintainConfig, avgcharsperline=75):
        logfiles = logmaintainConfig.LogfilesWatched.split(',')
        lineskept = logmaintainConfig.LinesKept
        tail.reduce_files_to_tail(logfiles, lineskept, avgcharsperline)

    def GetNextScheduledTime(self, timeConfig, instartup=False):
        """gets the next time at which an event should run"""
        frequency = timeConfig.frequency.lower()

        nextSchedule = datetime.datetime.now()
        # sets a skip rate, only works up to days...
        nrate = int(getattr(timeConfig, 'nrate', 1))

        if instartup:
            onstartup = prefs.evaluateboolean(getattr(timeConfig, "onstartup", None), False)
            if onstartup:
                return nextSchedule

        snaptime = prefs.evaluateboolean(getattr(timeConfig, "snaptime", None), False)
        if frequency == 'minutely':
            if snaptime and nextSchedule.minute > 0:
                nextHour = (nextSchedule + datetime.timedelta(hours=1)).hour
                nextTime = nextSchedule + datetime.timedelta(minutes=nrate)
                if nextTime.hour == nextHour and nextTime.minute > 0:
                  nextSchedule = nextSchedule.replace(hour=nextHour, minute=0, second=0, microsecond=0)
                  return nextSchedule
            if nextSchedule.second >= 0:
                nextSchedule += datetime.timedelta(minutes=nrate)
            return nextSchedule.replace(second=0)

        ScheduleHour, ScheduleMinute = map(int, getattr(timeConfig, "time", "12:00").split(':'))
        if frequency == 'hourly':
            if nextSchedule.minute >= ScheduleMinute:
                nextSchedule += datetime.timedelta(hours=nrate)
            return nextSchedule.replace(minute=ScheduleMinute, second=0)
        elif frequency == 'daily':
            if nextSchedule.hour > ScheduleHour or \
               (nextSchedule.hour == ScheduleHour and nextSchedule.minute >= ScheduleMinute):
                nextSchedule += datetime.timedelta(days=nrate)
        elif frequency == 'weekly':
            ScheduleDay = self.WEEKDAYS.index(timeConfig.day)
            if nextSchedule.weekday() > ScheduleDay or \
               (nextSchedule.weekday() == ScheduleDay and \
                (nextSchedule.hour > ScheduleHour or \
                 (nextSchedule.hour == ScheduleHour and nextSchedule.minute >= ScheduleMinute))):
                nextSchedule += datetime.timedelta(days = 7 - (nextSchedule.weekday() - ScheduleDay))
        elif frequency == 'monthly':
            ScheduleDay = int(timeConfig.date)
            if nextSchedule.day > ScheduleDay or \
               (nextSchedule.day == ScheduleDay and \
                (nextSchedule.hour > ScheduleHour or \
                 (nextSchedule.hour == ScheduleHour and nextSchedule.minute >= ScheduleMinute))):
                if nextSchedule.month < 12:
                    nextSchedule = nextSchedule.replace(month = nextSchedule.month + 1)
                else:
                    nextSchedule = nextSchedule.replace(month = 1, year = nextSchedule.year + 1)
            nextSchedule = nextSchedule.replace(day = ScheduleDay)
        else:
            raise ValueError("Unknown frequency type %s" % frequency)

        return nextSchedule.replace(hour=ScheduleHour, minute=ScheduleMinute)