4 #include <memcached/protocol_binary.h>
18 static int connect_server(
const char *hostname,
const char *port)
21 struct addrinfo hints = { .ai_family = AF_UNSPEC,
22 .ai_protocol = IPPROTO_TCP,
23 .ai_socktype = SOCK_STREAM };
25 if (getaddrinfo(hostname, port, &hints, &ai) != 0) {
29 if ((sock = socket(ai->ai_family, ai->ai_socktype,
30 ai->ai_protocol)) != -1) {
31 if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
48 static void retry_send(
int sock,
const void*
buf,
size_t len)
51 const char* ptr =
buf;
54 size_t num_bytes = len -
offset;
55 ssize_t nw = send(sock, ptr + offset, num_bytes, 0);
58 fprintf(stderr,
"Failed to write: %s\n", strerror(errno));
65 }
while (offset < len);
75 static void retry_recv(
int sock,
void *buf,
size_t len) {
81 ssize_t nr = recv(sock, ((
char*)buf) + offset, len - offset, 0);
84 fprintf(stderr,
"Failed to read: %s\n", strerror(errno));
90 fprintf(stderr,
"Connection closed\n");
96 }
while (offset < len);
106 static void print(
const char *key,
int keylen,
const char *val,
int vallen) {
107 fputs(
"STAT ", stdout);
108 (void)fwrite(key, keylen, 1, stdout);
110 (void)fwrite(val, vallen, 1, stdout);
120 static void request_stat(
int sock,
const char *key)
122 uint32_t buffsize = 0;
126 keylen = (uint16_t)strlen(key);
130 .message.header.request = {
131 .magic = PROTOCOL_BINARY_REQ,
132 .opcode = PROTOCOL_BINARY_CMD_STAT,
133 .keylen = htons(keylen),
134 .bodylen = htonl(keylen)
138 retry_send(sock, &request,
sizeof(request));
140 retry_send(sock, key, keylen);
145 retry_recv(sock, &response,
sizeof(response.bytes));
146 if (response.message.header.response.keylen != 0) {
147 uint16_t keylen = ntohs(response.message.header.response.keylen);
148 uint32_t vallen = ntohl(response.message.header.response.bodylen);
149 if (vallen > buffsize) {
150 if ((buffer = realloc(buffer, vallen)) == NULL) {
151 fprintf(stderr,
"Failed to allocate memory\n");
156 retry_recv(sock, buffer, vallen);
157 print(buffer, keylen, buffer + keylen, vallen - keylen);
159 }
while (response.message.header.response.keylen != 0);
170 int main(
int argc,
char **argv)
173 const char *
const default_ports[] = {
"memcache",
"11211", NULL };
174 const char *port = NULL;
175 const char *host = NULL;
179 initialize_sockets();
181 while ((cmd = getopt(argc, argv,
"h:p:")) != EOF) {
185 ptr = strchr(optarg,
':');
196 "Usage mcstat [-h host[:port]] [-p port] [statkey]*\n");
209 port = default_ports[ii++];
210 sock = connect_server(host, port);
211 }
while (sock == -1 && default_ports[ii] != NULL);
213 sock = connect_server(host, port);
217 fprintf(stderr,
"Failed to connect to memcached server (%s:%s): %s\n",
218 host, port, strerror(errno));
222 if (optind == argc) {
223 request_stat(sock, NULL);
225 for (
int ii = optind; ii < argc; ++ii) {
226 request_stat(sock, argv[ii]);