add error checking, for command overflow, and short writes
[awesomized/libmemcached] / lib / memcached_stats.c
1 /*
2 */
3
4 #include <memcached.h>
5
6 static void set_data(memcached_stat_st *stat, char *key, char *value)
7 {
8 if (!memcmp("pid", key, strlen("pid")))
9 {
10 stat->pid= strtol(value, (char **)NULL, 10);
11 }
12 else if (!memcmp("uptime", key, strlen("uptime")))
13 {
14 stat->uptime= strtol(value, (char **)NULL, 10);
15 }
16 else if (!memcmp("time", key, strlen("time")))
17 {
18 stat->time= strtoll(value, (char **)NULL, 10);
19 }
20 else if (!memcmp("version", key, strlen("version")))
21 {
22 memcpy(stat->version, value, 8);
23 }
24 else if (!memcmp("pointer_size", key, strlen("pointer_size")))
25 {
26 stat->pointer_size= strtoll(value, (char **)NULL, 10);
27 }
28 else if (!memcmp("rusage_user", key, strlen("rusage_user")))
29 {
30 stat->rusage_user= strtoll(value, (char **)NULL, 10);
31 }
32 else if (!memcmp("rusage_system", key, strlen("rusage_system")))
33 {
34 stat->rusage_system= strtoll(value, (char **)NULL, 10);
35 }
36 else if (!memcmp("rusage_user_seconds", key, strlen("rusage_user_seconds")))
37 {
38 stat->rusage_user_seconds= strtoll(value, (char **)NULL, 10);
39 }
40 else if (!memcmp("rusage_user_microseconds", key, strlen("rusage_user_microseconds")))
41 {
42 stat->rusage_user_microseconds= strtoll(value, (char **)NULL, 10);
43 }
44 else if (!memcmp("rusage_system_seconds", key, strlen("rusage_system_seconds")))
45 {
46 stat->rusage_system_seconds= strtoll(value, (char **)NULL, 10);
47 }
48 else if (!memcmp("rusage_system_microseconds", key, strlen("rusage_system_microseconds")))
49 {
50 stat->rusage_system_microseconds= strtoll(value, (char **)NULL, 10);
51 }
52 else if (!memcmp("curr_items", key, strlen("curr_items")))
53 {
54 stat->curr_items= strtoll(value, (char **)NULL, 10);
55 }
56 else if (!memcmp("total_items", key, strlen("total_items")))
57 {
58 stat->total_items= strtoll(value, (char **)NULL, 10);
59 }
60 else if (!memcmp("bytes", key, strlen("bytes")))
61 {
62 stat->bytes= strtoll(value, (char **)NULL, 10);
63 }
64 else if (!memcmp("curr_connections", key, strlen("curr_connections")))
65 {
66 stat->curr_connections= strtoll(value, (char **)NULL, 10);
67 }
68 else if (!memcmp("total_connections", key, strlen("total_connections")))
69 {
70 stat->total_connections= strtoll(value, (char **)NULL, 10);
71 }
72 else if (!memcmp("connection_structures", key, strlen("connection_structures")))
73 {
74 stat->connection_structures= strtoll(value, (char **)NULL, 10);
75 }
76 else if (!memcmp("cmd_get", key, strlen("cmd_get")))
77 {
78 stat->cmd_get= strtoll(value, (char **)NULL, 10);
79 }
80 else if (!memcmp("cmd_set", key, strlen("cmd_set")))
81 {
82 stat->cmd_set= strtoll(value, (char **)NULL, 10);
83 }
84 else if (!memcmp("get_hits", key, strlen("get_hits")))
85 {
86 stat->get_hits= strtoll(value, (char **)NULL, 10);
87 }
88 else if (!memcmp("get_misses", key, strlen("get_misses")))
89 {
90 stat->get_misses= strtoll(value, (char **)NULL, 10);
91 }
92 else if (!memcmp("evictions", key, strlen("evictions")))
93 {
94 stat->evictions= strtoll(value, (char **)NULL, 10);
95 }
96 else if (!memcmp("bytes_read", key, strlen("bytes_read")))
97 {
98 stat->bytes_read= strtoll(value, (char **)NULL, 10);
99 }
100 else if (!memcmp("bytes_written", key, strlen("bytes_written")))
101 {
102 stat->bytes_written= strtoll(value, (char **)NULL, 10);
103 }
104 else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes")))
105 {
106 stat->limit_maxbytes= strtoll(value, (char **)NULL, 10);
107 }
108 else if (!memcmp("threads", key, strlen("threads")))
109 {
110 stat->threads= strtol(key, (char **)NULL, 10);
111 }
112 else
113 {
114 fprintf(stderr, "Unknown key %s\n", key);
115 }
116 }
117
118 static memcached_return memcached_stats_fetch(memcached_st *ptr,
119 memcached_stat_st *stat,
120 char *args,
121 unsigned int server_key)
122 {
123 memcached_return rc;
124 char buffer[HUGE_STRING_LEN];
125 size_t send_length, sent_length;
126
127 rc= memcached_connect(ptr);
128
129 if (rc != MEMCACHED_SUCCESS)
130 return rc;
131
132 if (args)
133 send_length= snprintf(buffer, HUGE_STRING_LEN,
134 "stats %s\r\n", args);
135 else
136 send_length= snprintf(buffer, HUGE_STRING_LEN,
137 "stats\r\n");
138
139 if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
140 return MEMCACHED_WRITE_FAILURE;
141
142 if ((sent_length= write(ptr->hosts[server_key].fd, buffer, send_length) == -1))
143 {
144 fprintf(stderr, "failed on stats\n");
145
146 return MEMCACHED_WRITE_FAILURE;
147 }
148 if (sent_length != send_length)
149 return MEMCACHED_WRITE_FAILURE;
150
151
152 rc= memcached_response(ptr, buffer, HUGE_STRING_LEN, 0);
153
154 if (rc == MEMCACHED_SUCCESS)
155 {
156 char *string_ptr, *end_ptr;
157 char *key, *value;
158
159 string_ptr= buffer;
160 while (1)
161 {
162 if (memcmp(string_ptr, "STAT ", 5))
163 break;
164 string_ptr+= 5;
165 for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++);
166 key= string_ptr;
167 key[(size_t)(end_ptr-string_ptr)]= 0;
168
169 string_ptr= end_ptr + 1;
170 for (end_ptr= string_ptr; *end_ptr != '\r'; end_ptr++);
171 value= string_ptr;
172 value[(size_t)(end_ptr-string_ptr)]= 0;
173 string_ptr= end_ptr + 2;
174 set_data(stat, key, value);
175 }
176 }
177
178 return rc;
179 }
180
181 memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return *error)
182 {
183 unsigned int x;
184 memcached_return rc;
185 memcached_stat_st *stats;
186 rc= memcached_connect(ptr);
187
188 if (rc != MEMCACHED_SUCCESS)
189 {
190 *error= rc;
191 return NULL;
192 }
193
194 stats= (memcached_stat_st *)malloc(sizeof(memcached_st)*(ptr->number_of_hosts+1));
195 if (stats)
196 {
197 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
198 return NULL;
199 }
200 memset(stats, 0, sizeof(memcached_st)*(ptr->number_of_hosts+1));
201
202 for (x= 0; x < ptr->number_of_hosts; x++)
203 {
204 rc= memcached_stats_fetch(ptr, stats+x, args, x);
205 if (rc != MEMCACHED_SUCCESS)
206 rc= MEMCACHED_SOME_ERRORS;
207 }
208
209 *error= x == 0 ? MEMCACHED_SUCCESS : rc;
210 return stats;
211 }
212
213 memcached_return memcached_stat_hostname(memcached_stat_st *stat, char *args,
214 char *hostname, unsigned int port)
215 {
216 memcached_return rc;
217 memcached_st memc;
218
219 memcached_init(&memc);
220
221 memcached_server_add(&memc, hostname, port);
222
223 rc= memcached_connect(&memc);
224
225 if (rc != MEMCACHED_SUCCESS)
226 return rc;
227
228 rc= memcached_stats_fetch(&memc, stat, args, 0);
229
230 memcached_deinit(&memc);
231
232 return rc;
233 }