Merge branch 'collectd-5.7'
[collectd.git] / src / utils_cmd_flush.c
1 /**
2  * collectd - src/utils_cmd_flush.c
3  * Copyright (C) 2008, 2016 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
35 cmd_status_t cmd_parse_flush(size_t argc, char **argv, cmd_flush_t *ret_flush,
36                              const cmd_options_t *opts,
37                              cmd_error_handler_t *err) {
38
39   if ((ret_flush == NULL) || (opts == NULL)) {
40     errno = EINVAL;
41     cmd_error(CMD_ERROR, err, "Invalid arguments to cmd_parse_flush.");
42     return CMD_ERROR;
43   }
44
45   for (size_t i = 0; i < argc; i++) {
46     char *opt_key;
47     char *opt_value;
48     int status;
49
50     opt_key = NULL;
51     opt_value = NULL;
52     status = cmd_parse_option(argv[i], &opt_key, &opt_value, err);
53     if (status != 0) {
54       if (status == CMD_NO_OPTION)
55         cmd_error(CMD_PARSE_ERROR, err, "Invalid option string `%s'.", argv[i]);
56       cmd_destroy_flush(ret_flush);
57       return CMD_PARSE_ERROR;
58     }
59
60     if (strcasecmp("plugin", opt_key) == 0) {
61       strarray_add(&ret_flush->plugins, &ret_flush->plugins_num, opt_value);
62     } else if (strcasecmp("identifier", opt_key) == 0) {
63       identifier_t *id =
64           realloc(ret_flush->identifiers,
65                   (ret_flush->identifiers_num + 1) * sizeof(*id));
66       if (id == NULL) {
67         cmd_error(CMD_ERROR, err, "realloc failed.");
68         cmd_destroy_flush(ret_flush);
69         return CMD_ERROR;
70       }
71
72       ret_flush->identifiers = id;
73       id = ret_flush->identifiers + ret_flush->identifiers_num;
74       ret_flush->identifiers_num++;
75       if (parse_identifier(opt_value, &id->host, &id->plugin,
76                            &id->plugin_instance, &id->type, &id->type_instance,
77                            opts->identifier_default_host) != 0) {
78         cmd_error(CMD_PARSE_ERROR, err, "Invalid identifier `%s'.", opt_value);
79         cmd_destroy_flush(ret_flush);
80         return CMD_PARSE_ERROR;
81       }
82     } else if (strcasecmp("timeout", opt_key) == 0) {
83       char *endptr;
84
85       errno = 0;
86       endptr = NULL;
87       ret_flush->timeout = strtod(opt_value, &endptr);
88
89       if ((endptr == opt_value) || (errno != 0) ||
90           (!isfinite(ret_flush->timeout))) {
91         cmd_error(CMD_PARSE_ERROR, err,
92                   "Invalid value for option `timeout': %s", opt_value);
93         cmd_destroy_flush(ret_flush);
94         return CMD_PARSE_ERROR;
95       } else if (ret_flush->timeout < 0.0) {
96         ret_flush->timeout = 0.0;
97       }
98     } else {
99       cmd_error(CMD_PARSE_ERROR, err, "Cannot parse option `%s'.", opt_key);
100       cmd_destroy_flush(ret_flush);
101       return CMD_PARSE_ERROR;
102     }
103   }
104
105   return CMD_OK;
106 } /* cmd_status_t cmd_parse_flush */
107
108 cmd_status_t cmd_handle_flush(FILE *fh, char *buffer) {
109   cmd_error_handler_t err = {cmd_error_fh, fh};
110   cmd_t cmd;
111
112   int success = 0;
113   int error = 0;
114   int status;
115
116   if ((fh == NULL) || (buffer == NULL))
117     return -1;
118
119   DEBUG("utils_cmd_flush: cmd_handle_flush (fh = %p, buffer = %s);", (void *)fh,
120         buffer);
121
122   if ((status = cmd_parse(buffer, &cmd, NULL, &err)) != CMD_OK)
123     return status;
124   if (cmd.type != CMD_FLUSH) {
125     cmd_error(CMD_UNKNOWN_COMMAND, &err, "Unexpected command: `%s'.",
126               CMD_TO_STRING(cmd.type));
127     cmd_destroy(&cmd);
128     return CMD_UNKNOWN_COMMAND;
129   }
130
131   for (size_t i = 0; (i == 0) || (i < cmd.cmd.flush.plugins_num); i++) {
132     char *plugin = NULL;
133
134     if (cmd.cmd.flush.plugins_num != 0)
135       plugin = cmd.cmd.flush.plugins[i];
136
137     for (size_t j = 0; (j == 0) || (j < cmd.cmd.flush.identifiers_num); j++) {
138       char *identifier = NULL;
139       char buf[1024];
140
141       if (cmd.cmd.flush.identifiers_num != 0) {
142         identifier_t *id = cmd.cmd.flush.identifiers + j;
143         if (format_name(buf, sizeof(buf), id->host, id->plugin,
144                         id->plugin_instance, id->type,
145                         id->type_instance) != 0) {
146           error++;
147           continue;
148         }
149         identifier = buf;
150       }
151
152       if (plugin_flush(plugin, DOUBLE_TO_CDTIME_T(cmd.cmd.flush.timeout),
153                        identifier) == 0)
154         success++;
155       else
156         error++;
157     }
158   }
159
160   cmd_error(CMD_OK, &err, "Done: %i successful, %i errors", success, error);
161
162   cmd_destroy(&cmd);
163   return 0;
164 #undef PRINT_TO_SOCK
165 } /* cmd_status_t cmd_handle_flush */
166
167 void cmd_destroy_flush(cmd_flush_t *flush) {
168   if (flush == NULL)
169     return;
170
171   strarray_free(flush->plugins, flush->plugins_num);
172   flush->plugins = NULL;
173   flush->plugins_num = 0;
174
175   sfree(flush->identifiers);
176   flush->identifiers_num = 0;
177 } /* void cmd_destroy_flush */