X-Git-Url: https://git.octo.it/?a=blobdiff_plain;ds=sidebyside;f=src%2Frrd_daemon.c;h=8b23e5202a236676978b09ae1baaa6d9e4c35074;hb=3426dc792f7e35312ed11ccb07b483f8ed3c8b12;hp=3e9253017906dfab217dfa864fd6858f2750171f;hpb=86aa7285af4982db2d467680157a2114fb0096a0;p=rrdtool.git diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c index 3e92530..8b23e52 100644 --- a/src/rrd_daemon.c +++ b/src/rrd_daemon.c @@ -117,7 +117,7 @@ struct listen_socket_s socket_privilege privilege; /* state for BATCH processing */ - int batch_mode; + time_t batch_start; int batch_cmd; /* buffered IO */ @@ -405,7 +405,7 @@ static int add_response_info(listen_socket_t *sock, char *fmt, ...) /* {{{ */ int len; if (sock == NULL) return 0; /* journal replay mode */ - if (sock->batch_mode) return 0; /* no extra info returned when in BATCH */ + if (sock->batch_start) return 0; /* no extra info returned when in BATCH */ va_start(argp, fmt); #ifdef HAVE_VSNPRINTF @@ -453,7 +453,7 @@ static int send_response (listen_socket_t *sock, response_code rc, if (sock == NULL) return rc; /* journal replay mode */ - if (sock->batch_mode) + if (sock->batch_start) { if (rc == RESP_OK) return rc; /* no response on success during BATCH */ @@ -478,7 +478,7 @@ static int send_response (listen_socket_t *sock, response_code rc, len += rclen; /* append the result to the wbuf, don't write to the user */ - if (sock->batch_mode) + if (sock->batch_start) return add_to_wbuf(sock, buffer, len); /* first write must be complete */ @@ -748,8 +748,8 @@ static void *queue_thread_main (void *args __attribute__((unused))) /* {{{ */ flush_old_values (config_write_interval); /* Determine the time of the next cache flush. */ - while (next_flush.tv_sec <= now.tv_sec) - next_flush.tv_sec += config_flush_interval; + next_flush.tv_sec = + now.tv_sec + next_flush.tv_sec % config_flush_interval; /* unlock the cache while we rotate so we don't block incoming * updates if the fsync() blocks on disk I/O */ @@ -956,6 +956,26 @@ err: return 0; } /* }}} static int check_file_access */ +/* when using a base dir, convert relative paths to absolute paths. + * if necessary, modifies the "filename" pointer to point + * to the new path created in "tmp". "tmp" is provided + * by the caller and sizeof(tmp) must be >= PATH_MAX. + * + * this allows us to optimize for the expected case (absolute path) + * with a no-op. + */ +static void get_abs_path(char **filename, char *tmp) +{ + assert(tmp != NULL); + assert(filename != NULL && *filename != NULL); + + if (config_base_dir == NULL || **filename == '/') + return; + + snprintf(tmp, PATH_MAX, "%s/%s", config_base_dir, *filename); + *filename = tmp; +} /* }}} static int get_abs_path */ + /* returns 1 if we have the required privilege level, * otherwise issue an error to the user on sock */ static int has_privilege (listen_socket_t *sock, /* {{{ */ @@ -1183,7 +1203,7 @@ static int handle_request_stats (listen_socket_t *sock) /* {{{ */ static int handle_request_flush (listen_socket_t *sock, /* {{{ */ char *buffer, size_t buffer_size) { - char *file; + char *file, file_tmp[PATH_MAX]; int status; status = buffer_get_field (&buffer, &buffer_size, &file); @@ -1197,6 +1217,7 @@ static int handle_request_flush (listen_socket_t *sock, /* {{{ */ stats_flush_received++; pthread_mutex_unlock(&stats_lock); + get_abs_path(&file, file_tmp); if (!check_file_access(file, sock)) return 0; status = flush_file (file); @@ -1221,7 +1242,7 @@ static int handle_request_flush (listen_socket_t *sock, /* {{{ */ /* NOTREACHED */ assert(1==0); -} /* }}} int handle_request_slurp */ +} /* }}} int handle_request_flush */ static int handle_request_flushall(listen_socket_t *sock) /* {{{ */ { @@ -1244,7 +1265,7 @@ static int handle_request_pending(listen_socket_t *sock, /* {{{ */ char *buffer, size_t buffer_size) { int status; - char *file; + char *file, file_tmp[PATH_MAX]; cache_item_t *ci; status = buffer_get_field(&buffer, &buffer_size, &file); @@ -1256,6 +1277,8 @@ static int handle_request_pending(listen_socket_t *sock, /* {{{ */ if (status <= 0) return status; + get_abs_path(&file, file_tmp); + pthread_mutex_lock(&cache_lock); ci = g_tree_lookup(cache_tree, file); if (ci == NULL) @@ -1275,7 +1298,7 @@ static int handle_request_forget(listen_socket_t *sock, /* {{{ */ char *buffer, size_t buffer_size) { int status; - char *file; + char *file, file_tmp[PATH_MAX]; status = buffer_get_field(&buffer, &buffer_size, &file); if (status != 0) @@ -1286,6 +1309,7 @@ static int handle_request_forget(listen_socket_t *sock, /* {{{ */ if (status <= 0) return status; + get_abs_path(&file, file_tmp); if (!check_file_access(file, sock)) return 0; pthread_mutex_lock(&cache_lock); @@ -1308,19 +1332,17 @@ static int handle_request_forget(listen_socket_t *sock, /* {{{ */ } /* }}} static int handle_request_forget */ static int handle_request_update (listen_socket_t *sock, /* {{{ */ - char *buffer, size_t buffer_size) + time_t now, + char *buffer, size_t buffer_size) { - char *file; + char *file, file_tmp[PATH_MAX]; int values_num = 0; int bad_timestamps = 0; int status; char orig_buf[CMD_MAX]; - time_t now; cache_item_t *ci; - now = time (NULL); - status = has_privilege(sock, PRIV_HIGH); if (status <= 0) return status; @@ -1337,6 +1359,7 @@ static int handle_request_update (listen_socket_t *sock, /* {{{ */ stats_updates_received++; pthread_mutex_unlock(&stats_lock); + get_abs_path(&file, file_tmp); if (!check_file_access(file, sock)) return 0; pthread_mutex_lock (&cache_lock); @@ -1487,7 +1510,7 @@ static int handle_request_update (listen_socket_t *sock, /* {{{ */ /* we came across a "WROTE" entry during journal replay. * throw away any values that we have accumulated for this file */ -static int handle_request_wrote (const char *buffer) /* {{{ */ +static int handle_request_wrote (const char *buffer, time_t now) /* {{{ */ { int i; cache_item_t *ci; @@ -1510,7 +1533,7 @@ static int handle_request_wrote (const char *buffer) /* {{{ */ free(ci->values); } - wipe_ci_values(ci, time(NULL)); + wipe_ci_values(ci, now); remove_from_queue(ci); pthread_mutex_unlock(&cache_lock); @@ -1521,12 +1544,12 @@ static int handle_request_wrote (const char *buffer) /* {{{ */ static int batch_start (listen_socket_t *sock) /* {{{ */ { int status; - if (sock->batch_mode) + if (sock->batch_start) return send_response(sock, RESP_ERR, "Already in BATCH\n"); status = send_response(sock, RESP_OK, "Go ahead. End with dot '.' on its own line.\n"); - sock->batch_mode = 1; + sock->batch_start = time(NULL); sock->batch_cmd = 0; return status; @@ -1535,14 +1558,15 @@ static int batch_start (listen_socket_t *sock) /* {{{ */ /* finish "BATCH" processing and return results to the client */ static int batch_done (listen_socket_t *sock) /* {{{ */ { - assert(sock->batch_mode); - sock->batch_mode = 0; + assert(sock->batch_start); + sock->batch_start = 0; sock->batch_cmd = 0; return send_response(sock, RESP_OK, "errors\n"); } /* }}} static int batch_done */ /* if sock==NULL, we are in journal replay mode */ static int handle_request (listen_socket_t *sock, /* {{{ */ + time_t now, char *buffer, size_t buffer_size) { char *buffer_ptr; @@ -1560,15 +1584,15 @@ static int handle_request (listen_socket_t *sock, /* {{{ */ return (-1); } - if (sock != NULL && sock->batch_mode) + if (sock != NULL && sock->batch_start) sock->batch_cmd++; if (strcasecmp (command, "update") == 0) - return (handle_request_update (sock, buffer_ptr, buffer_size)); + return (handle_request_update (sock, now, buffer_ptr, buffer_size)); else if (strcasecmp (command, "wrote") == 0 && sock == NULL) { /* this is only valid in replay mode */ - return (handle_request_wrote (buffer_ptr)); + return (handle_request_wrote (buffer_ptr, now)); } else if (strcasecmp (command, "flush") == 0) return (handle_request_flush (sock, buffer_ptr, buffer_size)); @@ -1584,7 +1608,7 @@ static int handle_request (listen_socket_t *sock, /* {{{ */ return (handle_request_help (sock, buffer_ptr, buffer_size)); else if (strcasecmp (command, "batch") == 0 && sock != NULL) return batch_start(sock); - else if (strcasecmp (command, ".") == 0 && sock != NULL && sock->batch_mode) + else if (strcasecmp (command, ".") == 0 && sock != NULL && sock->batch_start) return batch_done(sock); else return send_response(sock, RESP_ERR, "Unknown command: %s\n", command); @@ -1700,6 +1724,7 @@ static int journal_replay (const char *file) /* {{{ */ int fail_cnt = 0; uint64_t line = 0; char entry[CMD_MAX]; + time_t now; if (file == NULL) return 0; @@ -1752,6 +1777,8 @@ static int journal_replay (const char *file) /* {{{ */ else RRDD_LOG(LOG_NOTICE, "replaying from journal: %s", file); + now = time(NULL); + while(!feof(fh)) { size_t entry_len; @@ -1773,7 +1800,7 @@ static int journal_replay (const char *file) /* {{{ */ entry[entry_len - 1] = '\0'; - if (handle_request(NULL, entry, entry_len) == 0) + if (handle_request(NULL, now, entry, entry_len) == 0) ++entry_cnt; else ++fail_cnt; @@ -1864,6 +1891,7 @@ static void *connection_thread_main (void *args) /* {{{ */ char *cmd; ssize_t cmd_len; ssize_t rbytes; + time_t now; struct pollfd pollfd; int status; @@ -1907,9 +1935,14 @@ static void *connection_thread_main (void *args) /* {{{ */ sock->next_read += rbytes; + if (sock->batch_start) + now = sock->batch_start; + else + now = time(NULL); + while ((cmd = next_cmd(sock, &cmd_len)) != NULL) { - status = handle_request (sock, cmd, cmd_len+1); + status = handle_request (sock, now, cmd, cmd_len+1); if (status != 0) goto out_close; }