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 *****************************************************************************/
8 #include "rrd_tool.h"
9 #include "rrd_rpncalc.h"
10 #include "rrd_client.h"
11 #include <stdarg.h>
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;
21 char *opt_daemon = NULL;
23 optind = 0;
24 opterr = 0; /* initialize getopt */
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 };
34 opt = getopt_long (argc, argv, "d:", long_options, &option_index);
36 if (opt == EOF)
37 break;
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;
51 default:
52 rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>",
53 argv[0]);
54 return (-1);
55 break;
56 }
57 } /* while (42) */
59 if ((argc - optind) != 1) {
60 rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>",
61 argv[0]);
62 return (-1);
63 }
65 if (opt_daemon == NULL)
66 {
67 char *temp;
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 }
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 }
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 }
98 rrdc_disconnect ();
99 } /* if (opt_daemon) */
101 status = rrd_lastupdate_r (argv[optind],
102 &last_update, &ds_count, &ds_names, &last_ds);
103 if (status != 0)
104 return (status);
106 for (i = 0; i < ds_count; i++)
107 printf(" %s", ds_names[i]);
108 printf ("\n\n");
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");
118 free(last_ds);
119 free(ds_names);
121 return (0);
122 } /* int rrd_lastupdate */
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;
134 rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
135 if (rrd_file == NULL) {
136 rrd_free(&rrd);
137 return (-1);
138 }
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 *));
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 *));
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);
166 if (((*ret_ds_names)[i] == NULL) || ((*ret_last_ds)[i] == NULL))
167 break;
168 }
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 }
195 rrd_free(&rrd);
196 rrd_close(rrd_file);
197 return (0);
198 } /* int rrd_lastupdate_r */