71457e41f6bba448510dfc43e07600dc9280ad92
[collectd.git] / src / collectd-flush.c
1 /**
2  * collectd-flush - src/collectd-flush.c
3  * Copyright (C) 2010 Håkon J Dugstad Johnsen
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Håkon J Dugstad Johnsen <hakon-dugstad.johnsen at telenor.com>
20  **/
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <getopt.h>
28
29 #include "libcollectdclient/client.h"
30
31 extern char *optarg;
32
33 static int flush (
34     const char *address,
35     const char *plugin,
36     const char *ident_str,
37     int timeout)
38 {
39   lcc_connection_t *connection;
40   lcc_identifier_t ident;
41
42   /* Pointer which is passed to lcc_flush.
43    * Either a null pointer or it points to ident */
44   lcc_identifier_t *identp;
45   int status;
46
47   connection = NULL;
48   status = lcc_connect(address, &connection);
49   if (status != 0) {
50     fprintf (stderr, "ERROR: Connecting to daemon at %s failed: %s.\n",
51         address, strerror (errno));
52     return 1;
53   }
54
55   identp = NULL;
56   if (ident_str != NULL && *ident_str != '\0') {
57     status = lcc_string_to_identifier (connection, &ident, ident_str);
58     if (status != 0) {
59       fprintf (stderr, "ERROR: Creating and identifier failed: %s.\n",
60           lcc_strerror(connection));
61       LCC_DESTROY (connection);
62
63       return 1;
64     }
65     identp = &ident;
66   }
67
68   status = lcc_flush (connection, plugin, identp, timeout);
69   if (status != 0) {
70     fprintf (stderr, "ERROR: Flushing failed: %s.\n",
71         lcc_strerror (connection));
72     LCC_DESTROY (connection);
73
74     return 1;
75   }
76
77   LCC_DESTROY (connection);
78
79   return 0;
80 }
81
82 void usage (const char *name) {
83   fprintf (stderr, "Usage: %s [options]\n"
84       "\n"
85       "Valid options are:\n"
86       "  -h, --help               Display this help message.\n"
87       "  -s, --socket=<socket>    Path to collectd's UNIX socket. Default: /var/run/collectd-unixsock\n"
88       "  -p, --plugin=<plugin>    Plugin to flush _to_ (not from). Example: rrdtool\n"
89       "  -i, --identifier=<identifier>\n"
90       "                           Only flush data specified by <identifier>, which has the format: \n"
91       "\n"
92       "                             [<hostname>/]<plugin>[-<plugin_instance>]/<type>[-<type_instance>]\n"
93       "\n"
94       "                           Hostname defaults to the local hostname if omitted.\n"
95       "                           No error is returned if the specified identifier does not exist.\n"
96       "                           Examples: uptime/uptime\n"
97       "                                     somehost/cpu-0/cpu-wait\n"
98       "  -t, --timeout=<timeout>  Only flush values older than this timeout.\n", name);
99 }
100
101 /*
102  * Count how many occurences there are of a char in a string.
103  */
104 int charoccurences (const char *str, char chr) {
105   int count = 0;
106   while (*str != '\0') {
107     if (*str == chr) {
108       count++;
109     }
110     str++;
111   }
112
113   return count;
114 }
115
116 int main (int argc, char **argv) {
117   char address[1024] = "unix:/var/run/collectd-unixsock";
118   char *plugin = NULL;
119   char ident_str[1024] = "";
120   int timeout = -1;
121   char hostname[1024];
122   char c;
123
124   static struct option long_options[] =
125     {
126       {"help", no_argument, 0, 'h'},
127       {"socket", required_argument, 0, 's'},
128       {"plugin", required_argument, 0, 'p'},
129       {"identifier", required_argument, 0, 'i'},
130       {"timeout", required_argument, 0, 't'}
131     };
132   int option_index = 0;
133
134
135   while ((c = getopt_long (argc, argv, "s:p:i:ht:", long_options, &option_index)) != -1) {
136     switch (c) {
137       case 's':
138         snprintf (address, sizeof (address), "unix:%s", optarg);
139         break;
140       case 'p':
141         plugin = optarg;
142         break;
143       case 'i':
144         if(charoccurences(optarg, '/') == 1) {
145           /* The user has omitted the hostname part of the identifier
146            * (there is only one '/' in the identifier)
147            * Let's add the local hostname */
148           if(gethostname(hostname, sizeof(hostname)) != 0) {
149             fprintf (stderr, "Could not get local hostname: %s", strerror(errno));
150             return 1;
151           }
152           /* Make sure hostname is zero-terminated */
153           hostname[sizeof(hostname)-1] = '\0';
154           snprintf (ident_str, sizeof (ident_str), "%s/%s", hostname, optarg);
155           /* Make sure ident_str is zero terminated */
156           ident_str[sizeof(ident_str)-1] = '\0';
157         } else {
158           strncpy(ident_str, optarg, sizeof (ident_str));
159           /* Make sure identifier is zero terminated */
160           ident_str[sizeof(ident_str)-1] = '\0';
161         }
162         break;
163       case 't':
164         timeout = atoi (optarg);
165         break;
166       case 'h':
167         usage (argv[0]);
168         return 0;
169       default:
170         usage (argv[0]);
171         return 1;
172     }
173   }
174
175   return flush(address, plugin, ident_str, timeout);
176 }