summaryrefslogtreecommitdiff
path: root/src/minicron.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2010-01-14 00:28:08 +0000
committerMike Buland <eichlan@xagasoft.com>2010-01-14 00:28:08 +0000
commit5471d34089277ad5c622fd9c392b9270229d9e3d (patch)
tree29bb6b159679ef3a9746fdc61c1ac4e7cea6fe5c /src/minicron.cpp
parentb07c2de16ae8dfa2c0fc4a594deddacc46386216 (diff)
downloadlibbu++-5471d34089277ad5c622fd9c392b9270229d9e3d.tar.gz
libbu++-5471d34089277ad5c622fd9c392b9270229d9e3d.tar.bz2
libbu++-5471d34089277ad5c622fd9c392b9270229d9e3d.tar.xz
libbu++-5471d34089277ad5c622fd9c392b9270229d9e3d.zip
Created the minicron system. This is a cute little cron like implementation
that allows a program to signal slots on a schedule, possibly a dynamic schedule.
Diffstat (limited to 'src/minicron.cpp')
-rw-r--r--src/minicron.cpp360
1 files changed, 360 insertions, 0 deletions
diff --git a/src/minicron.cpp b/src/minicron.cpp
new file mode 100644
index 0000000..f20a382
--- /dev/null
+++ b/src/minicron.cpp
@@ -0,0 +1,360 @@
1#include "bu/minicron.h"
2
3#include <stdlib.h>
4#include <time.h>
5
6Bu::MiniCron::MiniCron() :
7 jidNext( 1 )
8{
9}
10
11Bu::MiniCron::~MiniCron()
12{
13}
14
15bool Bu::MiniCron::hasJobs()
16{
17 return !hJobs.isEmpty();
18}
19
20time_t Bu::MiniCron::getNextRun()
21{
22 if( hasJobs() )
23 return hJobs.peek()->getNextRun();
24 return -1;
25}
26
27void Bu::MiniCron::poll()
28{
29 time_t tNow = time( NULL );
30
31 while( !hJobs.isEmpty() )
32 {
33 if( hJobs.peek()->getNextRun() <= tNow )
34 {
35 Job *pJob = hJobs.dequeue();
36 pJob->run();
37 if( pJob->bContinue )
38 {
39 hJobs.enqueue( pJob );
40 }
41 else
42 {
43 delete pJob;
44 }
45 }
46 else
47 {
48 break;
49 }
50 }
51}
52
53Bu::MiniCron::JobId Bu::MiniCron::addJob( Bu::MiniCron::CronSignal sigJob,
54 const Bu::MiniCron::Timer &t )
55{
56 JobId jid = jidNext++;
57 Job *pJob = new Job( jid );
58 pJob->sigJob = sigJob;
59 pJob->pTimer = t.clone();
60 pJob->tNextRun = pJob->pTimer->nextTime();
61 hJobs.enqueue( pJob );
62
63 return jid;
64}
65
66Bu::MiniCron::JobId Bu::MiniCron::addJobOnce( Bu::MiniCron::CronSignal sigJob,
67 const Bu::MiniCron::Timer &t )
68{
69 JobId jid = jidNext++;
70 Job *pJob = new Job( jid, false );
71 pJob->sigJob = sigJob;
72 pJob->pTimer = t.clone();
73 pJob->tNextRun = pJob->pTimer->nextTime();
74 hJobs.enqueue( pJob );
75
76 return jid;
77}
78
79void Bu::MiniCron::removeJob( JobId jid )
80{
81 Bu::List<Job *> lJobs;
82 while( !hJobs.isEmpty() )
83 {
84 Job *pJob = hJobs.dequeue();
85 if( pJob->getId() == jid )
86 {
87 delete pJob;
88 }
89 else
90 lJobs.append( pJob );
91 }
92
93 for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ )
94 {
95 hJobs.enqueue( *i );
96 }
97}
98
99Bu::MiniCron::Job::Job( JobId jid, bool bRepeat ) :
100 pTimer( NULL ),
101 bContinue( bRepeat ),
102 jid( jid ),
103 tAdded( time( NULL ) ),
104 iRunCount( 0 )
105{
106}
107
108Bu::MiniCron::Job::~Job()
109{
110 delete pTimer;
111 pTimer = NULL;
112}
113
114void Bu::MiniCron::Job::run()
115{
116 iRunCount++;
117 tNextRun = pTimer->nextTime();
118 sigJob( *this );
119}
120
121time_t Bu::MiniCron::Job::getNextRun()
122{
123 return tNextRun;
124}
125
126void Bu::MiniCron::Job::calcNextRun()
127{
128 if( pTimer )
129 tNextRun = pTimer->nextTime();
130}
131
132void Bu::MiniCron::Job::setTimer( const Timer &t )
133{
134 delete pTimer;
135 pTimer = t.clone();
136}
137
138void Bu::MiniCron::Job::stop()
139{
140 bContinue = false;
141}
142
143void Bu::MiniCron::Job::resume()
144{
145 bContinue = true;
146}
147
148Bu::MiniCron::JobId Bu::MiniCron::Job::getId()
149{
150 return jid;
151}
152
153time_t Bu::MiniCron::Job::getTimeCreated()
154{
155 return tAdded;
156}
157
158int Bu::MiniCron::Job::getRunCount()
159{
160 return iRunCount;
161}
162
163Bu::MiniCron::Timer::Timer()
164{
165}
166
167Bu::MiniCron::Timer::~Timer()
168{
169}
170
171Bu::MiniCron::TimerInterval::TimerInterval( time_t tFirst, time_t tInterval ) :
172 tNext( tFirst ),
173 tInterval( tInterval )
174{
175}
176
177Bu::MiniCron::TimerInterval::~TimerInterval()
178{
179}
180
181time_t Bu::MiniCron::TimerInterval::nextTime()
182{
183 time_t tRet = tNext;
184 tNext += tInterval;
185 return tRet;
186}
187
188Bu::MiniCron::TimerBasic::TimerBasic( const Bu::FString &s ) :
189 tLast( -1 ),
190 sSpec( s )
191{
192}
193
194Bu::MiniCron::TimerBasic::~TimerBasic()
195{
196}
197
198time_t Bu::MiniCron::TimerBasic::nextTime()
199{
200 if( tLast == -1 )
201 tLast = time( NULL );
202
203 Bu::FString::const_iterator i = sSpec.begin();
204 switch( lex( i ) )
205 {
206 case tokDaily:
207 {
208 int iHour = lexInt( i );
209 int iMin = lexInt( i );
210
211 struct tm t;
212 ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) );
213 if( iHour < t.tm_hour ||
214 (iHour == t.tm_hour && iMin <= t.tm_min) )
215 {
216 t.tm_mday++;
217 }
218 t.tm_hour = iHour;
219 t.tm_min = iMin;
220 t.tm_sec = 0;
221 tLast = mktime( &t );
222 }
223 break;
224
225 case tokHourly:
226 {
227 int iMin = lexInt( i );
228
229 struct tm t;
230 ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) );
231 if( iMin <= t.tm_min )
232 t.tm_hour++;
233 t.tm_min = iMin;
234 t.tm_sec = 0;
235 tLast = mktime( &t );
236 }
237 break;
238
239 case tokWeekly:
240 {
241 int iDay = lexInt( i );
242 int iHour = lexInt( i );
243 int iMin = lexInt( i );
244
245 struct tm t;
246 ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) );
247 if( iDay < t.tm_wday ||
248 (iDay == t.tm_wday && iHour < t.tm_hour) ||
249 (iDay == t.tm_wday && iHour == t.tm_hour
250 && iMin <= t.tm_min) )
251 {
252 if( iDay <= t.tm_wday )
253 t.tm_mday += 7 - (t.tm_wday-iDay);
254 else
255 t.tm_mday += 7 - (iDay-t.tm_wday);
256 }
257 else
258 {
259 t.tm_mday += (iDay-t.tm_wday);
260 }
261 t.tm_hour = iHour;
262 t.tm_min = iMin;
263 t.tm_sec = 0;
264 tLast = mktime( &t );
265 }
266 break;
267
268 case tokMonthly:
269 break;
270
271 case tokYearly:
272 break;
273
274 default:
275 break;
276 }
277
278 return tLast;
279}
280
281Bu::MiniCron::TimerBasic::Token Bu::MiniCron::TimerBasic::lex(
282 Bu::FString::const_iterator &i )
283{
284 if( !i )
285 {
286 return tokEos;
287 }
288
289 Bu::FString::const_iterator b = i;
290
291 for(; b && (*b == ' ' || *b == '\t'); b++ ) { i = b+1; }
292 for(; b && *b != ' ' && *b != '\t'; b++ ) { }
293
294 Bu::FString sTok( i, b );
295 i = b;
296
297 if( sTok == "daily" )
298 return tokDaily;
299 else if( sTok == "hourly" )
300 return tokHourly;
301 else if( sTok == "weekly" )
302 return tokWeekly;
303 else if( sTok == "monthly" )
304 return tokMonthly;
305 else if( sTok == "yearly" )
306 return tokYearly;
307 else if( sTok == "sun" )
308 {
309 iVal = 0;
310 return valInt;
311 }
312 else if( sTok == "mon" )
313 {
314 iVal = 1;
315 return valInt;
316 }
317 else if( sTok == "tue" )
318 {
319 iVal = 2;
320 return valInt;
321 }
322 else if( sTok == "wed" )
323 {
324 iVal = 3;
325 return valInt;
326 }
327 else if( sTok == "thu" )
328 {
329 iVal = 4;
330 return valInt;
331 }
332 else if( sTok == "fri" )
333 {
334 iVal = 5;
335 return valInt;
336 }
337 else if( sTok == "sat" )
338 {
339 iVal = 6;
340 return valInt;
341 }
342 else if( sTok[0] >= '0' && sTok[0] <= '9' )
343 {
344 iVal = strtol( sTok.getStr(), NULL, 0 );
345 return valInt;
346 }
347
348 return tokErr;
349}
350
351int Bu::MiniCron::TimerBasic::lexInt( Bu::FString::const_iterator &i )
352{
353 Token t = lex( i );
354 if( t == tokEos )
355 return 0;
356 if( t != valInt )
357 throw Bu::ExceptionBase("Expected int, got something else.");
358 return iVal;
359}
360