6 static const char *memcached_stat_keys
[] = {
19 "connection_structures",
34 memcached_stat_fn func
;
38 local_context(memcached_stat_fn func_arg
,
40 const char *args_arg
) :
48 static memcached_return_t
set_data(memcached_stat_st
*memc_stat
, char *key
, char *value
)
53 WATCHPOINT_STRING(key
);
54 return MEMCACHED_UNKNOWN_STAT_KEY
;
56 else if (not strcmp("pid", key
))
58 int64_t temp
= strtoll(value
, (char **)NULL
, 10);
60 if (temp
<= INT32_MAX
and ( sizeof(pid_t
) == sizeof(int32_t) ))
70 // If we got a value less then -1 then something went wrong in the
74 else if (not strcmp("uptime", key
))
76 memc_stat
->uptime
= strtoul(value
, (char **)NULL
, 10);
78 else if (not strcmp("time", key
))
80 memc_stat
->time
= strtoul(value
, (char **)NULL
, 10);
82 else if (not strcmp("version", key
))
84 memcpy(memc_stat
->version
, value
, strlen(value
));
85 memc_stat
->version
[strlen(value
)]= 0;
87 else if (not strcmp("pointer_size", key
))
89 memc_stat
->pointer_size
= strtoul(value
, (char **)NULL
, 10);
91 else if (not strcmp("rusage_user", key
))
94 for (walk_ptr
= value
; (!ispunct(*walk_ptr
)); walk_ptr
++) {};
97 memc_stat
->rusage_user_seconds
= strtoul(value
, (char **)NULL
, 10);
98 memc_stat
->rusage_user_microseconds
= strtoul(walk_ptr
, (char **)NULL
, 10);
100 else if (not strcmp("rusage_system", key
))
103 for (walk_ptr
= value
; (!ispunct(*walk_ptr
)); walk_ptr
++) {};
106 memc_stat
->rusage_system_seconds
= strtoul(value
, (char **)NULL
, 10);
107 memc_stat
->rusage_system_microseconds
= strtoul(walk_ptr
, (char **)NULL
, 10);
109 else if (not strcmp("curr_items", key
))
111 memc_stat
->curr_items
= strtoul(value
, (char **)NULL
, 10);
113 else if (not strcmp("total_items", key
))
115 memc_stat
->total_items
= strtoul(value
, (char **)NULL
, 10);
117 else if (not strcmp("bytes_read", key
))
119 memc_stat
->bytes_read
= strtoull(value
, (char **)NULL
, 10);
121 else if (not strcmp("bytes_written", key
))
123 memc_stat
->bytes_written
= strtoull(value
, (char **)NULL
, 10);
125 else if (not strcmp("bytes", key
))
127 memc_stat
->bytes
= strtoull(value
, (char **)NULL
, 10);
129 else if (not strcmp("curr_connections", key
))
131 memc_stat
->curr_connections
= strtoull(value
, (char **)NULL
, 10);
133 else if (not strcmp("total_connections", key
))
135 memc_stat
->total_connections
= strtoull(value
, (char **)NULL
, 10);
137 else if (not strcmp("connection_structures", key
))
139 memc_stat
->connection_structures
= strtoul(value
, (char **)NULL
, 10);
141 else if (not strcmp("cmd_get", key
))
143 memc_stat
->cmd_get
= strtoull(value
, (char **)NULL
, 10);
145 else if (not strcmp("cmd_set", key
))
147 memc_stat
->cmd_set
= strtoull(value
, (char **)NULL
, 10);
149 else if (not strcmp("get_hits", key
))
151 memc_stat
->get_hits
= strtoull(value
, (char **)NULL
, 10);
153 else if (not strcmp("get_misses", key
))
155 memc_stat
->get_misses
= strtoull(value
, (char **)NULL
, 10);
157 else if (not strcmp("evictions", key
))
159 memc_stat
->evictions
= strtoull(value
, (char **)NULL
, 10);
161 else if (not strcmp("limit_maxbytes", key
))
163 memc_stat
->limit_maxbytes
= strtoull(value
, (char **)NULL
, 10);
165 else if (not strcmp("threads", key
))
167 memc_stat
->threads
= strtoul(value
, (char **)NULL
, 10);
169 else if (not (strcmp("delete_misses", key
) == 0 or /* New stats in the 1.3 beta */
170 strcmp("delete_hits", key
) == 0 or /* Just swallow them for now.. */
171 strcmp("incr_misses", key
) == 0 or
172 strcmp("incr_hits", key
) == 0 or
173 strcmp("decr_misses", key
) == 0 or
174 strcmp("decr_hits", key
) == 0 or
175 strcmp("cas_misses", key
) == 0 or
176 strcmp("cas_hits", key
) == 0 or
177 strcmp("cas_badval", key
) == 0 or
178 strcmp("cmd_flush", key
) == 0 or
179 strcmp("accepting_conns", key
) == 0 or
180 strcmp("listen_disabled_num", key
) == 0 or
181 strcmp("conn_yields", key
) == 0 or
182 strcmp("auth_cmds", key
) == 0 or
183 strcmp("auth_errors", key
) == 0 or
184 strcmp("reclaimed", key
) == 0))
186 WATCHPOINT_STRING(key
);
187 /* return MEMCACHED_UNKNOWN_STAT_KEY; */
188 return MEMCACHED_SUCCESS
;
191 return MEMCACHED_SUCCESS
;
194 char *memcached_stat_get_value(const memcached_st
*ptr
, memcached_stat_st
*memc_stat
,
195 const char *key
, memcached_return_t
*error
)
197 char buffer
[SMALL_STRING_LEN
];
201 *error
= MEMCACHED_SUCCESS
;
203 if (not memcmp("pid", key
, sizeof("pid") -1))
205 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lld", (signed long long)memc_stat
->pid
);
207 else if (not memcmp("uptime", key
, sizeof("uptime") -1))
209 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->uptime
);
211 else if (not memcmp("time", key
, sizeof("time") -1))
213 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->time
);
215 else if (not memcmp("version", key
, sizeof("version") -1))
217 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%s", memc_stat
->version
);
219 else if (not memcmp("pointer_size", key
, sizeof("pointer_size") -1))
221 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->pointer_size
);
223 else if (not memcmp("rusage_user", key
, sizeof("rusage_user") -1))
225 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu.%lu", memc_stat
->rusage_user_seconds
, memc_stat
->rusage_user_microseconds
);
227 else if (not memcmp("rusage_system", key
, sizeof("rusage_system") -1))
229 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu.%lu", memc_stat
->rusage_system_seconds
, memc_stat
->rusage_system_microseconds
);
231 else if (not memcmp("curr_items", key
, sizeof("curr_items") -1))
233 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->curr_items
);
235 else if (not memcmp("total_items", key
, sizeof("total_items") -1))
237 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->total_items
);
239 else if (not memcmp("curr_connections", key
, sizeof("curr_connections") -1))
241 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->curr_connections
);
243 else if (not memcmp("total_connections", key
, sizeof("total_connections") -1))
245 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->total_connections
);
247 else if (not memcmp("connection_structures", key
, sizeof("connection_structures") -1))
249 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->connection_structures
);
251 else if (not memcmp("cmd_get", key
, sizeof("cmd_get") -1))
253 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->cmd_get
);
255 else if (not memcmp("cmd_set", key
, sizeof("cmd_set") -1))
257 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->cmd_set
);
259 else if (not memcmp("get_hits", key
, sizeof("get_hits") -1))
261 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->get_hits
);
263 else if (not memcmp("get_misses", key
, sizeof("get_misses") -1))
265 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->get_misses
);
267 else if (not memcmp("evictions", key
, sizeof("evictions") -1))
269 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->evictions
);
271 else if (not memcmp("bytes_read", key
, sizeof("bytes_read") -1))
273 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes_read
);
275 else if (not memcmp("bytes_written", key
, sizeof("bytes_written") -1))
277 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes_written
);
279 else if (not memcmp("bytes", key
, sizeof("bytes") -1))
281 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes
);
283 else if (not memcmp("limit_maxbytes", key
, sizeof("limit_maxbytes") -1))
285 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->limit_maxbytes
);
287 else if (not memcmp("threads", key
, sizeof("threads") -1))
289 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->threads
);
293 *error
= MEMCACHED_NOTFOUND
;
297 if (length
>= SMALL_STRING_LEN
|| length
< 0)
299 *error
= MEMCACHED_FAILURE
;
303 ret
= static_cast<char *>(libmemcached_malloc(ptr
, (size_t) (length
+ 1)));
304 memcpy(ret
, buffer
, (size_t) length
);
310 static memcached_return_t
binary_stats_fetch(memcached_stat_st
*memc_stat
,
312 memcached_server_write_instance_st instance
,
313 struct local_context
*check
)
315 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
316 protocol_binary_request_stats request
= {}; // = {.bytes= {0}};
317 request
.message
.header
.request
.magic
= PROTOCOL_BINARY_REQ
;
318 request
.message
.header
.request
.opcode
= PROTOCOL_BINARY_CMD_STAT
;
319 request
.message
.header
.request
.datatype
= PROTOCOL_BINARY_RAW_BYTES
;
323 size_t len
= strlen(args
);
325 memcached_return_t rc
= memcached_validate_key_length(len
, true);
326 if (rc
!= MEMCACHED_SUCCESS
)
331 request
.message
.header
.request
.keylen
= htons((uint16_t)len
);
332 request
.message
.header
.request
.bodylen
= htonl((uint32_t) len
);
334 struct libmemcached_io_vector_st vector
[]=
336 { request
.bytes
, sizeof(request
.bytes
) },
340 if (memcached_vdo(instance
, vector
, 2, true) != MEMCACHED_SUCCESS
)
342 memcached_io_reset(instance
);
343 return MEMCACHED_WRITE_FAILURE
;
348 if (memcached_do(instance
, request
.bytes
,
349 sizeof(request
.bytes
), true) != MEMCACHED_SUCCESS
)
351 memcached_io_reset(instance
);
352 return MEMCACHED_WRITE_FAILURE
;
356 memcached_server_response_decrement(instance
);
359 memcached_return_t rc
= memcached_response(instance
, buffer
, sizeof(buffer
), NULL
);
361 if (rc
== MEMCACHED_END
)
364 unlikely (rc
!= MEMCACHED_SUCCESS
)
366 memcached_io_reset(instance
);
372 unlikely((set_data(memc_stat
, buffer
, buffer
+ strlen(buffer
) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY
)
374 WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY
);
375 WATCHPOINT_ASSERT(0);
379 if (check
&& check
->func
)
381 size_t key_length
= strlen(buffer
);
383 check
->func(instance
,
385 buffer
+key_length
+1, strlen(buffer
+key_length
+1),
390 /* shit... memcached_response will decrement the counter, so I need to
391 ** reset it.. todo: look at this and try to find a better solution.
393 instance
->cursor_active
= 0;
395 return MEMCACHED_SUCCESS
;
398 static memcached_return_t
ascii_stats_fetch(memcached_stat_st
*memc_stat
,
400 memcached_server_write_instance_st instance
,
401 struct local_context
*check
)
403 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
408 send_length
= (size_t) snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, "stats %s\r\n", args
);
412 send_length
= (size_t) snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, "stats\r\n");
415 if (send_length
>= MEMCACHED_DEFAULT_COMMAND_SIZE
|| send_length
< 0)
417 return memcached_set_error(*instance
, MEMCACHED_MEMORY_ALLOCATION_FAILURE
, MEMCACHED_AT
,
418 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
421 memcached_return_t rc
= memcached_do(instance
, buffer
, (size_t)send_length
, true);
422 if (memcached_success(rc
))
424 while ((rc
= memcached_response(instance
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, NULL
)) == MEMCACHED_STAT
)
426 char *string_ptr
, *end_ptr
;
430 string_ptr
+= 5; /* Move past STAT */
431 for (end_ptr
= string_ptr
; isgraph(*end_ptr
); end_ptr
++) {};
433 key
[(size_t)(end_ptr
-string_ptr
)]= 0;
435 string_ptr
= end_ptr
+ 1;
436 for (end_ptr
= string_ptr
; !(isspace(*end_ptr
)); end_ptr
++) {};
438 value
[(size_t)(end_ptr
-string_ptr
)]= 0;
441 unlikely((set_data(memc_stat
, key
, value
)) == MEMCACHED_UNKNOWN_STAT_KEY
)
443 WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY
);
444 WATCHPOINT_ASSERT(0);
448 if (check
&& check
->func
)
450 check
->func(instance
,
452 value
, strlen(value
),
458 if (rc
== MEMCACHED_END
)
459 return MEMCACHED_SUCCESS
;
464 memcached_stat_st
*memcached_stat(memcached_st
*self
, char *args
, memcached_return_t
*error
)
466 memcached_return_t unused
;
472 memcached_return_t rc
;
473 if (memcached_failed(rc
= initialize_query(self
)))
480 WATCHPOINT_ASSERT(error
);
482 if (self
->flags
.use_udp
)
484 *error
= memcached_set_error(*self
, MEMCACHED_NOT_SUPPORTED
, MEMCACHED_AT
);
489 memcached_stat_st
*stats
= static_cast<memcached_stat_st
*>(libmemcached_calloc(self
, memcached_server_count(self
), sizeof(memcached_stat_st
)));
493 *error
= MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
498 WATCHPOINT_ASSERT(rc
== MEMCACHED_SUCCESS
);
499 rc
= MEMCACHED_SUCCESS
;
500 for (uint32_t x
= 0; x
< memcached_server_count(self
); x
++)
502 memcached_return_t temp_return
;
503 memcached_server_write_instance_st instance
;
504 memcached_stat_st
*stat_instance
;
506 stat_instance
= stats
+x
;
508 stat_instance
->pid
= -1;
509 stat_instance
->root
= self
;
511 instance
= memcached_server_instance_fetch(self
, x
);
513 if (self
->flags
.binary_protocol
)
515 temp_return
= binary_stats_fetch(stat_instance
, args
, instance
, NULL
);
519 temp_return
= ascii_stats_fetch(stat_instance
, args
, instance
, NULL
);
522 if (memcached_failed(temp_return
))
524 rc
= MEMCACHED_SOME_ERRORS
;
533 memcached_return_t
memcached_stat_servername(memcached_stat_st
*memc_stat
, char *args
,
534 const char *hostname
, in_port_t port
)
537 memcached_server_write_instance_st instance
;
539 memset(memc_stat
, 0, sizeof(memcached_stat_st
));
541 memcached_st
*memc_ptr
= memcached_create(&memc
);
543 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
545 memcached_server_add(&memc
, hostname
, port
);
547 memcached_return_t rc
;
548 if ((rc
= initialize_query(memc_ptr
)) != MEMCACHED_SUCCESS
)
553 instance
= memcached_server_instance_fetch(memc_ptr
, 0);
555 if (memc
.flags
.binary_protocol
)
557 rc
= binary_stats_fetch(memc_stat
, args
, instance
, NULL
);
561 rc
= ascii_stats_fetch(memc_stat
, args
, instance
, NULL
);
564 memcached_free(&memc
);
570 We make a copy of the keys since at some point in the not so distant future
571 we will add support for "found" keys.
573 char ** memcached_stat_get_keys(memcached_st
*ptr
,
575 memcached_return_t
*error
)
580 char **list
= static_cast<char **>(libmemcached_malloc(ptr
, sizeof(memcached_stat_keys
)));
583 *error
= memcached_set_error(*ptr
, MEMCACHED_MEMORY_ALLOCATION_FAILURE
, MEMCACHED_AT
);
587 memcpy(list
, memcached_stat_keys
, sizeof(memcached_stat_keys
));
589 *error
= MEMCACHED_SUCCESS
;
594 void memcached_stat_free(const memcached_st
*, memcached_stat_st
*memc_stat
)
596 WATCHPOINT_ASSERT(memc_stat
); // Be polite, but when debugging catch this as an error
597 if (memc_stat
== NULL
)
604 libmemcached_free(memc_stat
->root
, memc_stat
);
608 libmemcached_free(NULL
, memc_stat
);
611 static memcached_return_t
call_stat_fn(memcached_st
*ptr
,
612 memcached_server_write_instance_st instance
,
615 memcached_return_t rc
;
616 struct local_context
*check
= (struct local_context
*)context
;
618 if (ptr
->flags
.binary_protocol
)
620 rc
= binary_stats_fetch(NULL
, check
->args
, instance
, check
);
624 rc
= ascii_stats_fetch(NULL
, check
->args
, instance
, check
);
630 memcached_return_t
memcached_stat_execute(memcached_st
*memc
, const char *args
, memcached_stat_fn func
, void *context
)
632 memcached_version(memc
);
634 struct local_context
check(func
, context
, args
);
636 return memcached_server_execute(memc
, call_stat_fn
, (void *)&check
);