From b5e4fce1f3297a4a05b09163b844f0990ea3d455 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 12 Mar 2016 13:21:48 +0000 Subject: [PATCH] [Fetaure] Be more clever about map timeouts --- src/libutil/map.c | 63 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/src/libutil/map.c b/src/libutil/map.c index 7328cb5a5..d37d5e235 100644 --- a/src/libutil/map.c +++ b/src/libutil/map.c @@ -446,7 +446,7 @@ http_map_read (struct rspamd_http_connection *conn, /** * Callback for reading data from file */ -static void +static gboolean read_map_file (struct rspamd_map *map, struct file_map_data *data) { struct map_cb_data cbdata; @@ -456,14 +456,20 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data) if (map->read_callback == NULL || map->fin_callback == NULL) { msg_err_pool ("bad callback for reading map file"); - return; + return FALSE; + } + + if (access (data->filename, R_OK) == -1) { + /* File does not exist, skipping */ + msg_err_pool ("map file is unavailable for reading"); + return FALSE; } bytes = rspamd_file_xmap (data->filename, PROT_READ, &len); if (bytes == NULL) { msg_err_pool ("can't open map %s: %s", data->filename, strerror (errno)); - return; + return FALSE; } cbdata.state = 0; @@ -475,7 +481,7 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data) if (!rspamd_map_check_file_sig (data->filename, map, bytes, len)) { munmap (bytes, len); - return; + return FALSE; } } @@ -487,17 +493,34 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data) } munmap (bytes, len); + + return TRUE; } static void -jitter_timeout_event (struct rspamd_map *map, gboolean locked, gboolean initial) +jitter_timeout_event (struct rspamd_map *map, + gboolean locked, gboolean initial, gboolean errored) { + const gdouble error_mult = 20.0, lock_mult = 4.0; gdouble jittered_sec; - gdouble timeout = initial ? 1.0 : map->cfg->map_timeout; + gdouble timeout; + + if (initial) { + timeout = 0.0; + } + else if (errored) { + timeout = map->cfg->map_timeout * error_mult; + } + else if (locked) { + timeout = map->cfg->map_timeout * lock_mult; + } + else { + timeout = map->cfg->map_timeout; + } /* Plan event again with jitter */ evtimer_del (&map->ev); - jittered_sec = rspamd_time_jitter (locked ? timeout * 4 : timeout, 0); + jittered_sec = rspamd_time_jitter (timeout, 0); double_to_tv (jittered_sec, &map->tv); evtimer_add (&map->ev, &map->tv); @@ -519,25 +542,32 @@ file_callback (gint fd, short what, void *ud) if (g_atomic_int_get (map->locked)) { msg_info_pool ( "don't try to reread map as it is locked by other process, will reread it later"); - jitter_timeout_event (map, TRUE, FALSE); + jitter_timeout_event (map, TRUE, FALSE, FALSE); return; } g_atomic_int_inc (map->locked); - jitter_timeout_event (map, FALSE, FALSE); - if (stat (data->filename, - &st) != -1 && + + if (stat (data->filename, &st) != -1 && (st.st_mtime > data->st.st_mtime || data->st.st_mtime == -1)) { /* File was modified since last check */ memcpy (&data->st, &st, sizeof (struct stat)); } else { g_atomic_int_set (map->locked, 0); + jitter_timeout_event (map, FALSE, FALSE, FALSE); return; } msg_info_pool ("rereading map file %s", data->filename); - read_map_file (map, data); + + if (!read_map_file (map, data)) { + jitter_timeout_event (map, FALSE, FALSE, TRUE); + } + else { + jitter_timeout_event (map, FALSE, FALSE, FALSE); + } + g_atomic_int_set (map->locked, 0); } @@ -609,7 +639,6 @@ http_callback (gint fd, short what, void *ud) data = map->map_data; pool = map->pool; - jitter_timeout_event (map, FALSE, FALSE); /* Plan event */ cbd = g_slice_alloc0 (sizeof (struct http_callback_data)); @@ -621,6 +650,8 @@ http_callback (gint fd, short what, void *ud) if (cbd->out_fd == -1) { g_slice_free1 (sizeof (*cbd), cbd); msg_err_pool ("cannot create tempfile: %s", strerror (errno)); + jitter_timeout_event (map, FALSE, FALSE, TRUE); + return; } @@ -645,10 +676,12 @@ http_callback (gint fd, short what, void *ud) rdns_make_request_full (map->r->r, rspamd_map_dns_callback, cbd, map->cfg->dns_timeout, map->cfg->dns_retransmits, 1, data->host, RDNS_REQUEST_AAAA); + jitter_timeout_event (map, FALSE, FALSE, FALSE); } else { msg_warn_pool ("cannot load map: DNS resolver is not initialized"); free_http_cbdata (cbd); + jitter_timeout_event (map, FALSE, FALSE, TRUE); } } @@ -678,11 +711,11 @@ rspamd_map_watch (struct rspamd_config *cfg, read_map_file (map, map->map_data); } /* Plan event with jitter */ - jitter_timeout_event (map, FALSE, TRUE); + jitter_timeout_event (map, FALSE, TRUE, FALSE); } else if (map->protocol == MAP_PROTO_HTTP) { evtimer_set (&map->ev, http_callback, map); - jitter_timeout_event (map, FALSE, TRUE); + jitter_timeout_event (map, FALSE, TRUE, FALSE); } cur = g_list_next (cur); -- 2.39.5