Some more updates to the cron system, simplified somewhat by storing string and converting to bit masks for running.
This commit is contained in:
parent
3eacec0e63
commit
febdf40d5d
2 changed files with 134 additions and 87 deletions
199
src/cron.c
199
src/cron.c
|
@ -1,54 +1,48 @@
|
|||
#include "cron.h"
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int _field_to_string
|
||||
( char *out, uint64_t field, uint64_t mask, int offset )
|
||||
typedef struct cron
|
||||
{
|
||||
int i, cnt = 0, first = 1, start = -1;
|
||||
field &= mask;
|
||||
char *str; ///< String representation
|
||||
uint64_t min; ///< Minutes
|
||||
uint32_t hour; ///< Hours
|
||||
uint32_t dom; ///< Day of month
|
||||
uint16_t mon; ///< Month
|
||||
uint8_t dow; ///< Day of week
|
||||
} cron_t;
|
||||
|
||||
/* Star */
|
||||
if ( field == mask )
|
||||
return sprintf(out, "*");
|
||||
|
||||
for ( i = 0; i < 64; i++ ) {
|
||||
int b = (field >> i) & 0x1;
|
||||
if ( !b & start != -1 ) {
|
||||
if (!first)
|
||||
cnt += sprintf(out+cnt, ",");
|
||||
first = 0;
|
||||
cnt += sprintf(out+cnt, "%d", start + offset);
|
||||
if (i != (start+1))
|
||||
cnt += sprintf(out+cnt, "-%d", (i - 1) + offset);
|
||||
start = -1;
|
||||
} else if ( b & start == -1 )
|
||||
start = i;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int _field_from_string
|
||||
static int _cron_parse_field
|
||||
( const char *str, uint64_t *field, uint64_t mask, int offset )
|
||||
{
|
||||
int i = 0, j = 0, sn = -1, en = -1;
|
||||
int i = 0, j = 0, sn = -1, en = -1, mn = -1;
|
||||
*field = 0;
|
||||
while ( str[i] != '\0' ) {
|
||||
if ( str[i] == '*' ) *field = mask;
|
||||
else if ( str[i] == ',' || str[i] == ' ' ) {
|
||||
sscanf(str+j, "%d", sn == -1 ? &sn : &en);
|
||||
if ( str[i] == '*' ) {
|
||||
sn = 0;
|
||||
en = 64;
|
||||
j = -1;
|
||||
} else if ( str[i] == ',' || str[i] == ' ' ) {
|
||||
if (j >= 0)
|
||||
sscanf(str+j, "%d", en == -1 ? (sn == -1 ? &sn : &en) : &mn);
|
||||
if (en == -1) en = sn;
|
||||
if (mn == -1) mn = 1;
|
||||
while (sn <= en) {
|
||||
*field |= (0x1LL << (sn - offset));
|
||||
if ( (sn % mn) == 0 )
|
||||
*field |= (0x1LL << (sn - offset));
|
||||
sn++;
|
||||
}
|
||||
j = i+1;
|
||||
sn = -1;
|
||||
en = -1;
|
||||
sn = en = mn = -1;
|
||||
if (str[i] == ' ') break;
|
||||
} else if ( str[i] == '/' ) {
|
||||
if (j >= 0) sscanf(str+j, "%d", sn == -1 ? &sn : &en);
|
||||
j = i+1;
|
||||
mn = 1;
|
||||
} else if ( str[i] == '-' ) {
|
||||
sscanf(str+j, "%d", &sn);
|
||||
if (j >= 0) sscanf(str+j, "%d", &sn);
|
||||
j = i+1;
|
||||
en = 64;
|
||||
}
|
||||
|
@ -59,34 +53,74 @@ static int _field_from_string
|
|||
return i;
|
||||
}
|
||||
|
||||
void cron_to_string ( cron_t *cron, char *str )
|
||||
{
|
||||
int i = 0;
|
||||
i += _field_to_string(str+i, cron->min, CRON_MIN_MASK, 0);
|
||||
i += sprintf(str+i, " ");
|
||||
i += _field_to_string(str+i, cron->hour, CRON_HOUR_MASK, 0);
|
||||
i += sprintf(str+i, " ");
|
||||
i += _field_to_string(str+i, cron->dom, CRON_DOM_MASK, 1);
|
||||
i += sprintf(str+i, " ");
|
||||
i += _field_to_string(str+i, cron->mon, CRON_MON_MASK, 1);
|
||||
i += sprintf(str+i, " ");
|
||||
i += _field_to_string(str+i, cron->dow, CRON_DOW_MASK, 0);
|
||||
}
|
||||
|
||||
void cron_from_string ( cron_t *cron, const char *str )
|
||||
static int _cron_parse ( cron_t *cron, const char *str )
|
||||
{
|
||||
int i = 0;
|
||||
uint64_t u64;
|
||||
i += _field_from_string(str+i, &u64, CRON_MIN_MASK, 0);
|
||||
cron->min = u64;
|
||||
i += _field_from_string(str+i, &u64, CRON_HOUR_MASK, 0);
|
||||
cron->hour = (uint32_t)u64;
|
||||
i += _field_from_string(str+i, &u64, CRON_DOM_MASK, 1);
|
||||
cron->dom = (uint32_t)u64;
|
||||
i += _field_from_string(str+i, &u64, CRON_MON_MASK, 1);
|
||||
cron->mon = (uint16_t)u64;
|
||||
i += _field_from_string(str+i, &u64, CRON_DOW_MASK, 0);
|
||||
cron->dow = (uint8_t)u64;
|
||||
|
||||
/* daily */
|
||||
if ( !strcmp(str, "@daily") ) {
|
||||
cron->min = 1;
|
||||
cron->hour = 1;
|
||||
cron->dom = CRON_DOM_MASK;
|
||||
cron->mon = CRON_MON_MASK;
|
||||
cron->dow = CRON_DOW_MASK;
|
||||
|
||||
/* hourly */
|
||||
} else if ( !strcmp(str, "@hourly") ) {
|
||||
cron->min = 1;
|
||||
cron->hour = CRON_HOUR_MASK;
|
||||
cron->dom = CRON_DOM_MASK;
|
||||
cron->mon = CRON_MON_MASK;
|
||||
cron->dow = CRON_DOW_MASK;
|
||||
|
||||
/* standard */
|
||||
} else {
|
||||
i += _cron_parse_field(str+i, &u64, CRON_MIN_MASK, 0);
|
||||
cron->min = u64;
|
||||
i += _cron_parse_field(str+i, &u64, CRON_HOUR_MASK, 0);
|
||||
cron->hour = (uint32_t)u64;
|
||||
i += _cron_parse_field(str+i, &u64, CRON_DOM_MASK, 1);
|
||||
cron->dom = (uint32_t)u64;
|
||||
i += _cron_parse_field(str+i, &u64, CRON_MON_MASK, 1);
|
||||
cron->mon = (uint16_t)u64;
|
||||
i += _cron_parse_field(str+i, &u64, CRON_DOW_MASK, 0);
|
||||
cron->dow = (uint8_t)u64;
|
||||
}
|
||||
|
||||
return 1; // TODO: do proper validation
|
||||
}
|
||||
|
||||
cron_t *cron_create ( void )
|
||||
{
|
||||
return calloc(1, sizeof(cron_t));
|
||||
}
|
||||
|
||||
void cron_destroy ( cron_t *cron )
|
||||
{
|
||||
if (cron->str) free(cron->str);
|
||||
free(cron);
|
||||
}
|
||||
|
||||
const char *cron_get_string ( cron_t *cron )
|
||||
{
|
||||
return cron->str;
|
||||
}
|
||||
|
||||
int cron_set_string ( cron_t *cron, const char *str )
|
||||
{
|
||||
int save = 0;
|
||||
cron_t tmp;
|
||||
if (!cron->str || !strcmp(cron->str, str)) {
|
||||
tmp.str = (char*)str;
|
||||
if (_cron_parse(&tmp, str)) {
|
||||
if (cron->str) free(cron->str);
|
||||
*cron = tmp;
|
||||
cron->str = strdup(str);
|
||||
save = 1;
|
||||
}
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
int cron_is_time ( cron_t *cron )
|
||||
|
@ -109,23 +143,40 @@ int cron_is_time ( cron_t *cron )
|
|||
return ret;
|
||||
}
|
||||
|
||||
void cron_pack ( cron_t *cron, htsmsg_t *msg )
|
||||
// TODO: do proper search for next time
|
||||
time_t cron_next ( cron_t *cron )
|
||||
{
|
||||
htsmsg_add_u64(msg, "min", cron->min);
|
||||
htsmsg_add_u32(msg, "hour", cron->hour);
|
||||
htsmsg_add_u32(msg, "dom", cron->dom);
|
||||
htsmsg_add_u32(msg, "mon", cron->mon);
|
||||
htsmsg_add_u32(msg, "dow", cron->dow);
|
||||
time_t now;
|
||||
time(&now);
|
||||
now += 60;
|
||||
return (now / 60) * 60; // round to start of minute
|
||||
}
|
||||
|
||||
void cron_unpack ( cron_t *cron, htsmsg_t *msg )
|
||||
|
||||
void cron_serialize ( cron_t *cron, htsmsg_t *msg )
|
||||
{
|
||||
uint32_t u32 = 0;
|
||||
htsmsg_get_u64(msg, "min", &cron->min);
|
||||
htsmsg_get_u32(msg, "hour", &cron->hour);
|
||||
htsmsg_get_u32(msg, "dom", &cron->dom);
|
||||
htsmsg_get_u32(msg, "mon", &u32);
|
||||
cron->mon = (uint16_t)u32;
|
||||
htsmsg_get_u32(msg, "dow", &u32);
|
||||
cron->dow = (uint8_t)u32;
|
||||
htsmsg_add_str(msg, "cron", cron->str);
|
||||
}
|
||||
|
||||
cron_t *cron_deserialize ( htsmsg_t *msg )
|
||||
{
|
||||
// TODO: validate the string!
|
||||
cron_t *cron = cron_create();
|
||||
const char *str = htsmsg_get_str(msg, "cron");
|
||||
if (str) cron_set_string(cron, str);
|
||||
return cron;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int main ( int argc, char **argv )
|
||||
{
|
||||
cron_t *c = cron_create();
|
||||
cron_set_string(c, argv[1]);
|
||||
printf("min = 0x%016lx\n", c->min);
|
||||
printf("hour = 0x%06x\n", c->hour);
|
||||
printf("dom = 0x%08x\n", c->dom);
|
||||
printf("mon = 0x%03hx\n", c->mon);
|
||||
printf("dow = 0x%0hhx\n", c->dow);
|
||||
cron_destroy(c);
|
||||
}
|
||||
#endif
|
||||
|
|
22
src/cron.h
22
src/cron.h
|
@ -11,19 +11,15 @@
|
|||
#define CRON_MON_MASK 0x0FFF // 12 bits
|
||||
#define CRON_DOW_MASK 0xFF // 8 bits (allow 0/7 for sunday)
|
||||
|
||||
typedef struct cron
|
||||
{
|
||||
uint64_t min; ///< Minutes
|
||||
uint32_t hour; ///< Hours
|
||||
uint32_t dom; ///< Day of month
|
||||
uint16_t mon; ///< Month
|
||||
uint8_t dow; ///< Day of week
|
||||
} cron_t;
|
||||
typedef struct cron cron_t;
|
||||
|
||||
void cron_to_string ( cron_t *cron, char *str );
|
||||
void cron_from_string ( cron_t *cron, const char *str );
|
||||
int cron_is_time ( cron_t *cron );
|
||||
void cron_pack ( cron_t *cron, htsmsg_t *msg );
|
||||
void cron_unpack ( cron_t *cron, htsmsg_t *msg );
|
||||
cron_t *cron_create ( void );
|
||||
void cron_destroy ( cron_t *cron );
|
||||
const char *cron_get_string ( cron_t *cron );
|
||||
int cron_set_string ( cron_t *cron, const char *str );
|
||||
int cron_is_time ( cron_t *cron );
|
||||
time_t cron_next ( cron_t *cron );
|
||||
void cron_serialize ( cron_t *cron, htsmsg_t *msg );
|
||||
cron_t *cron_deserialize ( htsmsg_t *msg );
|
||||
|
||||
#endif /* __CRON_H__ */
|
||||
|
|
Loading…
Add table
Reference in a new issue