xref: /3.0.3-GA/memcached/programs/mcstat.c (revision b449bca0)
1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2#include "config.h"
3
4#include <memcached/protocol_binary.h>
5#include <memcached/openssl.h>
6#include <platform/platform.h>
7
8#include <getopt.h>
9#include <stdlib.h>
10#include <stdio.h>
11
12#include "utilities.h"
13
14/**
15 * Print the key value pair
16 * @param key key to print
17 * @param keylen length of key to print
18 * @param val value to print
19 * @param vallen length of value
20 */
21static void print(const char *key, int keylen, const char *val, int vallen) {
22    fputs("STAT ", stdout);
23    (void)fwrite(key, keylen, 1, stdout);
24    fputs(" ", stdout);
25    (void)fwrite(val, vallen, 1, stdout);
26    fputs("\n", stdout);
27    fflush(stdout);
28}
29
30/**
31 * Request a stat from the server
32 * @param sock socket connected to the server
33 * @param key the name of the stat to receive (NULL == ALL)
34 */
35static void request_stat(BIO *bio, const char *key)
36{
37    uint32_t buffsize = 0;
38    char *buffer = NULL;
39    uint16_t keylen = 0;
40    protocol_binary_request_stats request;
41    protocol_binary_response_no_extras response;
42
43    if (key != NULL) {
44        keylen = (uint16_t)strlen(key);
45    }
46
47    memset(&request, 0, sizeof(request));
48    request.message.header.request.magic = PROTOCOL_BINARY_REQ;
49    request.message.header.request.opcode = PROTOCOL_BINARY_CMD_STAT;
50    request.message.header.request.keylen = htons(keylen);
51    request.message.header.request.bodylen = htonl(keylen);
52
53    ensure_send(bio, &request, sizeof(request));
54    if (keylen > 0) {
55        ensure_send(bio, key, keylen);
56    }
57
58    do {
59        ensure_recv(bio, &response, sizeof(response.bytes));
60        if (response.message.header.response.keylen != 0) {
61            uint16_t keylen = ntohs(response.message.header.response.keylen);
62            uint32_t vallen = ntohl(response.message.header.response.bodylen);
63            if (vallen > buffsize) {
64                if ((buffer = realloc(buffer, vallen)) == NULL) {
65                    fprintf(stderr, "Failed to allocate memory\n");
66                    exit(1);
67                }
68                buffsize = vallen;
69            }
70            ensure_recv(bio, buffer, vallen);
71            print(buffer, keylen, buffer + keylen, vallen - keylen);
72        }
73    } while (response.message.header.response.keylen != 0);
74}
75
76int main(int argc, char** argv) {
77    int cmd;
78    const char *port = "11210";
79    const char *host = "localhost";
80    const char *user = NULL;
81    const char *pass = NULL;
82    int secure = 0;
83    char *ptr;
84    SSL_CTX* ctx;
85    BIO* bio;
86
87    /* Initialize the socket subsystem */
88    cb_initialize_sockets();
89
90    while ((cmd = getopt(argc, argv, "h:p:u:P:s")) != EOF) {
91        switch (cmd) {
92        case 'h' :
93            host = optarg;
94            ptr = strchr(optarg, ':');
95            if (ptr != NULL) {
96                *ptr = '\0';
97                port = ptr + 1;
98            }
99            break;
100        case 'p':
101            port = optarg;
102            break;
103        case 'u' :
104            user = optarg;
105            break;
106        case 'P':
107            pass = optarg;
108            break;
109        case 's':
110            secure = 1;
111            break;
112        default:
113            fprintf(stderr,
114                    "Usage mcstat [-h host[:port]] [-p port] [-u user] [-P pass] [-s] [statkey]*\n");
115            return 1;
116        }
117    }
118
119    if (create_ssl_connection(&ctx, &bio, host, port, user, pass, secure) != 0) {
120        return 1;
121    }
122
123    if (optind == argc) {
124        request_stat(bio, NULL);
125    } else {
126        int ii;
127        for (ii = optind; ii < argc; ++ii) {
128            request_stat(bio, argv[ii]);
129        }
130    }
131
132    BIO_free_all(bio);
133    if (secure) {
134        SSL_CTX_free(ctx);
135    }
136
137    return EXIT_SUCCESS;
138}
139