refs #78 for minicrons with a period of longer than one second (checkpoints),

change minicron to count the period from the beginning of
the callback's execution and not the end. For checkpoints, this makes them
reliably start every 60 seconds.
This commit is contained in:
Zardosht Kasheff 2013-10-07 10:17:03 -04:00
parent 6e60da0886
commit 548bc646b2
2 changed files with 36 additions and 18 deletions

View file

@ -145,10 +145,15 @@ minicron_do (void *pv)
wakeup_at.tv_nsec += (p->period_in_ms % 1000) * 1000000;
toku_timespec_t now;
toku_gettime(&now);
int compare = timespec_compare(&wakeup_at, &now);
// if the time to wakeup has yet to come, then we sleep
// otherwise, we continue
if (compare > 0) {
int r = toku_cond_timedwait(&p->condvar, &p->mutex, &wakeup_at);
if (r!=0 && r!=ETIMEDOUT) fprintf(stderr, "%s:%d r=%d (%s)", __FILE__, __LINE__, r, strerror(r));
assert(r==0 || r==ETIMEDOUT);
}
}
// Now we woke up, and we should figure out what to do
if (p->do_shutdown) {
toku_mutex_unlock(&p->mutex);
@ -161,13 +166,12 @@ minicron_do (void *pv)
time_to_call.tv_sec += p->period_in_ms/1000;
time_to_call.tv_nsec += (p->period_in_ms % 1000) * 1000000;
int compare = timespec_compare(&time_to_call, &now);
//printf("compare(%.6f, %.6f)=%d\n", time_to_call.tv_sec + time_to_call.tv_nsec*1e-9, now.tv_sec+now.tv_nsec*1e-9, compare);
if (compare <= 0) {
toku_gettime(&p->time_of_last_call_to_f); // the measured period includes the time to make the call.
toku_mutex_unlock(&p->mutex);
int r = p->f(p->arg);
assert(r==0);
toku_mutex_lock(&p->mutex);
toku_gettime(&p->time_of_last_call_to_f); // the period is measured between calls to f.
}
}

View file

@ -199,9 +199,9 @@ test4 (void *v) {
int counter = 0;
ZERO_STRUCT(m);
int r = toku_minicron_setup(&m, 2000, run_3sec, &counter); assert(r==0);
sleep(9);
sleep(10);
r = toku_minicron_shutdown(&m); assert(r==0);
assert(counter==2);
assert(counter==3);
return v;
}
@ -212,9 +212,9 @@ test5 (void *v) {
ZERO_STRUCT(m);
int r = toku_minicron_setup(&m, 10000, run_3sec, &counter); assert(r==0);
toku_minicron_change_period(&m, 2000);
sleep(9);
sleep(10);
r = toku_minicron_shutdown(&m); assert(r==0);
assert(counter==2);
assert(counter==3);
return v;
}
@ -229,6 +229,19 @@ test6 (void *v) {
return v;
}
// test that we actually run once per period, even if the execution is long
static void*
test7 (void *v) {
struct minicron m;
int counter = 0;
ZERO_STRUCT(m);
int r = toku_minicron_setup(&m, 5000, run_3sec, &counter); assert(r==0);
sleep(17);
r = toku_minicron_shutdown(&m); assert(r==0);
assert(counter==3);
return v;
}
typedef void*(*ptf)(void*);
int
test_main (int argc, const char *argv[]) {
@ -238,7 +251,8 @@ test_main (int argc, const char *argv[]) {
ptf testfuns[] = {test1, test2, test3,
test4,
test5,
test6
test6,
test7
};
#define N (sizeof(testfuns)/sizeof(testfuns[0]))
toku_pthread_t tests[N];