+static int buffer_get_field (char **buffer_ret, /* {{{ */
+ size_t *buffer_size_ret, char **field_ret)
+{
+ char *buffer;
+ size_t buffer_pos;
+ size_t buffer_size;
+ char *field;
+ size_t field_size;
+ int status;
+
+ buffer = *buffer_ret;
+ buffer_pos = 0;
+ buffer_size = *buffer_size_ret;
+ field = *buffer_ret;
+ field_size = 0;
+
+ /* This is ensured by `handle_request'. */
+ assert (buffer[buffer_size - 1] == ' ');
+
+ status = -1;
+ while (buffer_pos < buffer_size)
+ {
+ /* Check for end-of-field or end-of-buffer */
+ if (buffer[buffer_pos] == ' ')
+ {
+ field[field_size] = 0;
+ field_size++;
+ buffer_pos++;
+ status = 0;
+ break;
+ }
+ /* Handle escaped characters. */
+ else if (buffer[buffer_pos] == '\\')
+ {
+ if (buffer_pos >= (buffer_size - 1))
+ break;
+ buffer_pos++;
+ field[field_size] = buffer[buffer_pos];
+ field_size++;
+ buffer_pos++;
+ }
+ /* Normal operation */
+ else
+ {
+ field[field_size] = buffer[buffer_pos];
+ field_size++;
+ buffer_pos++;
+ }
+ } /* while (buffer_pos < buffer_size) */
+
+ if (status != 0)
+ return (status);
+
+ *buffer_ret = buffer + buffer_pos;
+ *buffer_size_ret = buffer_size - buffer_pos;
+ *field_ret = field;
+
+ return (0);
+} /* }}} int buffer_get_field */
+
+static int flush_file (const char *filename) /* {{{ */
+{
+ cache_item_t *ci;
+
+ pthread_mutex_lock (&cache_lock);
+
+ ci = g_tree_lookup (cache_tree, filename);
+ if (ci == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ return (ENOENT);
+ }
+
+ /* Enqueue at head */
+ enqueue_cache_item (ci, HEAD);
+ pthread_cond_signal (&cache_cond);
+
+ while ((ci->flags & CI_FLAGS_IN_QUEUE) != 0)
+ {
+ ci = NULL;
+
+ pthread_cond_wait (&flush_cond, &cache_lock);
+
+ ci = g_tree_lookup (cache_tree, filename);
+ if (ci == NULL)
+ {
+ RRDD_LOG (LOG_ERR, "flush_file: Tree node went away "
+ "while waiting for flush.");
+ pthread_mutex_unlock (&cache_lock);
+ return (-1);
+ }
+ }
+
+ pthread_mutex_unlock (&cache_lock);
+ return (0);
+} /* }}} int flush_file */
+
+static int handle_request_flush (int fd, /* {{{ */
+ char *buffer, size_t buffer_size)
+{
+ char *file;
+ int status;
+ char result[4096];
+
+ status = buffer_get_field (&buffer, &buffer_size, &file);
+ if (status != 0)
+ {
+ RRDD_LOG (LOG_INFO, "handle_request_flush: Cannot get file name.");
+ return (-1);
+ }
+
+ status = flush_file (file);
+ if (status == 0)
+ snprintf (result, sizeof (result), "0 Successfully flushed %s.\n", file);
+ else if (status == ENOENT)
+ snprintf (result, sizeof (result), "-1 No such file: %s.\n", file);
+ else if (status < 0)
+ strncpy (result, "-1 Internal error.\n", sizeof (result));
+ else
+ snprintf (result, sizeof (result), "-1 Failed with status %i.\n", status);
+ result[sizeof (result) - 1] = 0;
+
+ status = write (fd, result, strlen (result));
+ if (status < 0)
+ {
+ status = errno;
+ RRDD_LOG (LOG_INFO, "handle_request_flush: write(2) returned an error.");
+ return (status);
+ }
+
+ return (0);
+} /* }}} int handle_request_flush */
+