6 static const char *memcached_stat_keys
[] = {
19 "connection_structures",
34 memcached_stat_fn func
;
40 static memcached_return_t
set_data(memcached_stat_st
*memc_stat
, char *key
, char *value
)
45 WATCHPOINT_STRING(key
);
46 return MEMCACHED_UNKNOWN_STAT_KEY
;
48 else if (!strcmp("pid", key
))
50 memc_stat
->pid
= (uint32_t) strtol(value
, (char **)NULL
, 10);
52 else if (!strcmp("uptime", key
))
54 memc_stat
->uptime
= (uint32_t) strtol(value
, (char **)NULL
, 10);
56 else if (!strcmp("time", key
))
58 memc_stat
->time
= (uint32_t) strtol(value
, (char **)NULL
, 10);
60 else if (!strcmp("version", key
))
62 memcpy(memc_stat
->version
, value
, strlen(value
));
63 memc_stat
->version
[strlen(value
)]= 0;
65 else if (!strcmp("pointer_size", key
))
67 memc_stat
->pointer_size
= (uint32_t) strtol(value
, (char **)NULL
, 10);
69 else if (!strcmp("rusage_user", key
))
72 for (walk_ptr
= value
; (!ispunct(*walk_ptr
)); walk_ptr
++);
75 memc_stat
->rusage_user_seconds
= (uint32_t) strtol(value
, (char **)NULL
, 10);
76 memc_stat
->rusage_user_microseconds
= (uint32_t) strtol(walk_ptr
, (char **)NULL
, 10);
78 else if (!strcmp("rusage_system", key
))
81 for (walk_ptr
= value
; (!ispunct(*walk_ptr
)); walk_ptr
++);
84 memc_stat
->rusage_system_seconds
= (uint32_t) strtol(value
, (char **)NULL
, 10);
85 memc_stat
->rusage_system_microseconds
= (uint32_t) strtol(walk_ptr
, (char **)NULL
, 10);
87 else if (!strcmp("curr_items", key
))
89 memc_stat
->curr_items
= (uint32_t) strtol(value
, (char **)NULL
, 10);
91 else if (!strcmp("total_items", key
))
93 memc_stat
->total_items
= (uint32_t) strtol(value
, (char **)NULL
, 10);
95 else if (!strcmp("bytes_read", key
))
97 memc_stat
->bytes_read
= (uint32_t) strtoll(value
, (char **)NULL
, 10);
99 else if (!strcmp("bytes_written", key
))
101 memc_stat
->bytes_written
= (uint32_t) strtoll(value
, (char **)NULL
, 10);
103 else if (!strcmp("bytes", key
))
105 memc_stat
->bytes
= (uint32_t) strtoll(value
, (char **)NULL
, 10);
107 else if (!strcmp("curr_connections", key
))
109 memc_stat
->curr_connections
= (uint32_t) strtoll(value
, (char **)NULL
, 10);
111 else if (!strcmp("total_connections", key
))
113 memc_stat
->total_connections
= (uint32_t) strtoll(value
, (char **)NULL
, 10);
115 else if (!strcmp("connection_structures", key
))
117 memc_stat
->connection_structures
= (uint32_t) strtol(value
, (char **)NULL
, 10);
119 else if (!strcmp("cmd_get", key
))
121 memc_stat
->cmd_get
= (uint64_t) strtoll(value
, (char **)NULL
, 10);
123 else if (!strcmp("cmd_set", key
))
125 memc_stat
->cmd_set
= (uint64_t) strtoll(value
, (char **)NULL
, 10);
127 else if (!strcmp("get_hits", key
))
129 memc_stat
->get_hits
= (uint64_t) strtoll(value
, (char **)NULL
, 10);
131 else if (!strcmp("get_misses", key
))
133 memc_stat
->get_misses
= (uint64_t)strtoll(value
, (char **)NULL
, 10);
135 else if (!strcmp("evictions", key
))
137 memc_stat
->evictions
= (uint64_t)strtoll(value
, (char **)NULL
, 10);
139 else if (!strcmp("limit_maxbytes", key
))
141 memc_stat
->limit_maxbytes
= (uint64_t) strtoll(value
, (char **)NULL
, 10);
143 else if (!strcmp("threads", key
))
145 memc_stat
->threads
= (uint32_t) strtol(value
, (char **)NULL
, 10);
147 else if (!(strcmp("delete_misses", key
) == 0 ||/* New stats in the 1.3 beta */
148 strcmp("delete_hits", key
) == 0 ||/* Just swallow them for now.. */
149 strcmp("incr_misses", key
) == 0 ||
150 strcmp("incr_hits", key
) == 0 ||
151 strcmp("decr_misses", key
) == 0 ||
152 strcmp("decr_hits", key
) == 0 ||
153 strcmp("cas_misses", key
) == 0 ||
154 strcmp("cas_hits", key
) == 0 ||
155 strcmp("cas_badval", key
) == 0 ||
156 strcmp("cmd_flush", key
) == 0 ||
157 strcmp("accepting_conns", key
) == 0 ||
158 strcmp("listen_disabled_num", key
) == 0 ||
159 strcmp("conn_yields", key
) == 0 ||
160 strcmp("auth_cmds", key
) == 0 ||
161 strcmp("auth_errors", key
) == 0 ||
162 strcmp("reclaimed", key
) == 0))
164 WATCHPOINT_STRING(key
);
165 return MEMCACHED_UNKNOWN_STAT_KEY
;
168 return MEMCACHED_SUCCESS
;
171 char *memcached_stat_get_value(const memcached_st
*ptr
, memcached_stat_st
*memc_stat
,
172 const char *key
, memcached_return_t
*error
)
174 char buffer
[SMALL_STRING_LEN
];
178 *error
= MEMCACHED_SUCCESS
;
180 if (!memcmp("pid", key
, strlen("pid")))
181 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->pid
);
182 else if (!memcmp("uptime", key
, strlen("uptime")))
183 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->uptime
);
184 else if (!memcmp("time", key
, strlen("time")))
185 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->time
);
186 else if (!memcmp("version", key
, strlen("version")))
187 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%s", memc_stat
->version
);
188 else if (!memcmp("pointer_size", key
, strlen("pointer_size")))
189 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->pointer_size
);
190 else if (!memcmp("rusage_user", key
, strlen("rusage_user")))
191 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u.%u", memc_stat
->rusage_user_seconds
, memc_stat
->rusage_user_microseconds
);
192 else if (!memcmp("rusage_system", key
, strlen("rusage_system")))
193 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u.%u", memc_stat
->rusage_system_seconds
, memc_stat
->rusage_system_microseconds
);
194 else if (!memcmp("curr_items", key
, strlen("curr_items")))
195 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->curr_items
);
196 else if (!memcmp("total_items", key
, strlen("total_items")))
197 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->total_items
);
198 else if (!memcmp("curr_connections", key
, strlen("curr_connections")))
199 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->curr_connections
);
200 else if (!memcmp("total_connections", key
, strlen("total_connections")))
201 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->total_connections
);
202 else if (!memcmp("connection_structures", key
, strlen("connection_structures")))
203 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->connection_structures
);
204 else if (!memcmp("cmd_get", key
, strlen("cmd_get")))
205 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->cmd_get
);
206 else if (!memcmp("cmd_set", key
, strlen("cmd_set")))
207 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->cmd_set
);
208 else if (!memcmp("get_hits", key
, strlen("get_hits")))
209 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->get_hits
);
210 else if (!memcmp("get_misses", key
, strlen("get_misses")))
211 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->get_misses
);
212 else if (!memcmp("evictions", key
, strlen("evictions")))
213 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->evictions
);
214 else if (!memcmp("bytes_read", key
, strlen("bytes_read")))
215 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes_read
);
216 else if (!memcmp("bytes_written", key
, strlen("bytes_written")))
217 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes_written
);
218 else if (!memcmp("bytes", key
, strlen("bytes")))
219 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes
);
220 else if (!memcmp("limit_maxbytes", key
, strlen("limit_maxbytes")))
221 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->limit_maxbytes
);
222 else if (!memcmp("threads", key
, strlen("threads")))
223 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%u", memc_stat
->threads
);
226 *error
= MEMCACHED_NOTFOUND
;
230 if (length
>= SMALL_STRING_LEN
|| length
< 0)
232 *error
= MEMCACHED_FAILURE
;
236 ret
= libmemcached_malloc(ptr
, (size_t) (length
+ 1));
237 memcpy(ret
, buffer
, (size_t) length
);
243 static memcached_return_t
binary_stats_fetch(memcached_stat_st
*memc_stat
,
245 memcached_server_write_instance_st instance
,
246 struct local_context
*check
)
248 memcached_return_t rc
;
250 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
251 protocol_binary_request_stats request
= {.bytes
= {0}};
252 request
.message
.header
.request
.magic
= PROTOCOL_BINARY_REQ
;
253 request
.message
.header
.request
.opcode
= PROTOCOL_BINARY_CMD_STAT
;
254 request
.message
.header
.request
.datatype
= PROTOCOL_BINARY_RAW_BYTES
;
258 size_t len
= strlen(args
);
260 rc
= memcached_validate_key_length(len
, true);
261 unlikely (rc
!= MEMCACHED_SUCCESS
)
264 request
.message
.header
.request
.keylen
= htons((uint16_t)len
);
265 request
.message
.header
.request
.bodylen
= htonl((uint32_t) len
);
267 struct libmemcached_io_vector_st vector
[]=
269 { .length
= sizeof(request
.bytes
), .buffer
= request
.bytes
},
270 { .length
= len
, .buffer
= args
}
273 if (memcached_vdo(instance
, vector
, 2, true) != MEMCACHED_SUCCESS
)
275 memcached_io_reset(instance
);
276 return MEMCACHED_WRITE_FAILURE
;
281 if (memcached_do(instance
, request
.bytes
,
282 sizeof(request
.bytes
), true) != MEMCACHED_SUCCESS
)
284 memcached_io_reset(instance
);
285 return MEMCACHED_WRITE_FAILURE
;
289 memcached_server_response_decrement(instance
);
292 rc
= memcached_response(instance
, buffer
, sizeof(buffer
), NULL
);
294 if (rc
== MEMCACHED_END
)
297 unlikely (rc
!= MEMCACHED_SUCCESS
)
299 memcached_io_reset(instance
);
305 unlikely((set_data(memc_stat
, buffer
, buffer
+ strlen(buffer
) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY
)
307 WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY
);
308 WATCHPOINT_ASSERT(0);
312 if (check
&& check
->func
)
314 size_t key_length
= strlen(buffer
);
316 check
->func(instance
,
318 buffer
+key_length
+1, strlen(buffer
+key_length
+1),
323 /* shit... memcached_response will decrement the counter, so I need to
324 ** reset it.. todo: look at this and try to find a better solution.
326 instance
->cursor_active
= 0;
328 return MEMCACHED_SUCCESS
;
331 static memcached_return_t
ascii_stats_fetch(memcached_stat_st
*memc_stat
,
333 memcached_server_write_instance_st instance
,
334 struct local_context
*check
)
336 memcached_return_t rc
;
337 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
341 send_length
= (size_t) snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
342 "stats %s\r\n", args
);
344 send_length
= (size_t) snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
347 if (send_length
>= MEMCACHED_DEFAULT_COMMAND_SIZE
|| send_length
< 0)
348 return MEMCACHED_WRITE_FAILURE
;
350 rc
= memcached_do(instance
, buffer
, (size_t)send_length
, true);
351 if (rc
!= MEMCACHED_SUCCESS
)
356 rc
= memcached_response(instance
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, NULL
);
358 if (rc
== MEMCACHED_STAT
)
360 char *string_ptr
, *end_ptr
;
364 string_ptr
+= 5; /* Move past STAT */
365 for (end_ptr
= string_ptr
; isgraph(*end_ptr
); end_ptr
++);
367 key
[(size_t)(end_ptr
-string_ptr
)]= 0;
369 string_ptr
= end_ptr
+ 1;
370 for (end_ptr
= string_ptr
; !(isspace(*end_ptr
)); end_ptr
++);
372 value
[(size_t)(end_ptr
-string_ptr
)]= 0;
373 string_ptr
= end_ptr
+ 2;
376 unlikely((set_data(memc_stat
, key
, value
)) == MEMCACHED_UNKNOWN_STAT_KEY
)
378 WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY
);
379 WATCHPOINT_ASSERT(0);
383 if (check
&& check
->func
)
385 check
->func(instance
,
387 value
, strlen(value
),
396 if (rc
== MEMCACHED_END
)
397 return MEMCACHED_SUCCESS
;
402 memcached_stat_st
*memcached_stat(memcached_st
*ptr
, char *args
, memcached_return_t
*error
)
404 memcached_return_t rc
;
405 memcached_stat_st
*stats
;
407 unlikely (ptr
->flags
.use_udp
)
409 *error
= MEMCACHED_NOT_SUPPORTED
;
413 stats
= libmemcached_calloc(ptr
, memcached_server_count(ptr
), sizeof(memcached_stat_st
));
417 *error
= MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
421 rc
= MEMCACHED_SUCCESS
;
422 for (uint32_t x
= 0; x
< memcached_server_count(ptr
); x
++)
424 memcached_return_t temp_return
;
425 memcached_server_write_instance_st instance
;
426 memcached_stat_st
*stat_instance
;
428 stat_instance
= stats
+ x
;
430 stat_instance
->root
= ptr
;
432 instance
= memcached_server_instance_fetch(ptr
, x
);
434 if (ptr
->flags
.binary_protocol
)
436 temp_return
= binary_stats_fetch(stat_instance
, args
, instance
, NULL
);
440 temp_return
= ascii_stats_fetch(stat_instance
, args
, instance
, NULL
);
443 if (temp_return
!= MEMCACHED_SUCCESS
)
444 rc
= MEMCACHED_SOME_ERRORS
;
451 memcached_return_t
memcached_stat_servername(memcached_stat_st
*memc_stat
, char *args
,
452 const char *hostname
, in_port_t port
)
454 memcached_return_t rc
;
456 memcached_st
*memc_ptr
;
457 memcached_server_write_instance_st instance
;
459 memset(memc_stat
, 0, sizeof(memcached_stat_st
));
461 memc_ptr
= memcached_create(&memc
);
462 WATCHPOINT_ASSERT(memc_ptr
);
464 memcached_server_add(&memc
, hostname
, port
);
466 instance
= memcached_server_instance_fetch(memc_ptr
, 0);
468 if (memc
.flags
.binary_protocol
)
470 rc
= binary_stats_fetch(memc_stat
, args
, instance
, NULL
);
474 rc
= ascii_stats_fetch(memc_stat
, args
, instance
, NULL
);
477 memcached_free(&memc
);
483 We make a copy of the keys since at some point in the not so distant future
484 we will add support for "found" keys.
486 char ** memcached_stat_get_keys(const memcached_st
*ptr
,
487 memcached_stat_st
*memc_stat
,
488 memcached_return_t
*error
)
491 size_t length
= sizeof(memcached_stat_keys
);
495 list
= libmemcached_malloc(ptr
, length
);
499 *error
= MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
503 memcpy(list
, memcached_stat_keys
, sizeof(memcached_stat_keys
));
505 *error
= MEMCACHED_SUCCESS
;
510 void memcached_stat_free(const memcached_st
*ptr
, memcached_stat_st
*memc_stat
)
512 if (memc_stat
== NULL
)
514 WATCHPOINT_ASSERT(0); /* Be polite, but when debugging catch this as an error */
520 libmemcached_free(memc_stat
->root
, memc_stat
);
524 libmemcached_free(ptr
, memc_stat
);
532 static memcached_return_t
call_stat_fn(memcached_st
*ptr
,
533 memcached_server_write_instance_st instance
,
536 memcached_return_t rc
;
537 struct local_context
*check
= (struct local_context
*)context
;
539 if (ptr
->flags
.binary_protocol
)
541 rc
= binary_stats_fetch(NULL
, check
->args
, instance
, check
);
545 rc
= ascii_stats_fetch(NULL
, check
->args
, instance
, check
);
551 memcached_return_t
memcached_stat_execute(memcached_st
*memc
, const char *args
, memcached_stat_fn func
, void *context
)
553 memcached_version(memc
);
555 struct local_context check
= { .func
= func
, .context
= context
, .args
= args
};
557 return memcached_server_execute(memc
, call_stat_fn
, (void *)&check
);