+ for (int i=0; i < ci->values_num; i++)
+ add_response_info(sock, "%s\n", ci->values[i]);
+
+ pthread_mutex_unlock(&cache_lock);
+ return send_response(sock, RESP_OK, "updates pending\n");
+} /* }}} static int handle_request_pending */
+
+static int handle_request_forget(listen_socket_t *sock, /* {{{ */
+ char *buffer, size_t buffer_size)
+{
+ int status;
+ char *file, file_tmp[PATH_MAX];
+
+ status = buffer_get_field(&buffer, &buffer_size, &file);
+ if (status != 0)
+ return send_response(sock, RESP_ERR,
+ "Usage: FORGET <filename>\n");
+
+ status = has_privilege(sock, PRIV_HIGH);
+ if (status <= 0)
+ return status;
+
+ get_abs_path(&file, file_tmp);
+ if (!check_file_access(file, sock)) return 0;
+
+ pthread_mutex_lock(&cache_lock);
+ status = forget_file(file);
+ pthread_mutex_unlock(&cache_lock);
+
+ if (status == 0)
+ {
+ 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));
+
+ /* NOTREACHED */
+ assert(1==0);
+} /* }}} static int handle_request_forget */
+
+static int handle_request_update (listen_socket_t *sock, /* {{{ */
+ time_t now,
+ char *buffer, size_t buffer_size)
+{
+ char *file, file_tmp[PATH_MAX];
+ int values_num = 0;
+ int bad_timestamps = 0;
+ int status;
+ char orig_buf[CMD_MAX];
+
+ cache_item_t *ci;
+
+ status = has_privilege(sock, PRIV_HIGH);
+ if (status <= 0)
+ return status;
+
+ /* save it for the journal later */
+ strncpy(orig_buf, buffer, sizeof(orig_buf)-1);
+
+ status = buffer_get_field (&buffer, &buffer_size, &file);
+ if (status != 0)
+ return send_response(sock, RESP_ERR,
+ "Usage: UPDATE <filename> <values> [<values> ...]\n");
+
+ pthread_mutex_lock(&stats_lock);
+ 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);