/*
* Now for some includes..
*/
-#include "rrd.h" /* {{{ */
+/* {{{ */
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) && !defined(HAVE_CONFIG_H)
+#include "../win32/config.h"
+#else
+#ifdef HAVE_CONFIG_H
+#include "../rrd_config.h"
+#endif
+#endif
+
+#include "rrd.h"
#include "rrd_client.h"
#include <stdlib.h>
ci->flags &= ~CI_FLAGS_IN_QUEUE;
} /* }}} static void remove_from_queue */
-/* remove an entry from the tree and free all its resources.
- * must hold 'cache lock' while calling this.
- * returns 0 on success, otherwise errno */
-static int forget_file(const char *file)
+/* free the resources associated with the cache_item_t
+ * must hold cache_lock when calling this function
+ */
+static void *free_cache_item(cache_item_t *ci) /* {{{ */
{
- cache_item_t *ci;
-
- ci = g_tree_lookup(cache_tree, file);
- if (ci == NULL)
- return ENOENT;
+ if (ci == NULL) return NULL;
- g_tree_remove (cache_tree, file);
remove_from_queue(ci);
for (int i=0; i < ci->values_num; i++)
free (ci);
- return 0;
-} /* }}} static int forget_file */
+ return NULL;
+} /* }}} static void *free_cache_item */
/*
* enqueue_cache_item:
{
/* should never fail, since we have held the cache_lock
* the entire time */
- assert( forget_file(cfd.keys[k]) == 0 );
+ assert( g_tree_remove(cache_tree, cfd.keys[k]) == TRUE );
}
if (cfd.keys != NULL)
char *buffer, size_t buffer_size)
{
int status;
+ gboolean found;
char *file, file_tmp[PATH_MAX];
status = buffer_get_field(&buffer, &buffer_size, &file);
if (!check_file_access(file, sock)) return 0;
pthread_mutex_lock(&cache_lock);
- status = forget_file(file);
+ found = g_tree_remove(cache_tree, file);
pthread_mutex_unlock(&cache_lock);
- if (status == 0)
+ if (found == TRUE)
{
if (sock != NULL)
journal_write("forget", file);
return send_response(sock, RESP_OK, "Gone!\n");
}
else
- return send_response(sock, RESP_ERR, "cannot forget: %s\n",
- status < 0 ? "Internal error" : rrd_strerror(status));
+ return send_response(sock, RESP_ERR, "%s\n", rrd_strerror(ENOENT));
/* NOTREACHED */
assert(1==0);
{
char *file, file_tmp[PATH_MAX];
int values_num = 0;
- int bad_timestamps = 0;
int status;
char orig_buf[CMD_MAX];
wipe_ci_values(ci, now);
ci->flags = CI_FLAGS_IN_TREE;
- ci->flushed = PTHREAD_COND_INITIALIZER;
+ pthread_cond_init(&ci->flushed, NULL);
pthread_mutex_lock(&cache_lock);
- g_tree_insert (cache_tree, (void *) ci->file, (void *) ci);
+ g_tree_replace (cache_tree, (void *) ci->file, (void *) ci);
} /* }}} */
assert (ci != NULL);
stamp = strtol(value, &eostamp, 10);
if (eostamp == value || eostamp == NULL || *eostamp != ':')
{
- ++bad_timestamps;
- add_response_info(sock, "Cannot find timestamp in '%s'!\n", value);
- continue;
+ pthread_mutex_unlock(&cache_lock);
+ return send_response(sock, RESP_ERR,
+ "Cannot find timestamp in '%s'!\n", value);
}
else if (stamp <= ci->last_update_stamp)
{
- ++bad_timestamps;
- add_response_info(sock,
- "illegal attempt to update using time %ld when"
- " last update time is %ld (minimum one second step)\n",
- stamp, ci->last_update_stamp);
- continue;
+ pthread_mutex_unlock(&cache_lock);
+ return send_response(sock, RESP_ERR,
+ "illegal attempt to update using time %ld when last"
+ " update time is %ld (minimum one second step)\n",
+ stamp, ci->last_update_stamp);
}
else
ci->last_update_stamp = stamp;
pthread_mutex_unlock (&cache_lock);
if (values_num < 1)
- {
- /* journal replay mode */
- if (sock == NULL) return RESP_ERR;
-
- /* if we had only one update attempt, then return the full
- error message... try to get the most information out
- of the limited error space allowed by the protocol
- */
- if (bad_timestamps == 1)
- return send_response(sock, RESP_ERR, "%s", sock->wbuf);
- else
- return send_response(sock, RESP_ERR,
- "No values updated (%d bad timestamps).\n",
- bad_timestamps);
- }
+ return send_response(sock, RESP_ERR, "No values updated.\n");
else
return send_response(sock, RESP_OK,
"errors, enqueued %i value(s).\n", values_num);
return batch_start(sock);
else if (strcasecmp (command, ".") == 0 && sock != NULL && sock->batch_start)
return batch_done(sock);
+ else if (strcasecmp (command, "quit") == 0)
+ return -1;
else
return send_response(sock, RESP_ERR, "Unknown command: %s\n", command);
if (file == NULL) return 0;
{
- char *reason;
+ char *reason = "unknown error";
int status = 0;
struct stat statbuf;
} /* }}} static void journal_init */
-static void close_connection(listen_socket_t *sock)
+static void free_listen_socket(listen_socket_t *sock) /* {{{ */
{
- close(sock->fd) ; sock->fd = -1;
+ assert(sock != NULL);
+
free(sock->rbuf); sock->rbuf = NULL;
free(sock->wbuf); sock->wbuf = NULL;
-
free(sock);
-}
+} /* }}} void free_listen_socket */
+
+static void close_connection(listen_socket_t *sock) /* {{{ */
+{
+ if (sock->fd >= 0)
+ {
+ close(sock->fd);
+ sock->fd = -1;
+ }
+
+ free_listen_socket(sock);
+
+} /* }}} void close_connection */
static void *connection_thread_main (void *args) /* {{{ */
{
- pthread_t self;
listen_socket_t *sock;
int i;
int fd;
sizeof (pthread_t) * (connection_threads_num + 1));
if (temp == NULL)
{
- RRDD_LOG (LOG_ERR, "connection_thread_main: realloc failed.");
+ RRDD_LOG (LOG_ERR, "connection_thread_main: realloc(++) failed.");
}
else
{
out_close:
close_connection(sock);
- self = pthread_self ();
/* Remove this thread from the connection threads list */
pthread_mutex_lock (&connection_threads_lock);
- /* Find out own index in the array */
- for (i = 0; i < connection_threads_num; i++)
- if (pthread_equal (connection_threads[i], self) != 0)
- break;
- assert (i < connection_threads_num);
-
- /* Move the trailing threads forward. */
- if (i < (connection_threads_num - 1))
{
- memmove (connection_threads + i,
- connection_threads + i + 1,
- sizeof (pthread_t) * (connection_threads_num - i - 1));
- }
+ pthread_t self;
+ pthread_t *temp;
- connection_threads_num--;
+ /* Find out own index in the array */
+ self = pthread_self ();
+ for (i = 0; i < connection_threads_num; i++)
+ if (pthread_equal (connection_threads[i], self) != 0)
+ break;
+ assert (i < connection_threads_num);
+
+ /* Move the trailing threads forward. */
+ if (i < (connection_threads_num - 1))
+ {
+ memmove (connection_threads + i,
+ connection_threads + i + 1,
+ sizeof (pthread_t) * (connection_threads_num - i - 1));
+ }
+
+ connection_threads_num--;
+
+ temp = realloc(connection_threads,
+ sizeof(*connection_threads) * connection_threads_num);
+ if (connection_threads_num > 0 && temp == NULL)
+ RRDD_LOG(LOG_ERR, "connection_thread_main: realloc(--) failed.");
+ else
+ connection_threads = temp;
+ }
pthread_mutex_unlock (&connection_threads_lock);
return (NULL);
fprintf (stderr, "rrdcached: listen(%s) failed: %s\n.",
sock->addr, rrd_strerror(errno));
close (fd);
+ freeaddrinfo(ai_res);
return (-1);
}
listen_fds_num++;
} /* for (ai_ptr) */
+ freeaddrinfo(ai_res);
return (0);
} /* }}} static int open_listen_socket_network */
while (do_shutdown == 0)
{
- assert (pollfds_num == ((int) listen_fds_num));
for (i = 0; i < pollfds_num; i++)
{
pollfds[i].fd = listen_fds[i].fd;
}
pthread_mutex_unlock (&connection_threads_lock);
+ free(pollfds);
+
return (NULL);
} /* }}} void *listen_thread_main */
if (config_listen_address_list_len > 0)
{
for (int i = 0; i < config_listen_address_list_len; i++)
+ {
open_listen_socket (config_listen_address_list[i]);
+ free_listen_socket (config_listen_address_list[i]);
+ }
+
+ free(config_listen_address_list);
}
else
{
openlog ("rrdcached", LOG_PID, LOG_DAEMON);
RRDD_LOG(LOG_INFO, "starting up");
- cache_tree = g_tree_new ((GCompareFunc) strcmp);
+ cache_tree = g_tree_new_full ((GCompareDataFunc) strcmp, NULL, NULL,
+ (GDestroyNotify) free_cache_item);
if (cache_tree == NULL)
{
RRDD_LOG (LOG_ERR, "daemonize: g_tree_new failed.");
remove_pidfile ();
+ free(config_base_dir);
+ free(config_pid_file);
+ free(journal_cur);
+ free(journal_old);
+
+ pthread_mutex_lock(&cache_lock);
+ g_tree_destroy(cache_tree);
+
RRDD_LOG(LOG_INFO, "goodbye");
closelog ();