Merge branch 'collectd-5.5' into collectd-5.6
[collectd.git] / src / utils_cmd_flush.c
1 /**
2  * collectd - src/utils_cmd_flush.c
3  * Copyright (C) 2008       Sebastian Harl
4  * Copyright (C) 2008       Florian Forster
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *   Sebastian "tokkee" Harl <sh at tokkee.org>
26  *   Florian "octo" Forster <octo at collectd.org>
27  **/
28
29 #include "collectd.h"
30
31 #include "common.h"
32 #include "plugin.h"
33 #include "utils_cmd_flush.h"
34 #include "utils_parse_option.h"
35
36 int handle_flush(FILE *fh, char *buffer) {
37   int success = 0;
38   int error = 0;
39
40   double timeout = 0.0;
41   char **plugins = NULL;
42   size_t plugins_num = 0;
43   char **identifiers = NULL;
44   size_t identifiers_num = 0;
45
46 #define PRINT_TO_SOCK(fh, ...)                                                 \
47   do {                                                                         \
48     if (fprintf(fh, __VA_ARGS__) < 0) {                                        \
49       char errbuf[1024];                                                       \
50       WARNING("handle_flush: failed to write to socket #%i: %s", fileno(fh),   \
51               sstrerror(errno, errbuf, sizeof(errbuf)));                       \
52       strarray_free(plugins, plugins_num);                                     \
53       strarray_free(identifiers, identifiers_num);                             \
54       return -1;                                                               \
55     }                                                                          \
56     fflush(fh);                                                                \
57   } while (0)
58
59   if ((fh == NULL) || (buffer == NULL))
60     return (-1);
61
62   DEBUG("utils_cmd_flush: handle_flush (fh = %p, buffer = %s);", (void *)fh,
63         buffer);
64
65   if (strncasecmp("FLUSH", buffer, strlen("FLUSH")) != 0) {
66     PRINT_TO_SOCK(fh, "-1 Cannot parse command.\n");
67     return (-1);
68   }
69   buffer += strlen("FLUSH");
70
71   while (*buffer != 0) {
72     char *opt_key;
73     char *opt_value;
74     int status;
75
76     opt_key = NULL;
77     opt_value = NULL;
78     status = parse_option(&buffer, &opt_key, &opt_value);
79     if (status != 0) {
80       PRINT_TO_SOCK(fh, "-1 Parsing options failed.\n");
81       strarray_free(plugins, plugins_num);
82       strarray_free(identifiers, identifiers_num);
83       return (-1);
84     }
85
86     if (strcasecmp("plugin", opt_key) == 0)
87       strarray_add(&plugins, &plugins_num, opt_value);
88     else if (strcasecmp("identifier", opt_key) == 0)
89       strarray_add(&identifiers, &identifiers_num, opt_value);
90     else if (strcasecmp("timeout", opt_key) == 0) {
91       char *endptr;
92
93       errno = 0;
94       endptr = NULL;
95       timeout = strtod(opt_value, &endptr);
96
97       if ((endptr == opt_value) || (errno != 0) || (!isfinite(timeout))) {
98         PRINT_TO_SOCK(fh, "-1 Invalid value for option `timeout': "
99                           "%s\n",
100                       opt_value);
101         strarray_free(plugins, plugins_num);
102         strarray_free(identifiers, identifiers_num);
103         return (-1);
104       } else if (timeout < 0.0) {
105         timeout = 0.0;
106       }
107     } else {
108       PRINT_TO_SOCK(fh, "-1 Cannot parse option %s\n", opt_key);
109       strarray_free(plugins, plugins_num);
110       strarray_free(identifiers, identifiers_num);
111       return (-1);
112     }
113   } /* while (*buffer != 0) */
114
115   for (size_t i = 0; (i == 0) || (i < plugins_num); i++) {
116     char *plugin = NULL;
117
118     if (plugins_num != 0)
119       plugin = plugins[i];
120
121     for (size_t j = 0; (j == 0) || (j < identifiers_num); j++) {
122       char *identifier = NULL;
123       int status;
124
125       if (identifiers_num != 0)
126         identifier = identifiers[j];
127
128       status = plugin_flush(plugin, DOUBLE_TO_CDTIME_T(timeout), identifier);
129       if (status == 0)
130         success++;
131       else
132         error++;
133     }
134   }
135
136   PRINT_TO_SOCK(fh, "0 Done: %i successful, %i errors\n", success, error);
137
138   strarray_free(plugins, plugins_num);
139   strarray_free(identifiers, identifiers_num);
140   return (0);
141 #undef PRINT_TO_SOCK
142 } /* int handle_flush */
143
144 /* vim: set sw=4 ts=4 tw=78 noexpandtab : */