Welcome, guest | Sign In | My Account | Store | Cart

We have tried to write an audit for our server to check our server's connection, status and other internal info and there are multiple threads invoking multiple tasks. So I came up with this simple utility that takes a job and runs it in a specific interval.

Python, 122 lines
  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
import time
import threading
import sys

# TODO: Maybe Interval should be a multiply of Precision.

class Job:
    Interval = 0
    Elapsed = 0
    JobFunction = None
    Force = False

class JobController(threading.Thread):
    
    def __init__(self,precision=1.0):
        threading.Thread.__init__(self)
        self.__StopIt = False
        self.__Jobs = {}
        self.__JobCounter = 0
        self.__Precision = precision
        self.__JobsLock = threading.Lock()
        
    def run(self):
        
        while(1):
            jobfuncs = []

            if self.__StopIt == True:
                return
            
            self.__JobsLock.acquire()
            try:
                for key,val in self.__Jobs.items():
                    val.Elapsed += self.__Precision
                    if val.Elapsed >= val.Interval or val.Force:
                        val.Elapsed = 0
                        val.Force = False
                        
                        # copy to another list for
                        # not acquirirng JobsLock()
                        # while calling the JobsFunction 
                        jobfuncs.append(val.JobFunction)
            finally:
                self.__JobsLock.release()
                
            # now invoke the job functions
            for jobfunc in jobfuncs:
                try:
                    jobfunc()
                # no unhandled exceptions allowed
                except Exception,e:
                    print "JOBERROR:"+str(e)
            time.sleep(self.__Precision)
                    
            
    def JcStart(self):
        self.start()
    
    def JcStop(self):
        self.__StopIt = True
        
    def __AssertBounds(self,val,min,max):
        if (val < min) or (val > max):
            raise AssertionError, "value not in bounds" \
                      "["+str(val)+"]["+str(min)+"]["+str(max)+"]"
        
    def JcAddJob(self,interval,jobfunction):
        
        self.__AssertBounds(interval,self.__Precision,float(sys.maxint))
        
        # create a job object
        ajob = Job()
        ajob.Interval = interval
        ajob.Elapsed = 0
        ajob.JobFunction = jobfunction
        ajob.Force = False
        # append it to jobs dict
        self.__JobCounter += 1

        self.__JobsLock.acquire()
        try:
            self.__Jobs[self.__JobCounter] = ajob
        finally:
            self.__JobsLock.release()
            
        return self.__JobCounter
        
    def JcRemoveJob(self,jobid):
        self.__JobsLock.acquire()
        try:
            del self.__Jobs[jobid]
        finally:
            self.__JobsLock.release()
        
    def JcForceJob(self,jobid):
        self.__JobsLock.acquire()
        try:            
            self.__Jobs[jobid].Force = True
        finally:
            self.__JobsLock.release()
        
    def JcChangeJob(self,jobid,interval,jobfunction):

        self.__AssertBounds(interval,self.__Precision,sys.maxint)
        
        self.__JobsLock.acquire()
        try:  
            self.__Jobs[jobid].Interval = interval
            self.__Jobs[jobid].JobFunction = jobfunction
        finally:
            self.__JobsLock.release()

# EXAMPLE
A simple example is like this:
jc = JobController(60.0) # precision is 60 secs, so main JobController will be invoked
                         # per 60 secs.
jc.JcAddJob(60*30,CheckConnectionJob)
jc.JcAddJob(60*5,CheckStatisticsJob)
jc.start()
jc.JcAddJob(60*5,CheckPingJob)
.
.

2 comments

utku karatas 12 years, 5 months ago  # | flag

You must be crusified for prepending the class name into the method names. Go back to C, man! :)

jade 11 years, 5 months ago  # | flag

I like it, pretty handy

Created by sumerc on Mon, 11 May 2009 (MIT)
Python recipes (4591)
sumerc's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks