diff --git a/master.c b/master.c index 9b43c0ca..93c41464 100644 --- a/master.c +++ b/master.c @@ -125,7 +125,7 @@ void master_loop(char **argv, char **environ) { char log_buf[4096]; - uint64_t current_time = time(NULL); + time_t current_time = time(NULL); struct timeval last_respawn; @@ -172,21 +172,19 @@ void master_loop(char **argv, char **environ) { struct uwsgi_rb_timer *min_timeout; struct rb_root *rb_timers = uwsgi_init_rb_timer(); + struct tm *uwsgi_cron_delta; - // release the GIL - //UWSGI_RELEASE_GIL - /* route signals to workers... */ uwsgi_unix_signal(SIGHUP, grace_them_all); uwsgi_unix_signal(SIGTERM, reap_them_all); uwsgi_unix_signal(SIGINT, kill_them_all); uwsgi_unix_signal(SIGQUIT, kill_them_all); - /* used only to avoid human-errors */ - uwsgi_unix_signal(SIGUSR1, stats); + uwsgi.master_queue = event_queue_init(); + /* route signals to workers... */ #ifdef UWSGI_DEBUG uwsgi_log("adding %d to signal poll\n", uwsgi.shared->worker_signal_pipe[0]); #endif @@ -500,6 +498,75 @@ void master_loop(char **argv, char **environ) { } } + + // check uwsgi-cron table + if (ushared->cron_cnt) { + current_time = time(NULL); + uwsgi_cron_delta = localtime( ¤t_time ); + + if (uwsgi_cron_delta) { + + // fix month + uwsgi_cron_delta->tm_mon++; + + uwsgi_lock(uwsgi.cron_table_lock); + for(i=0;icron_cnt;i++) { + + struct uwsgi_cron *ucron = &ushared->cron[i]; + int uc_minute, uc_hour, uc_day, uc_month, uc_week; + + uc_minute = ucron->minute; + uc_hour = ucron->hour; + uc_day = ucron->day; + uc_month = ucron->month; + uc_week = ucron->week; + + if (ucron->minute == -1) uc_minute = uwsgi_cron_delta->tm_min; + if (ucron->hour == -1) uc_hour = uwsgi_cron_delta->tm_hour; + if (ucron->month == -1) uc_month = uwsgi_cron_delta->tm_mon; + + // mday and wday are ORed + if (ucron->day == -1 && ucron->week == -1) { + if (ucron->day == -1) uc_day = uwsgi_cron_delta->tm_mday; + if (ucron->week == -1) uc_week = uwsgi_cron_delta->tm_wday; + } + else if (ucron->day == -1) { + ucron->day = uwsgi_cron_delta->tm_mday; + } + else if (ucron->week == -1) { + ucron->week = uwsgi_cron_delta->tm_wday; + } + else { + if (ucron->day == uwsgi_cron_delta->tm_mday) { + ucron->week = uwsgi_cron_delta->tm_wday; + } + else if (ucron->week == uwsgi_cron_delta->tm_wday) { + ucron->day = uwsgi_cron_delta->tm_mday; + } + } + + if (uwsgi_cron_delta->tm_min == uc_minute && + uwsgi_cron_delta->tm_hour == uc_hour && + uwsgi_cron_delta->tm_mon == uc_month && + uwsgi_cron_delta->tm_mday == uc_day && + uwsgi_cron_delta->tm_wday == uc_week) { + + + // date match, signal it ? + if (current_time - ucron->last_job > 60) { + uwsgi_route_signal(ucron->sig); + ucron->last_job = current_time; + } + } + + } + uwsgi_unlock(uwsgi.cron_table_lock); + } + else { + uwsgi_error("localtime()"); + } + } + if (rlen > 0) { if (uwsgi.log_master) { @@ -726,7 +793,7 @@ void master_loop(char **argv, char **environ) { for(i=0;i< (int)uwsgi.cache_max_items;i++) { uwsgi_wlock(uwsgi.cache_lock); if (uwsgi.cache_items[i].expires) { - if (uwsgi.cache_items[i].expires < current_time) { + if (uwsgi.cache_items[i].expires < (uint64_t) current_time) { uwsgi_cache_del(uwsgi.cache_items[i].key, uwsgi.cache_items[i].keysize); } } diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index 38aa6b0a..0ea78480 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -181,6 +181,25 @@ PyObject *py_uwsgi_close(PyObject * self, PyObject * args) { } +PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) { + + uint8_t uwsgi_signal; + int minute, hour, day, month, week; + + if (!PyArg_ParseTuple(args, "Biiiii:add_cron", &uwsgi_signal, &minute, &hour, &day, &month, &week)) { + return NULL; + } + + if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) { + return PyErr_Format(PyExc_ValueError, "unable to add cron"); + } + + Py_INCREF(Py_True); + return Py_True; +} + + + PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) { uint8_t uwsgi_signal; @@ -2343,6 +2362,7 @@ static PyMethodDef uwsgi_advanced_methods[] = { {"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""}, {"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""}, {"add_rb_timer", py_uwsgi_add_rb_timer, METH_VARARGS, ""}, + {"add_cron", py_uwsgi_add_cron, METH_VARARGS, ""}, {"register_rpc", py_uwsgi_register_rpc, METH_VARARGS, ""}, {"rpc", py_uwsgi_rpc, METH_VARARGS, ""}, diff --git a/signal.c b/signal.c index a3aa5432..d6a3fca6 100644 --- a/signal.c +++ b/signal.c @@ -91,6 +91,31 @@ int uwsgi_add_timer(uint8_t sig, int secs) { } +int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) { + + uwsgi_lock(uwsgi.cron_table_lock); + + if (ushared->cron_cnt < MAX_CRONS) { + + ushared->cron[ushared->cron_cnt].sig = sig; + ushared->cron[ushared->cron_cnt].minute = minute; + ushared->cron[ushared->cron_cnt].hour = hour; + ushared->cron[ushared->cron_cnt].day = day; + ushared->cron[ushared->cron_cnt].month = month; + ushared->cron[ushared->cron_cnt].week = week; + ushared->cron_cnt++; + } + else { + uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS); + uwsgi_unlock(uwsgi.cron_table_lock); + return -1; + } + + uwsgi_unlock(uwsgi.cron_table_lock); + + return 0; +} + int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) { uwsgi_lock(uwsgi.rb_timer_table_lock); diff --git a/uwsgi.c b/uwsgi.c index b8dd4469..16cd093b 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -1251,6 +1251,10 @@ int uwsgi_start(void *v_argv) { // daemons table lock uwsgi.daemon_table_lock = uwsgi_mmap_shared_lock(); uwsgi_lock_init(uwsgi.daemon_table_lock); + + // cron table lock + uwsgi.cron_table_lock = uwsgi_mmap_shared_lock(); + uwsgi_lock_init(uwsgi.cron_table_lock); } if (uwsgi.spool_dir) { diff --git a/uwsgi.h b/uwsgi.h index 147ec217..c5aa7b10 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -20,6 +20,7 @@ #define MAX_GATEWAYS 64 #define MAX_DAEMONS 8 #define MAX_SUBSCRIPTIONS 8 +#define MAX_CRONS 64 #ifndef UWSGI_LOAD_EMBEDDED_PLUGINS #define UWSGI_LOAD_EMBEDDED_PLUGINS @@ -978,6 +979,7 @@ struct uwsgi_server { void *fmon_table_lock; void *timer_table_lock; void *rb_timer_table_lock; + void *cron_table_lock; void *rpc_table_lock; void *spooler_lock; @@ -1063,6 +1065,18 @@ struct uwsgi_snmp_server_value { }; #endif +struct uwsgi_cron { + + int minute; + int hour; + int day; + int month; + int week; + + time_t last_job; + uint8_t sig; +}; + struct uwsgi_shared { //vga 80 x25 specific ! @@ -1118,6 +1132,9 @@ struct uwsgi_shared { #ifdef __linux__ struct tcp_info ti; #endif + + struct uwsgi_cron cron[MAX_CRONS]; + int cron_cnt; }; struct uwsgi_core { @@ -1590,3 +1607,5 @@ void uwsgi_nuclear_blast(); void uwsgi_unix_signal(int, void (*)(int)); char *uwsgi_get_exported_opt(char *); + +int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);