bin: consolidate clients
[awesomized/libmemcached] / src / bin / memping.cc
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "mem_config.h"
17
18 #define PROGRAM_NAME "memping"
19 #define PROGRAM_DESCRIPTION "Ping a server or a set of servers."
20 #define PROGRAM_VERSION "1.1"
21
22 #include "common/options.hpp"
23 #include "common/checks.hpp"
24
25 #include "libmemcached/util.h"
26
27 static memcached_return_t ping(const memcached_st *memc, const memcached_instance_st *s, void *ctx) {
28 auto opt = static_cast<client_options *>(ctx);
29 memcached_return_t rc;
30 bool ok;
31
32 if (opt->isset("debug")) {
33 std::cerr << "Trying to ping" << s->_hostname << ":" << s->port() << ".\n";
34 }
35
36 if (auto username = opt->argof("username")) {
37 auto password = opt->argof("password");
38 ok = libmemcached_util_ping2(s->_hostname, s->port(), username, password, &rc);
39 } else {
40 ok = libmemcached_util_ping(s->_hostname, s->port(), &rc);
41 }
42 if (!ok && !opt->isset("quiet")) {
43 std::cerr << "Failed to ping '" << s->_hostname << ":" << s->port()
44 << ":" << memcached_strerror(memc, rc) << ".\n";
45 }
46
47 return rc;
48 }
49
50 int main(int argc, char *argv[]) {
51 client_options opt{PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_DESCRIPTION};
52
53 for (const auto &def : opt.defaults) {
54 switch (def.opt.val) {
55 case 'h': // --help
56 case 'V': // --version
57 case 'v': // --verbose
58 case 'd': // --debug
59 case 'q': // --quiet
60 case 's': // --servers
61 case 'u': // --username
62 case 'p': // --password
63 opt.add(def);
64 break;
65 default:
66 break;
67 }
68 }
69
70 if (!opt.parse(argc, argv, nullptr)) {
71 exit(EXIT_FAILURE);
72 }
73
74 memcached_st memc;
75 if (!check_memcached(opt, memc)) {
76 exit(EXIT_FAILURE);
77 }
78
79 if (!opt.apply(&memc)) {
80 memcached_free(&memc);
81 exit(EXIT_FAILURE);
82 }
83
84 auto exit_code = EXIT_SUCCESS;
85 memcached_server_fn cb[1] = {&ping};
86 if (!memcached_success(memcached_server_cursor(&memc, cb, &opt, 1))) {
87 exit_code = EXIT_FAILURE;
88 }
89
90 memcached_free(&memc);
91 exit(exit_code);
92 }
93
94 #include <cerrno>
95 #include <cstdio>
96 #include <cstring>
97 #include <getopt.h>
98 #include <unistd.h>
99
100 #include "libmemcached-1.0/memcached.h"
101 #include "libmemcachedutil-1.0/util.h"
102 #include "client_options.h"
103 #include "utilities.h"
104
105 #include <iostream>
106
107 static bool opt_binary = false;
108 static int opt_verbose = 0;
109 static time_t opt_expire = 0;
110 static char *opt_servers = NULL;
111 static char *opt_username;
112 static char *opt_passwd;
113
114 #define PROGRAM_NAME "memping"
115 #define PROGRAM_DESCRIPTION "Ping a server to see if it is alive"
116
117 /* Prototypes */
118 void options_parse(int argc, char *argv[]);
119
120 int main(int argc, char *argv[]) {
121 options_parse(argc, argv);
122
123 if (opt_servers == NULL) {
124 char *temp;
125
126 if ((temp = getenv("MEMCACHED_SERVERS"))) {
127 opt_servers = strdup(temp);
128 }
129
130 if (opt_servers == NULL) {
131 std::cerr << "No Servers provided" << std::endl;
132 exit(EXIT_FAILURE);
133 }
134 }
135
136 int exit_code = EXIT_SUCCESS;
137 memcached_server_st *servers = memcached_servers_parse(opt_servers);
138 if (servers == NULL or memcached_server_list_count(servers) == 0) {
139 std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
140 exit_code = EXIT_FAILURE;
141 } else {
142 for (uint32_t x = 0; x < memcached_server_list_count(servers); x++) {
143 memcached_return_t instance_rc;
144 const char *hostname = servers[x].hostname;
145 in_port_t port = servers[x].port;
146
147 if (opt_verbose) {
148 std::cout << "Trying to ping " << hostname << ":" << port << std::endl;
149 }
150
151 if (libmemcached_util_ping2(hostname, port, opt_username, opt_passwd, &instance_rc) == false)
152 {
153 std::cerr << "Failed to ping " << hostname << ":" << port << " "
154 << memcached_strerror(NULL, instance_rc) << std::endl;
155 exit_code = EXIT_FAILURE;
156 }
157 }
158 }
159 memcached_server_list_free(servers);
160
161 free(opt_servers);
162
163 return exit_code;
164 }
165
166 void options_parse(int argc, char *argv[]) {
167 memcached_programs_help_st help_options[] = {
168 {0},
169 };
170
171 static struct option long_options[] = {
172 {(OPTIONSTRING) "version", no_argument, NULL, OPT_VERSION},
173 {(OPTIONSTRING) "help", no_argument, NULL, OPT_HELP},
174 {(OPTIONSTRING) "quiet", no_argument, NULL, OPT_QUIET},
175 {(OPTIONSTRING) "verbose", no_argument, &opt_verbose, OPT_VERBOSE},
176 {(OPTIONSTRING) "debug", no_argument, &opt_verbose, OPT_DEBUG},
177 {(OPTIONSTRING) "servers", required_argument, NULL, OPT_SERVERS},
178 {(OPTIONSTRING) "expire", required_argument, NULL, OPT_EXPIRE},
179 {(OPTIONSTRING) "binary", no_argument, NULL, OPT_BINARY},
180 {(OPTIONSTRING) "username", required_argument, NULL, OPT_USERNAME},
181 {(OPTIONSTRING) "password", required_argument, NULL, OPT_PASSWD},
182 {0, 0, 0, 0},
183 };
184
185 bool opt_version = false;
186 bool opt_help = false;
187 int option_index = 0;
188 while (1) {
189 int option_rv = getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
190
191 if (option_rv == -1)
192 break;
193
194 switch (option_rv) {
195 case 0:
196 break;
197
198 case OPT_BINARY:
199 opt_binary = true;
200 break;
201
202 case OPT_VERBOSE: /* --verbose or -v */
203 opt_verbose = OPT_VERBOSE;
204 break;
205
206 case OPT_DEBUG: /* --debug or -d */
207 opt_verbose = OPT_DEBUG;
208 break;
209
210 case OPT_VERSION: /* --version or -V */
211 version_command(PROGRAM_NAME);
212 break;
213
214 case OPT_HELP: /* --help or -h */
215 help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
216 break;
217
218 case OPT_SERVERS: /* --servers or -s */
219 opt_servers = strdup(optarg);
220 break;
221
222 case OPT_EXPIRE: /* --expire */
223 errno = 0;
224 opt_expire = time_t(strtoll(optarg, (char **) NULL, 10));
225 if (errno) {
226 std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::endl;
227 exit(EXIT_FAILURE);
228 }
229 break;
230
231 case OPT_USERNAME:
232 opt_username = optarg;
233 opt_binary = true;
234 break;
235
236 case OPT_PASSWD:
237 opt_passwd = optarg;
238 break;
239
240 case OPT_QUIET:
241 close_stdio();
242 break;
243
244 case '?':
245 /* getopt_long already printed an error message. */
246 exit(1);
247 default:
248 abort();
249 }
250 }
251
252 if (opt_version) {
253 version_command(PROGRAM_NAME);
254 exit(EXIT_SUCCESS);
255 }
256
257 if (opt_help) {
258 help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
259 exit(EXIT_SUCCESS);
260 }
261 }