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 memc_stat
->pid
= strtoul(value
, (char **)NULL
, 10);
60 else if (not strcmp("uptime", key
))
62 memc_stat
->uptime
= strtoul(value
, (char **)NULL
, 10);
64 else if (not strcmp("time", key
))
66 memc_stat
->time
= strtoul(value
, (char **)NULL
, 10);
68 else if (not strcmp("version", key
))
70 memcpy(memc_stat
->version
, value
, strlen(value
));
71 memc_stat
->version
[strlen(value
)]= 0;
73 else if (not strcmp("pointer_size", key
))
75 memc_stat
->pointer_size
= strtoul(value
, (char **)NULL
, 10);
77 else if (not strcmp("rusage_user", key
))
80 for (walk_ptr
= value
; (!ispunct(*walk_ptr
)); walk_ptr
++) {};
83 memc_stat
->rusage_user_seconds
= strtoul(value
, (char **)NULL
, 10);
84 memc_stat
->rusage_user_microseconds
= strtoul(walk_ptr
, (char **)NULL
, 10);
86 else if (not strcmp("rusage_system", key
))
89 for (walk_ptr
= value
; (!ispunct(*walk_ptr
)); walk_ptr
++) {};
92 memc_stat
->rusage_system_seconds
= strtoul(value
, (char **)NULL
, 10);
93 memc_stat
->rusage_system_microseconds
= strtoul(walk_ptr
, (char **)NULL
, 10);
95 else if (not strcmp("curr_items", key
))
97 memc_stat
->curr_items
= strtoul(value
, (char **)NULL
, 10);
99 else if (not strcmp("total_items", key
))
101 memc_stat
->total_items
= strtoul(value
, (char **)NULL
, 10);
103 else if (not strcmp("bytes_read", key
))
105 memc_stat
->bytes_read
= strtoull(value
, (char **)NULL
, 10);
107 else if (not strcmp("bytes_written", key
))
109 memc_stat
->bytes_written
= strtoull(value
, (char **)NULL
, 10);
111 else if (not strcmp("bytes", key
))
113 memc_stat
->bytes
= strtoull(value
, (char **)NULL
, 10);
115 else if (not strcmp("curr_connections", key
))
117 memc_stat
->curr_connections
= strtoull(value
, (char **)NULL
, 10);
119 else if (not strcmp("total_connections", key
))
121 memc_stat
->total_connections
= strtoull(value
, (char **)NULL
, 10);
123 else if (not strcmp("connection_structures", key
))
125 memc_stat
->connection_structures
= strtoul(value
, (char **)NULL
, 10);
127 else if (not strcmp("cmd_get", key
))
129 memc_stat
->cmd_get
= strtoull(value
, (char **)NULL
, 10);
131 else if (not strcmp("cmd_set", key
))
133 memc_stat
->cmd_set
= strtoull(value
, (char **)NULL
, 10);
135 else if (not strcmp("get_hits", key
))
137 memc_stat
->get_hits
= strtoull(value
, (char **)NULL
, 10);
139 else if (not strcmp("get_misses", key
))
141 memc_stat
->get_misses
= strtoull(value
, (char **)NULL
, 10);
143 else if (not strcmp("evictions", key
))
145 memc_stat
->evictions
= strtoull(value
, (char **)NULL
, 10);
147 else if (not strcmp("limit_maxbytes", key
))
149 memc_stat
->limit_maxbytes
= strtoull(value
, (char **)NULL
, 10);
151 else if (not strcmp("threads", key
))
153 memc_stat
->threads
= strtoul(value
, (char **)NULL
, 10);
155 else if (not (strcmp("delete_misses", key
) == 0 or /* New stats in the 1.3 beta */
156 strcmp("delete_hits", key
) == 0 or /* Just swallow them for now.. */
157 strcmp("incr_misses", key
) == 0 or
158 strcmp("incr_hits", key
) == 0 or
159 strcmp("decr_misses", key
) == 0 or
160 strcmp("decr_hits", key
) == 0 or
161 strcmp("cas_misses", key
) == 0 or
162 strcmp("cas_hits", key
) == 0 or
163 strcmp("cas_badval", key
) == 0 or
164 strcmp("cmd_flush", key
) == 0 or
165 strcmp("accepting_conns", key
) == 0 or
166 strcmp("listen_disabled_num", key
) == 0 or
167 strcmp("conn_yields", key
) == 0 or
168 strcmp("auth_cmds", key
) == 0 or
169 strcmp("auth_errors", key
) == 0 or
170 strcmp("reclaimed", key
) == 0))
172 WATCHPOINT_STRING(key
);
173 /* return MEMCACHED_UNKNOWN_STAT_KEY; */
174 return MEMCACHED_SUCCESS
;
177 return MEMCACHED_SUCCESS
;
180 char *memcached_stat_get_value(const memcached_st
*ptr
, memcached_stat_st
*memc_stat
,
181 const char *key
, memcached_return_t
*error
)
183 char buffer
[SMALL_STRING_LEN
];
187 *error
= MEMCACHED_SUCCESS
;
189 if (not memcmp("pid", key
, sizeof("pid") -1))
191 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->pid
);
193 else if (not memcmp("uptime", key
, sizeof("uptime") -1))
195 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->uptime
);
197 else if (not memcmp("time", key
, sizeof("time") -1))
199 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->time
);
201 else if (not memcmp("version", key
, sizeof("version") -1))
203 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%s", memc_stat
->version
);
205 else if (not memcmp("pointer_size", key
, sizeof("pointer_size") -1))
207 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->pointer_size
);
209 else if (not memcmp("rusage_user", key
, sizeof("rusage_user") -1))
211 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu.%lu", memc_stat
->rusage_user_seconds
, memc_stat
->rusage_user_microseconds
);
213 else if (not memcmp("rusage_system", key
, sizeof("rusage_system") -1))
215 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu.%lu", memc_stat
->rusage_system_seconds
, memc_stat
->rusage_system_microseconds
);
217 else if (not memcmp("curr_items", key
, sizeof("curr_items") -1))
219 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->curr_items
);
221 else if (not memcmp("total_items", key
, sizeof("total_items") -1))
223 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->total_items
);
225 else if (not memcmp("curr_connections", key
, sizeof("curr_connections") -1))
227 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->curr_connections
);
229 else if (not memcmp("total_connections", key
, sizeof("total_connections") -1))
231 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->total_connections
);
233 else if (not memcmp("connection_structures", key
, sizeof("connection_structures") -1))
235 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->connection_structures
);
237 else if (not memcmp("cmd_get", key
, sizeof("cmd_get") -1))
239 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->cmd_get
);
241 else if (not memcmp("cmd_set", key
, sizeof("cmd_set") -1))
243 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->cmd_set
);
245 else if (not memcmp("get_hits", key
, sizeof("get_hits") -1))
247 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->get_hits
);
249 else if (not memcmp("get_misses", key
, sizeof("get_misses") -1))
251 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->get_misses
);
253 else if (not memcmp("evictions", key
, sizeof("evictions") -1))
255 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->evictions
);
257 else if (not memcmp("bytes_read", key
, sizeof("bytes_read") -1))
259 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes_read
);
261 else if (not memcmp("bytes_written", key
, sizeof("bytes_written") -1))
263 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes_written
);
265 else if (not memcmp("bytes", key
, sizeof("bytes") -1))
267 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->bytes
);
269 else if (not memcmp("limit_maxbytes", key
, sizeof("limit_maxbytes") -1))
271 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%llu", (unsigned long long)memc_stat
->limit_maxbytes
);
273 else if (not memcmp("threads", key
, sizeof("threads") -1))
275 length
= snprintf(buffer
, SMALL_STRING_LEN
,"%lu", memc_stat
->threads
);
279 *error
= MEMCACHED_NOTFOUND
;
283 if (length
>= SMALL_STRING_LEN
|| length
< 0)
285 *error
= MEMCACHED_FAILURE
;
289 ret
= static_cast<char *>(libmemcached_malloc(ptr
, (size_t) (length
+ 1)));
290 memcpy(ret
, buffer
, (size_t) length
);
296 static memcached_return_t
binary_stats_fetch(memcached_stat_st
*memc_stat
,
298 memcached_server_write_instance_st instance
,
299 struct local_context
*check
)
301 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
302 protocol_binary_request_stats request
= {}; // = {.bytes= {0}};
303 request
.message
.header
.request
.magic
= PROTOCOL_BINARY_REQ
;
304 request
.message
.header
.request
.opcode
= PROTOCOL_BINARY_CMD_STAT
;
305 request
.message
.header
.request
.datatype
= PROTOCOL_BINARY_RAW_BYTES
;
309 size_t len
= strlen(args
);
311 memcached_return_t rc
= memcached_validate_key_length(len
, true);
312 unlikely (rc
!= MEMCACHED_SUCCESS
)
315 request
.message
.header
.request
.keylen
= htons((uint16_t)len
);
316 request
.message
.header
.request
.bodylen
= htonl((uint32_t) len
);
318 struct libmemcached_io_vector_st vector
[]=
320 { sizeof(request
.bytes
), request
.bytes
},
324 if (memcached_vdo(instance
, vector
, 2, true) != MEMCACHED_SUCCESS
)
326 memcached_io_reset(instance
);
327 return MEMCACHED_WRITE_FAILURE
;
332 if (memcached_do(instance
, request
.bytes
,
333 sizeof(request
.bytes
), true) != MEMCACHED_SUCCESS
)
335 memcached_io_reset(instance
);
336 return MEMCACHED_WRITE_FAILURE
;
340 memcached_server_response_decrement(instance
);
343 memcached_return_t rc
= memcached_response(instance
, buffer
, sizeof(buffer
), NULL
);
345 if (rc
== MEMCACHED_END
)
348 unlikely (rc
!= MEMCACHED_SUCCESS
)
350 memcached_io_reset(instance
);
356 unlikely((set_data(memc_stat
, buffer
, buffer
+ strlen(buffer
) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY
)
358 WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY
);
359 WATCHPOINT_ASSERT(0);
363 if (check
&& check
->func
)
365 size_t key_length
= strlen(buffer
);
367 check
->func(instance
,
369 buffer
+key_length
+1, strlen(buffer
+key_length
+1),
374 /* shit... memcached_response will decrement the counter, so I need to
375 ** reset it.. todo: look at this and try to find a better solution.
377 instance
->cursor_active
= 0;
379 return MEMCACHED_SUCCESS
;
382 static memcached_return_t
ascii_stats_fetch(memcached_stat_st
*memc_stat
,
384 memcached_server_write_instance_st instance
,
385 struct local_context
*check
)
387 memcached_return_t rc
;
388 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
392 send_length
= (size_t) snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
393 "stats %s\r\n", args
);
395 send_length
= (size_t) snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
398 if (send_length
>= MEMCACHED_DEFAULT_COMMAND_SIZE
|| send_length
< 0)
399 return MEMCACHED_WRITE_FAILURE
;
401 rc
= memcached_do(instance
, buffer
, (size_t)send_length
, true);
402 if (rc
!= MEMCACHED_SUCCESS
)
407 rc
= memcached_response(instance
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, NULL
);
409 if (rc
== MEMCACHED_STAT
)
411 char *string_ptr
, *end_ptr
;
415 string_ptr
+= 5; /* Move past STAT */
416 for (end_ptr
= string_ptr
; isgraph(*end_ptr
); end_ptr
++) {};
418 key
[(size_t)(end_ptr
-string_ptr
)]= 0;
420 string_ptr
= end_ptr
+ 1;
421 for (end_ptr
= string_ptr
; !(isspace(*end_ptr
)); end_ptr
++) {};
423 value
[(size_t)(end_ptr
-string_ptr
)]= 0;
424 string_ptr
= end_ptr
+ 2;
427 unlikely((set_data(memc_stat
, key
, value
)) == MEMCACHED_UNKNOWN_STAT_KEY
)
429 WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY
);
430 WATCHPOINT_ASSERT(0);
434 if (check
&& check
->func
)
436 check
->func(instance
,
438 value
, strlen(value
),
449 if (rc
== MEMCACHED_END
)
450 return MEMCACHED_SUCCESS
;
455 memcached_stat_st
*memcached_stat(memcached_st
*self
, char *args
, memcached_return_t
*error
)
457 memcached_return_t rc
;
458 if ((rc
= initialize_query(self
)) != MEMCACHED_SUCCESS
)
466 WATCHPOINT_ASSERT(error
);
468 unlikely (self
->flags
.use_udp
)
471 *error
= MEMCACHED_NOT_SUPPORTED
;
476 memcached_stat_st
*stats
= static_cast<memcached_stat_st
*>(libmemcached_calloc(self
, memcached_server_count(self
), sizeof(memcached_stat_st
)));
481 *error
= MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
486 WATCHPOINT_ASSERT(rc
== MEMCACHED_SUCCESS
);
487 rc
= MEMCACHED_SUCCESS
;
488 for (uint32_t x
= 0; x
< memcached_server_count(self
); x
++)
490 memcached_return_t temp_return
;
491 memcached_server_write_instance_st instance
;
492 memcached_stat_st
*stat_instance
;
494 stat_instance
= stats
+x
;
496 stat_instance
->root
= self
;
498 instance
= memcached_server_instance_fetch(self
, x
);
500 if (self
->flags
.binary_protocol
)
502 temp_return
= binary_stats_fetch(stat_instance
, args
, instance
, NULL
);
506 temp_return
= ascii_stats_fetch(stat_instance
, args
, instance
, NULL
);
509 if (temp_return
!= MEMCACHED_SUCCESS
)
510 rc
= MEMCACHED_SOME_ERRORS
;
519 memcached_return_t
memcached_stat_servername(memcached_stat_st
*memc_stat
, char *args
,
520 const char *hostname
, in_port_t port
)
523 memcached_server_write_instance_st instance
;
525 memset(memc_stat
, 0, sizeof(memcached_stat_st
));
527 memcached_st
*memc_ptr
= memcached_create(&memc
);
529 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
531 memcached_server_add(&memc
, hostname
, port
);
533 memcached_return_t rc
;
534 if ((rc
= initialize_query(memc_ptr
)) != MEMCACHED_SUCCESS
)
539 instance
= memcached_server_instance_fetch(memc_ptr
, 0);
541 if (memc
.flags
.binary_protocol
)
543 rc
= binary_stats_fetch(memc_stat
, args
, instance
, NULL
);
547 rc
= ascii_stats_fetch(memc_stat
, args
, instance
, NULL
);
550 memcached_free(&memc
);
556 We make a copy of the keys since at some point in the not so distant future
557 we will add support for "found" keys.
559 char ** memcached_stat_get_keys(memcached_st
*ptr
,
561 memcached_return_t
*error
)
566 char **list
= static_cast<char **>(libmemcached_malloc(ptr
, sizeof(memcached_stat_keys
)));
569 *error
= memcached_set_error(*ptr
, MEMCACHED_MEMORY_ALLOCATION_FAILURE
, MEMCACHED_AT
);
573 memcpy(list
, memcached_stat_keys
, sizeof(memcached_stat_keys
));
575 *error
= MEMCACHED_SUCCESS
;
580 void memcached_stat_free(const memcached_st
*, memcached_stat_st
*memc_stat
)
582 WATCHPOINT_ASSERT(memc_stat
); // Be polite, but when debugging catch this as an error
590 libmemcached_free(memc_stat
->root
, memc_stat
);
594 libmemcached_free(NULL
, memc_stat
);
597 static memcached_return_t
call_stat_fn(memcached_st
*ptr
,
598 memcached_server_write_instance_st instance
,
601 memcached_return_t rc
;
602 struct local_context
*check
= (struct local_context
*)context
;
604 if (ptr
->flags
.binary_protocol
)
606 rc
= binary_stats_fetch(NULL
, check
->args
, instance
, check
);
610 rc
= ascii_stats_fetch(NULL
, check
->args
, instance
, check
);
616 memcached_return_t
memcached_stat_execute(memcached_st
*memc
, const char *args
, memcached_stat_fn func
, void *context
)
618 memcached_version(memc
);
620 struct local_context
check(func
, context
, args
);
622 return memcached_server_execute(memc
, call_stat_fn
, (void *)&check
);