RRDcached patch. This implements an infrastructure, where rrd updates can be
[rrdtool.git] / src / rrd_lastupdate.c
1 /*****************************************************************************
2  * RRDtool 1.3.2  Copyright by Tobi Oetiker, 1997-2008
3  *                Copyright by Florian Forster, 2008
4  *****************************************************************************
5  * rrd_lastupdate  Get the last datum entered for each DS
6  *****************************************************************************/
7
8 #include "rrd_tool.h"
9 #include "rrd_rpncalc.h"
10 #include "rrd_client.h"
11 #include <stdarg.h>
12
13 int rrd_lastupdate (int argc, char **argv)
14 {
15     time_t    last_update;
16     char    **ds_names;
17     char    **last_ds;
18     unsigned long ds_count, i;
19     int status;
20
21     char *opt_daemon = NULL;
22
23     optind = 0;
24     opterr = 0;         /* initialize getopt */
25
26     while (42) {
27         int       opt;
28         int       option_index = 0;
29         static struct option long_options[] = {
30             {"daemon", required_argument, 0, 'd'},
31             {0, 0, 0, 0}
32         };
33
34         opt = getopt_long (argc, argv, "d:", long_options, &option_index);
35
36         if (opt == EOF)
37             break;
38
39         switch (opt) {
40         case 'd':
41             if (opt_daemon != NULL)
42                     free (opt_daemon);
43             opt_daemon = strdup (optarg);
44             if (opt_daemon == NULL)
45             {
46                 rrd_set_error ("strdup failed.");
47                 return (-1);
48             }
49             break;
50
51         default:
52             rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>",
53                     argv[0]);
54             return (-1);
55             break;
56         }
57     }                   /* while (42) */
58
59     if ((argc - optind) != 1) {
60         rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>",
61                 argv[0]);
62         return (-1);
63     }
64
65     if (opt_daemon == NULL)
66     {
67         char *temp;
68
69         temp = getenv (ENV_RRDCACHED_ADDRESS);
70         if (temp != NULL)
71         {
72             opt_daemon = strdup (temp);
73             if (opt_daemon == NULL)
74             {
75                 rrd_set_error("strdup failed.");
76                 return (-1);
77             }
78         }
79     }
80
81     if (opt_daemon != NULL)
82     {
83         status = rrdc_connect (opt_daemon);
84         if (status != 0)
85         {
86             rrd_set_error ("rrdc_connect failed with status %i.", status);
87             return (-1);
88         }
89
90         status = rrdc_flush (argv[optind]);
91         if (status != 0)
92         {
93             rrd_set_error ("rrdc_flush (%s) failed with status %i.",
94                     argv[optind], status);
95             return (-1);
96         }
97
98         rrdc_disconnect ();
99     } /* if (opt_daemon) */
100
101     status = rrd_lastupdate_r (argv[optind],
102             &last_update, &ds_count, &ds_names, &last_ds);
103     if (status != 0)
104         return (status);
105
106     for (i = 0; i < ds_count; i++)
107         printf(" %s", ds_names[i]);
108     printf ("\n\n");
109
110     printf ("%10lu:", last_update);
111     for (i = 0; i < ds_count; i++) {
112         printf(" %s", last_ds[i]);
113         free(last_ds[i]);
114         free(ds_names[i]);
115     }
116     printf("\n");
117
118     free(last_ds);
119     free(ds_names);
120
121     return (0);
122 } /* int rrd_lastupdate */
123
124 int rrd_lastupdate_r(const char *filename,
125         time_t *ret_last_update,
126         unsigned long *ret_ds_count,
127         char ***ret_ds_names,
128         char ***ret_last_ds)
129 {
130     unsigned long i = 0;
131     rrd_t     rrd;
132     rrd_file_t *rrd_file;
133
134     rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
135     if (rrd_file == NULL) {
136         rrd_free(&rrd);
137         return (-1);
138     }
139
140     *ret_last_update = rrd.live_head->last_up;
141     *ret_ds_count = rrd.stat_head->ds_cnt;
142     *ret_ds_names = (char **) malloc (rrd.stat_head->ds_cnt * sizeof(char *));
143     if (*ret_ds_names == NULL) {
144         rrd_set_error ("malloc fetch ret_ds_names array");
145         rrd_close (rrd_file);
146         rrd_free (&rrd);
147         return (-1);
148     }
149     memset (*ret_ds_names, 0, rrd.stat_head->ds_cnt * sizeof(char *));
150
151     *ret_last_ds = (char **) malloc (rrd.stat_head->ds_cnt * sizeof(char *));
152     if (*ret_last_ds == NULL) {
153         rrd_set_error ("malloc fetch ret_last_ds array");
154         free (*ret_ds_names);
155         *ret_ds_names = NULL;
156         rrd_close (rrd_file);
157         rrd_free (&rrd);
158         return (-1);
159     }
160     memset (*ret_last_ds, 0, rrd.stat_head->ds_cnt * sizeof(char *));
161
162     for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
163         (*ret_ds_names)[i] = sprintf_alloc("%s", rrd.ds_def[i].ds_nam);
164         (*ret_last_ds)[i] = sprintf_alloc("%s", rrd.pdp_prep[i].last_ds);
165
166         if (((*ret_ds_names)[i] == NULL) || ((*ret_last_ds)[i] == NULL))
167             break;
168     }
169
170     /* Check if all names and values could be copied and free everything if
171      * not. */
172     if (i < rrd.stat_head->ds_cnt) {
173         rrd_set_error ("sprintf_alloc failed");
174         for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
175             if ((*ret_ds_names)[i] != NULL)
176             {
177                 free ((*ret_ds_names)[i]);
178                 (*ret_ds_names)[i] = NULL;
179             }
180             if ((*ret_last_ds)[i] != NULL)
181             {
182                 free ((*ret_last_ds)[i]);
183                 (*ret_last_ds)[i] = NULL;
184             }
185         }
186         free (*ret_ds_names);
187         *ret_ds_names = NULL;
188         free (*ret_last_ds);
189         *ret_last_ds = NULL;
190         rrd_close (rrd_file);
191         rrd_free (&rrd);
192         return (-1);
193     }
194
195     rrd_free(&rrd);
196     rrd_close(rrd_file);
197     return (0);
198 } /* int rrd_lastupdate_r */