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