+ 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);
+
+ /* NOTREACHED */
+ assert(1==0);
+
+} /* }}} int handle_request_update */
+
+/* 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 (HANDLER_PROTO) /* {{{ */
+{
+ cache_item_t *ci;
+ const char *file = buffer;
+
+ pthread_mutex_lock(&cache_lock);
+
+ ci = g_tree_lookup(cache_tree, file);
+ if (ci == NULL)
+ {
+ pthread_mutex_unlock(&cache_lock);
+ return (0);
+ }
+
+ if (ci->values)
+ rrd_free_ptrs((void ***) &ci->values, &ci->values_num);
+
+ wipe_ci_values(ci, now);
+ remove_from_queue(ci);
+
+ pthread_mutex_unlock(&cache_lock);
+ return (0);
+} /* }}} int handle_request_wrote */
+
+/* start "BATCH" processing */
+static int batch_start (HANDLER_PROTO) /* {{{ */
+{
+ int status;
+ 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_start = time(NULL);
+ sock->batch_cmd = 0;
+
+ return status;
+} /* }}} static int batch_start */
+
+/* finish "BATCH" processing and return results to the client */
+static int batch_done (HANDLER_PROTO) /* {{{ */
+{
+ assert(sock->batch_start);
+ sock->batch_start = 0;
+ sock->batch_cmd = 0;
+ return send_response(sock, RESP_OK, "errors\n");
+} /* }}} static int batch_done */
+
+static int handle_request_quit (HANDLER_PROTO) /* {{{ */
+{
+ return -1;
+} /* }}} static int handle_request_quit */
+
+struct command COMMANDS[] = {
+ {
+ "UPDATE",
+ handle_request_update,
+ PRIV_HIGH,
+ CMD_CONTEXT_ANY,
+ "UPDATE <filename> <values> [<values> ...]\n"
+ ,
+ "Adds the given file to the internal cache if it is not yet known and\n"
+ "appends the given value(s) to the entry. See the rrdcached(1) manpage\n"
+ "for details.\n"
+ "\n"
+ "Each <values> has the following form:\n"
+ " <values> = <time>:<value>[:<value>[...]]\n"
+ "See the rrdupdate(1) manpage for details.\n"
+ },
+ {
+ "WROTE",
+ handle_request_wrote,
+ PRIV_HIGH,
+ CMD_CONTEXT_JOURNAL,
+ NULL,
+ NULL
+ },
+ {
+ "FLUSH",
+ handle_request_flush,
+ PRIV_LOW,
+ CMD_CONTEXT_CLIENT | CMD_CONTEXT_BATCH,
+ "FLUSH <filename>\n"
+ ,
+ "Adds the given filename to the head of the update queue and returns\n"
+ "after it has been dequeued.\n"
+ },
+ {
+ "FLUSHALL",
+ handle_request_flushall,
+ PRIV_HIGH,
+ CMD_CONTEXT_CLIENT,
+ "FLUSHALL\n"
+ ,
+ "Triggers writing of all pending updates. Returns immediately.\n"
+ },
+ {
+ "PENDING",
+ handle_request_pending,
+ PRIV_HIGH,
+ CMD_CONTEXT_CLIENT,
+ "PENDING <filename>\n"
+ ,
+ "Shows any 'pending' updates for a file, in order.\n"
+ "The updates shown have not yet been written to the underlying RRD file.\n"
+ },
+ {
+ "FORGET",
+ handle_request_forget,
+ PRIV_HIGH,
+ CMD_CONTEXT_ANY,
+ "FORGET <filename>\n"
+ ,
+ "Removes the file completely from the cache.\n"
+ "Any pending updates for the file will be lost.\n"
+ },
+ {
+ "QUEUE",
+ handle_request_queue,
+ PRIV_LOW,
+ CMD_CONTEXT_CLIENT,
+ "QUEUE\n"
+ ,
+ "Shows all files in the output queue.\n"
+ "The output is zero or more lines in the following format:\n"
+ "(where <num_vals> is the number of values to be written)\n"
+ "\n"
+ "<num_vals> <filename>\n"
+ },
+ {
+ "STATS",
+ handle_request_stats,
+ PRIV_LOW,
+ CMD_CONTEXT_CLIENT,
+ "STATS\n"
+ ,
+ "Returns some performance counters, see the rrdcached(1) manpage for\n"
+ "a description of the values.\n"
+ },