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.
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)
.
.
|
You must be crusified for prepending the class name into the method names. Go back to C, man! :)
I like it, pretty handy