Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 995 lines (859 sloc) 30.492 kb
22dd900 @steveyen moved memagent reconfig stuff into cproxy_config.c
steveyen authored
1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
6fcace5 @trondn Move to pandora build
trondn authored
2 #include "config.h"
22dd900 @steveyen moved memagent reconfig stuff into cproxy_config.c
steveyen authored
3 #include <stdio.h>
0577ccb @steveyen avoid libmemcached dependency
steveyen authored
4 #include <stdlib.h>
22dd900 @steveyen moved memagent reconfig stuff into cproxy_config.c
steveyen authored
5 #include <string.h>
6 #include <errno.h>
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
7 #include <ctype.h>
caae159 @steveyen find_downstream_conn can flag if we're talking to ourselves
steveyen authored
8 #include <unistd.h>
22dd900 @steveyen moved memagent reconfig stuff into cproxy_config.c
steveyen authored
9 #include <pthread.h>
10 #include <assert.h>
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
11 #include <math.h>
22dd900 @steveyen moved memagent reconfig stuff into cproxy_config.c
steveyen authored
12 #include "memcached.h"
13 #include "cproxy.h"
14 #include "work.h"
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
15 #include "log.h"
22dd900 @steveyen moved memagent reconfig stuff into cproxy_config.c
steveyen authored
16
db94fe9 @steveyen helper_g_free()
steveyen authored
17 // Local declarations.
18 //
286f08e @steveyen jid/pswd can optionally be read from a secure file
steveyen authored
19 static char *readfile(char *path);
20
6a26e91 @steveyen MB-2897 - use 64-bits for msec_current time
steveyen authored
21 volatile uint64_t msec_current_time = 0;
21cb663 @steveyen msec_clock_handler() configured off by default
steveyen authored
22 int msec_cycle = 0;
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
23 struct event msec_clockevent;
c3efc27 @steveyen configurable retries max, and clock resolution
steveyen authored
24 struct event_base *msec_clockevent_base = NULL;
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
25
caae159 @steveyen find_downstream_conn can flag if we're talking to ourselves
steveyen authored
26 char cproxy_hostname[300] = {0}; // Immutable after init.
27
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
28 void msec_clock_handler(const int fd, const short which, void *arg);
29 void msec_set_current_time(void);
30
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
31 int cproxy_init_string(char *cfg_str,
8a7e4b6 @steveyen Moved nthreads out of proxy_behavior.
steveyen authored
32 proxy_behavior behavior,
33 int nthreads);
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
34
26bf25b @steveyen calling init_conflate()
steveyen authored
35 int cproxy_init_agent(char *cfg_str,
36 proxy_behavior behavior,
37 int nthreads);
38
050b81f @mtaneja mcmux protocol support for moxi
mtaneja authored
39 int cproxy_init_mcmux_mode(int proxy_port,
40 proxy_behavior behavior,
41 int nthreads);
42
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
43 proxy_behavior behavior_default_g = {
8128746 @steveyen MB-2403 - default to 200ms clock cycle for better logging
steveyen authored
44 .cycle = 200, // Clock cycle or quantum, in milliseconds.
0b23b54 @steveyen pt-12636461 - default timeout config
steveyen authored
45 .downstream_max = 1024,
46 .downstream_conn_max = 4, // Use 0 for unlimited.
46423ca @steveyen added weight and key/val aliases
steveyen authored
47 .downstream_weight = 0,
1021a58 @steveyen default downstream_retry is 1
steveyen authored
48 .downstream_retry = 1,
987091c @steveyen renamed downstream_prot to downstream_protocol
steveyen authored
49 .downstream_protocol = proxy_downstream_ascii_prot,
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
50 .downstream_timeout = {
0b23b54 @steveyen pt-12636461 - default timeout config
steveyen authored
51 .tv_sec = 5,
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
52 .tv_usec = 0
53 },
026a9b7 @steveyen MB-2825 - downstream_conn_queue_timeout
steveyen authored
54 .downstream_conn_queue_timeout = {
55 .tv_sec = 0,
0b23b54 @steveyen pt-12636461 - default timeout config
steveyen authored
56 .tv_usec = 200000
026a9b7 @steveyen MB-2825 - downstream_conn_queue_timeout
steveyen authored
57 },
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
58 .wait_queue_timeout = {
59 .tv_sec = 0,
0b23b54 @steveyen pt-12636461 - default timeout config
steveyen authored
60 .tv_usec = 200000
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
61 },
0229813 @steveyen MB-2806 - connect_timeout is now -Z configurable
steveyen authored
62 .connect_timeout = {
0b23b54 @steveyen pt-12636461 - default timeout config
steveyen authored
63 .tv_sec = 0,
64 .tv_usec = 400000
0229813 @steveyen MB-2806 - connect_timeout is now -Z configurable
steveyen authored
65 },
646bff3 @steveyen MB-2724 - configurable auth_timeout with auth timeout blacklisting
steveyen authored
66 .auth_timeout = {
67 .tv_sec = 0,
0b23b54 @steveyen pt-12636461 - default timeout config
steveyen authored
68 .tv_usec = 100000
646bff3 @steveyen MB-2724 - configurable auth_timeout with auth timeout blacklisting
steveyen authored
69 },
d38ecbc @steveyen bug 1911 - time_stats flag to capture more timing info
steveyen authored
70 .time_stats = false,
167ac24 @steveyen MB-3798 - moxi option for ketama/weighted/modula item distributions
steveyen authored
71 .mcs_opts = {0},
0b23b54 @steveyen pt-12636461 - default timeout config
steveyen authored
72 .connect_max_errors = 5, // In zstored, 10.
73 .connect_retry_interval = 30000, // In zstored, 30000.
3f95ed5 @steveyen configurable max number of front cache items
steveyen authored
74 .front_cache_max = 200,
c1506ae @steveyen parsing front_cache_lifespan behavior
steveyen authored
75 .front_cache_lifespan = 0,
7197f19 @steveyen front_cache_spec in behavior
steveyen authored
76 .front_cache_spec = {0},
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
77 .front_cache_unspec = {0},
e5910ca @steveyen started key_stats
steveyen authored
78 .key_stats_max = 4000,
79 .key_stats_lifespan = 0,
80 .key_stats_spec = {0},
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
81 .key_stats_unspec = {0},
5971996 @steveyen matcher refactor with lock
steveyen authored
82 .optimize_set = {0},
50187c2 @steveyen added proxy-level behavior settings
steveyen authored
83 .host = {0},
629370a @steveyen no more host:port meaning in svr name
steveyen authored
84 .port = 0,
50187c2 @steveyen added proxy-level behavior settings
steveyen authored
85 .bucket = {0},
3642114 @steveyen MB-2972 - return SERVER_ERROR for membase bucket GET's
steveyen authored
86 .nodeLocator = {0},
50187c2 @steveyen added proxy-level behavior settings
steveyen authored
87 .usr = {0},
f93e1b3 @steveyen port_listen and proxy name is part of identifier
steveyen authored
88 .pwd = {0},
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
89 .port_listen = MOXI_DEFAULT_LISTEN_PORT,
1e0192d @steveyen bug 1998 - handle missing default bucket correctly
steveyen authored
90 .default_bucket_name = FIRST_BUCKET
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
91 };
92
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
93 /** Length of key that may be zero or space terminated.
94 */
db94fe9 @steveyen helper_g_free()
steveyen authored
95 size_t skey_len(const char *key) {
96 assert(key);
97
98 char *x = (char *) key;
99 while (*x != ' ' && *x != '\0')
100 x++;
101
102 return x - key;
103 }
104
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
105 /** Hash of key that may be zero or space terminated.
106 */
ea4d064 @dustin Replaced glib dependency with a custom hash table.
dustin authored
107 int skey_hash(const void *v) {
db94fe9 @steveyen helper_g_free()
steveyen authored
108 assert(v);
109
110 const char *key = v;
111 size_t len = skey_len(key);
112
113 return murmur_hash(key, len);
114 }
115
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
116 /** Returns true if two keys are equal, where the
117 * keys may be zero or space terminated.
118 */
ea4d064 @dustin Replaced glib dependency with a custom hash table.
dustin authored
119 int skey_equal(const void *v1, const void *v2) {
db94fe9 @steveyen helper_g_free()
steveyen authored
120 assert(v1);
121 assert(v2);
122
123 const char *k1 = v1;
124 const char *k2 = v2;
125
126 size_t n1 = skey_len(k1);
127 size_t n2 = skey_len(k2);
128
129 return (n1 == n2 && strncmp(k1, k2, n1) == 0);
130 }
131
ea4d064 @dustin Replaced glib dependency with a custom hash table.
dustin authored
132 static void *noop_dup(const void *v)
133 {
134 return (void*)v;
db94fe9 @steveyen helper_g_free()
steveyen authored
135 }
136
ea4d064 @dustin Replaced glib dependency with a custom hash table.
dustin authored
137 void noop_free(void *v) {
e1ae2ef @alk fixes tons of warnings produced on GNU/Linux
alk authored
138 (void)v;
ea4d064 @dustin Replaced glib dependency with a custom hash table.
dustin authored
139 /* Nothing */
140 }
141
142 static int
143 str_eq(const void* p1, const void*p2)
144 {
145 char *str1=(char *)p1;
146 char *str2=(char *)p2;
147 assert(str1 != NULL);
148 assert(str2 != NULL);
149 return strcmp(str1, str2) == 0;
150 }
151
152 struct hash_ops strhash_ops = {
153 .hashfunc = genhash_string_hash,
154 .hasheq = str_eq,
155 .dupKey = noop_dup,
156 .dupValue = noop_dup,
157 .freeKey = noop_free,
158 .freeValue = noop_free
159 };
160
161 struct hash_ops skeyhash_ops = {
162 .hashfunc = skey_hash,
163 .hasheq = skey_equal,
164 .dupKey = noop_dup,
165 .dupValue = noop_dup,
166 .freeKey = noop_free,
167 .freeValue = noop_free
168 };
169
947c762 @steveyen trimstr()
steveyen authored
170 /** Returns pointer to first non-space char in string.
171 */
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
172 char *skipspace(char *s) {
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
173 if (s == NULL) {
947c762 @steveyen trimstr()
steveyen authored
174 return NULL;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
175 }
947c762 @steveyen trimstr()
steveyen authored
176
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
177 while (isspace(*s) && *s != '\0') {
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
178 s++;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
179 }
180
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
181 return s;
182 }
183
947c762 @steveyen trimstr()
steveyen authored
184 /** Modifies string by zero'ing out any trailing spaces.
185 */
186 char *trailspace(char *s) {
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
187 if (s == NULL) {
947c762 @steveyen trimstr()
steveyen authored
188 return NULL;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
189 }
947c762 @steveyen trimstr()
steveyen authored
190
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
191 for (char *e = s + strlen(s) - 1; e >= s && isspace(*e); e--) {
947c762 @steveyen trimstr()
steveyen authored
192 *e = '\0';
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
193 }
947c762 @steveyen trimstr()
steveyen authored
194
195 return s;
196 }
197
198 /** Modifies string by removing prefix and suffix whitespace chars.
199 * Returns the pointer into the string that you should use.
200 */
201 char *trimstr(char *s) {
202 return trailspace(skipspace(s));
203 }
204
205 /** Like strdup(), but trims spaces from start and end.
206 * Unlike with trimstr(strdup(s)), you can call free(trimstrdup(s)),
207 * and the correct memory is free()'ed.
208 */
209 char *trimstrdup(char *s) {
210 return trailspace(strdup(skipspace(s)));
211 }
212
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
213 /** Returns true if first word in a string equals a given word.
214 */
215 bool wordeq(char *s, char *word) {
216 assert(s);
217 assert(word);
218
219 char *end = s;
220 while (!isspace(*end) && *end != '\0')
221 end++;
222
223 return strncmp(s, word, end - s) == 0;
224 }
225
db94fe9 @steveyen helper_g_free()
steveyen authored
226 // ---------------------------------------
227
2f57f3a @steveyen cproxy_core_init need to call g_thread_init()
steveyen authored
228 static bool cproxy_core_initted = false;
229
286f08e @steveyen jid/pswd can optionally be read from a secure file
steveyen authored
230 /** The cfg_str may be a path to a file like...
231 *
232 * /full/path
233 * or...
234 * ./relative/path
235 * or...
236 * ../another/relative/path
237 *
238 * But not...
239 *
240 * incorrect/relative/path
241 *
242 * Paths are detected by the first character of '/' or '.'.
243 *
244 * The contents of the file should be in cfg_str format.
245 */
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
246 int cproxy_init(char *cfg_str,
247 char *behavior_str,
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
248 int nthreads,
249 struct event_base *main_base) {
83bd5c8 @steveyen cproxy stats more work in progress
steveyen authored
250 assert(nthreads > 1); // Main + at least one worker.
24042d2 @steveyen moved protocol handling stuff into cproxy_protocol.c
steveyen authored
251 assert(nthreads == settings.num_threads);
252
2f57f3a @steveyen cproxy_core_init need to call g_thread_init()
steveyen authored
253 if (cproxy_core_initted == false) {
254 cproxy_core_initted = true;
255
256 gethostname(cproxy_hostname, sizeof(cproxy_hostname));
257
258 cproxy_init_a2a();
259 cproxy_init_a2b();
d785d2d @steveyen b2b upstream & downstream for simple, non-quiet commands
steveyen authored
260 cproxy_init_b2b();
2f57f3a @steveyen cproxy_core_init need to call g_thread_init()
steveyen authored
261 }
262
9531761 @steveyen mcmux compat needs cmd-line behavior
steveyen authored
263 if ((cfg_str == NULL || strlen(cfg_str) <= 0) &&
264 (false == settings.enable_mcmux_mode)) {
bc3236b @steveyen revivied old init for testing
steveyen authored
265 return 0;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
266 }
bc3236b @steveyen revivied old init for testing
steveyen authored
267
7a2d764 @steveyen removed JHP_STATS conditional code
steveyen authored
268 if (behavior_str != NULL &&
269 (behavior_str[0] == '.' ||
270 behavior_str[0] == '/')) {
6bd9a2c @steveyen behavior_str parameter can also be filename
steveyen authored
271 char *buf = readfile(behavior_str);
272 if (buf != NULL) {
273 int rv = cproxy_init(cfg_str, buf, nthreads, main_base);
274 free(buf);
275 return rv;
276 } else {
10cd773 @steveyen bug 1958 - using stderr if moxi exit()'s
steveyen authored
277 moxi_log_write("ERROR: could not read behavior file: %s\n", behavior_str);
278 if (ml->log_mode != ERRORLOG_STDERR) {
279 fprintf(stderr, "ERROR: could not read behavior file: %s\n", behavior_str);
280 }
6bd9a2c @steveyen behavior_str parameter can also be filename
steveyen authored
281 exit(EXIT_FAILURE);
282 }
283 }
284
9531761 @steveyen mcmux compat needs cmd-line behavior
steveyen authored
285 if ((false == settings.enable_mcmux_mode) &&
286 (cfg_str[0] == '.' || cfg_str[0] == '/')) {
286f08e @steveyen jid/pswd can optionally be read from a secure file
steveyen authored
287 char *buf = readfile(cfg_str);
288 if (buf != NULL) {
289 int rv = cproxy_init(buf, behavior_str, nthreads, main_base);
290 free(buf);
291 return rv;
292 } else {
10cd773 @steveyen bug 1958 - using stderr if moxi exit()'s
steveyen authored
293 moxi_log_write("ERROR: could not read cfg file: %s\n", cfg_str);
294 if (ml->log_mode != ERRORLOG_STDERR) {
295 fprintf(stderr, "ERROR: could not read cfg file: %s\n", cfg_str);
296 }
286f08e @steveyen jid/pswd can optionally be read from a secure file
steveyen authored
297 exit(EXIT_FAILURE);
298 }
299 }
caae159 @steveyen find_downstream_conn can flag if we're talking to ourselves
steveyen authored
300
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
301 if (behavior_str == NULL) {
68ea4a6 @steveyen handle when behavior_str is NULL
steveyen authored
302 behavior_str = "";
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
303 }
68ea4a6 @steveyen handle when behavior_str is NULL
steveyen authored
304
2049eba @steveyen bug 2231 - MOXI_USE_LIBVBUCKET and MOXI_USE_LIBMEMCACHED
steveyen authored
305 #ifdef MOXI_USE_LIBVBUCKET
759eb74 @steveyen default to binary protocol during vbucket usage
steveyen authored
306 // The vbucket feature only works in binary protocol.
307 //
308 behavior_default_g.downstream_protocol = proxy_downstream_binary_prot;
309 #endif
310
12e9de4 @steveyen bug 1885 - allow sasl plain usr/pwd from ENV
steveyen authored
311 char *env_usr = getenv("MOXI_SASL_PLAIN_USR");
312 if (env_usr != NULL) {
313 strncpy(behavior_default_g.usr, env_usr, sizeof(behavior_default_g.usr) - 1);
314 behavior_default_g.usr[sizeof(behavior_default_g.usr) - 1] = '\0';
315
316 moxi_log_write("env: MOXI_SASL_PLAIN_USR (%d)\n",
317 strlen(behavior_default_g.usr));
318 }
319
320 char *env_pwd = getenv("MOXI_SASL_PLAIN_PWD");
321 if (env_pwd != NULL) {
322 strncpy(behavior_default_g.pwd, env_pwd, sizeof(behavior_default_g.pwd) - 1);
323 behavior_default_g.pwd[sizeof(behavior_default_g.pwd) - 1] = '\0';
324
325 moxi_log_write("env: MOXI_SASL_PLAIN_PWD (%d)\n",
326 strlen(behavior_default_g.pwd));
327 }
328
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
329 proxy_behavior behavior =
330 cproxy_parse_behavior(behavior_str,
331 behavior_default_g);
332
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
333 if (behavior.cycle > 0) {
c3efc27 @steveyen configurable retries max, and clock resolution
steveyen authored
334 msec_cycle = behavior.cycle;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
335 }
c3efc27 @steveyen configurable retries max, and clock resolution
steveyen authored
336
337 msec_clockevent_base = main_base;
338 msec_clock_handler(0, 0, NULL);
339
050b81f @mtaneja mcmux protocol support for moxi
mtaneja authored
340 if (true == settings.enable_mcmux_mode) {
341 return cproxy_init_mcmux_mode(settings.port,
342 behavior,
343 nthreads);
344 }
345
91951d5 @steveyen bug 1366 - simplified moxi cmd-line
steveyen authored
346 // Not jid format and not a URL, so it must be a simple cmd-line
347 // or file-based config.
348 //
349 if (strchr(cfg_str, '@') == NULL &&
350 strstr(cfg_str, "http://") == NULL) {
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
351 return cproxy_init_string(cfg_str,
8a7e4b6 @steveyen Moved nthreads out of proxy_behavior.
steveyen authored
352 behavior,
353 nthreads);
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
354 }
1ce052b @steveyen cleanup error msgs around init
steveyen authored
355
90c377b @steveyen fixed wrong define
steveyen authored
356 #ifdef HAVE_CONFLATE_H
656ca64 @steveyen Exit if empty -z configuration
steveyen authored
357 if (settings.verbose > 2) {
358 cproxy_dump_behavior(&behavior, "cproxy_init_agent", 2);
359 }
360
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
361 return cproxy_init_agent(cfg_str,
8a7e4b6 @steveyen Moved nthreads out of proxy_behavior.
steveyen authored
362 behavior,
363 nthreads);
3c28b75 @steveyen taking strophe out if memagent.h not there
steveyen authored
364 #else
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
365 moxi_log_write("missing conflate\n");
8032f2d @steveyen better startup err msgs
steveyen authored
366 exit(EXIT_FAILURE);
3c28b75 @steveyen taking strophe out if memagent.h not there
steveyen authored
367 return 1;
368 #endif
fa62546 @steveyen parsing cmdline instead of hardcoded jid/password
steveyen authored
369 }
370
050b81f @mtaneja mcmux protocol support for moxi
mtaneja authored
371 int cproxy_init_mcmux_mode(int proxy_port,
372 proxy_behavior behavior,
373 int nthreads) {
374
375 char *proxy_name = "default";
376
377 if (settings.verbose > 1) {
378 cproxy_dump_behavior(&behavior, "init_string", 2);
379 }
380
381 int behaviors_num = 1; // Number of servers.
382 proxy_behavior_pool behavior_pool;
383 memset(&behavior_pool, 0, sizeof(proxy_behavior_pool));
384
385 behavior_pool.base = behavior;
386 behavior_pool.num = behaviors_num;
387 behavior_pool.arr = calloc(behaviors_num,
388 sizeof(proxy_behavior));
389
390 if (behavior_pool.arr != NULL) {
391 for (int i = 0; i < behaviors_num; i++) {
392 behavior_pool.arr[i] = behavior;
393 }
394
395 proxy_main *m = cproxy_gen_proxy_main(behavior, nthreads,
396 PROXY_CONF_TYPE_STATIC);
397 if (m == NULL) {
398 moxi_log_write("could not alloc proxy_main\n");
399 exit(EXIT_FAILURE);
400 }
401
402 proxy *p = cproxy_create(m,
403 proxy_name,
404 proxy_port,
405 "mcmux_config",
406 0, // config_ver.
407 &behavior_pool,
408 nthreads);
409 if (p != NULL) {
410 pthread_mutex_lock(&m->proxy_main_lock);
411 p->next = m->proxy_head;
412 m->proxy_head = p;
413 pthread_mutex_unlock(&m->proxy_main_lock);
414
415 int n = cproxy_listen(p);
416 if (n > 0) {
417 if (settings.verbose > 1) {
418 moxi_log_write("moxi listening on %d with %d conns\n",
419 proxy_port, n);
420 }
421 } else {
422 moxi_log_write("moxi error -- port %d unavailable?\n",
04d6311 @steveyen bug 2576 - relevant err msg when bad uds socket
steveyen authored
423 proxy_port);
050b81f @mtaneja mcmux protocol support for moxi
mtaneja authored
424 exit(EXIT_FAILURE);
425 }
426 } else {
427 moxi_log_write("could not alloc proxy\n");
428 exit(EXIT_FAILURE);
429 }
430
431 free(behavior_pool.arr);
432 } else {
433 moxi_log_write("could not alloc behaviors\n");
434 exit(EXIT_FAILURE);
435 }
436
437 return 0;
438 }
439
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
440 int cproxy_init_string(char *cfg_str,
8a7e4b6 @steveyen Moved nthreads out of proxy_behavior.
steveyen authored
441 proxy_behavior behavior,
442 int nthreads) {
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
443 /* cfg looks like "local_port=host:port,host:port;local_port=host:port"
bc3236b @steveyen revivied old init for testing
steveyen authored
444 * like "11222=memcached1.foo.net:11211" This means local port 11222
445 * will be a proxy to downstream memcached server running at
446 * host memcached1.foo.net on port 11211.
447 */
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
448 if (cfg_str== NULL ||
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
449 strlen(cfg_str) <= 0) {
bc3236b @steveyen revivied old init for testing
steveyen authored
450 return 0;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
451 }
bc3236b @steveyen revivied old init for testing
steveyen authored
452
453 char *buff;
454 char *next;
455 char *proxy_name = "default";
456 char *proxy_sect;
457 char *proxy_port_str;
458 int proxy_port;
459
fbc73db @steveyen cproxy_dump_behavior
steveyen authored
460 if (settings.verbose > 1) {
c1506ae @steveyen parsing front_cache_lifespan behavior
steveyen authored
461 cproxy_dump_behavior(&behavior, "init_string", 2);
fbc73db @steveyen cproxy_dump_behavior
steveyen authored
462 }
463
3d67f5e @steveyen trimstrdup()
steveyen authored
464 buff = trimstrdup(cfg_str);
bc3236b @steveyen revivied old init for testing
steveyen authored
465 next = buff;
466 while (next != NULL) {
947c762 @steveyen trimstr()
steveyen authored
467 proxy_sect = strsep(&next, ";");
bc3236b @steveyen revivied old init for testing
steveyen authored
468
947c762 @steveyen trimstr()
steveyen authored
469 proxy_port_str = trimstr(strsep(&proxy_sect, "="));
bc3236b @steveyen revivied old init for testing
steveyen authored
470 if (proxy_sect == NULL) {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
471 moxi_log_write("bad moxi config, missing =\n");
bc3236b @steveyen revivied old init for testing
steveyen authored
472 exit(EXIT_FAILURE);
473 }
474 proxy_port = atoi(proxy_port_str);
475 if (proxy_port <= 0) {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
476 moxi_log_write("missing proxy port\n");
bc3236b @steveyen revivied old init for testing
steveyen authored
477 exit(EXIT_FAILURE);
478 }
947c762 @steveyen trimstr()
steveyen authored
479 proxy_sect = trimstr(proxy_sect);
bc3236b @steveyen revivied old init for testing
steveyen authored
480
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
481 int behaviors_num = 1; // Number of servers.
16be84f @steveyen proxy_behavior_pool struct
steveyen authored
482 for (char *x = proxy_sect; *x != '\0'; x++) {
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
483 if (*x == ',') {
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
484 behaviors_num++;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
485 }
16be84f @steveyen proxy_behavior_pool struct
steveyen authored
486 }
487
488 proxy_behavior_pool behavior_pool;
489 memset(&behavior_pool, 0, sizeof(proxy_behavior_pool));
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
490
16be84f @steveyen proxy_behavior_pool struct
steveyen authored
491 behavior_pool.base = behavior;
492 behavior_pool.num = behaviors_num;
493 behavior_pool.arr = calloc(behaviors_num,
494 sizeof(proxy_behavior));
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
495
16be84f @steveyen proxy_behavior_pool struct
steveyen authored
496 if (behavior_pool.arr != NULL) {
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
497 for (int i = 0; i < behaviors_num; i++) {
16be84f @steveyen proxy_behavior_pool struct
steveyen authored
498 behavior_pool.arr[i] = behavior;
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
499 }
500
f4d3531 Added new ascii commands of "stats proxy sub-command".
Joon(JunHyun Park) authored
501 proxy_main *m = cproxy_gen_proxy_main(behavior, nthreads,
502 PROXY_CONF_TYPE_STATIC);
503 if (m == NULL) {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
504 moxi_log_write("could not alloc proxy_main\n");
f4d3531 Added new ascii commands of "stats proxy sub-command".
Joon(JunHyun Park) authored
505 exit(EXIT_FAILURE);
506 }
507
2bebd7a @steveyen added proxy_main ptr to the proxy struct
steveyen authored
508 proxy *p = cproxy_create(m,
509 proxy_name,
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
510 proxy_port,
511 proxy_sect,
512 0, // config_ver.
16be84f @steveyen proxy_behavior_pool struct
steveyen authored
513 &behavior_pool,
8a7e4b6 @steveyen Moved nthreads out of proxy_behavior.
steveyen authored
514 nthreads);
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
515 if (p != NULL) {
f4d3531 Added new ascii commands of "stats proxy sub-command".
Joon(JunHyun Park) authored
516 pthread_mutex_lock(&m->proxy_main_lock);
517 p->next = m->proxy_head;
518 m->proxy_head = p;
519 pthread_mutex_unlock(&m->proxy_main_lock);
520
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
521 int n = cproxy_listen(p);
522 if (n > 0) {
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
523 if (settings.verbose > 1) {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
524 moxi_log_write("moxi listening on %d with %d conns\n",
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
525 proxy_port, n);
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
526 }
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
527 } else {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
528 moxi_log_write("moxi error -- port %d unavailable?\n",
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
529 proxy_port);
530 exit(EXIT_FAILURE);
531 }
07086ab @steveyen moxi errors when port is unavailable to listen
steveyen authored
532 } else {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
533 moxi_log_write("could not alloc proxy\n");
07086ab @steveyen moxi errors when port is unavailable to listen
steveyen authored
534 exit(EXIT_FAILURE);
bc3236b @steveyen revivied old init for testing
steveyen authored
535 }
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
536
16be84f @steveyen proxy_behavior_pool struct
steveyen authored
537 free(behavior_pool.arr);
bc3236b @steveyen revivied old init for testing
steveyen authored
538 } else {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
539 moxi_log_write("could not alloc behaviors\n");
bc3236b @steveyen revivied old init for testing
steveyen authored
540 exit(EXIT_FAILURE);
541 }
542 }
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
543
bc3236b @steveyen revivied old init for testing
steveyen authored
544 free(buff);
545
546 return 0;
547 }
2365e34 @steveyen using latest kvpairs structures
steveyen authored
548
a4d1193 @alk implemented gdb-callable connections_diag
alk authored
549 proxy_main *diag_last_proxy_main;
550
f4d3531 Added new ascii commands of "stats proxy sub-command".
Joon(JunHyun Park) authored
551 proxy_main *cproxy_gen_proxy_main(proxy_behavior behavior, int nthreads,
552 enum_proxy_conf_type conf_type) {
553 proxy_main *m = calloc(1, sizeof(proxy_main));
554 if (m != NULL) {
555 m->proxy_head = NULL;
556 m->behavior = behavior;
557 m->nthreads = nthreads;
558 m->conf_type = conf_type;
559
560 pthread_mutex_init(&m->proxy_main_lock, NULL);
561
562 m->stat_configs = 0;
563 m->stat_config_fails = 0;
564 m->stat_proxy_starts = 0;
565 m->stat_proxy_start_fails = 0;
566 m->stat_proxy_existings = 0;
567 m->stat_proxy_shutdowns = 0;
a4d1193 @alk implemented gdb-callable connections_diag
alk authored
568
569 diag_last_proxy_main = m;
f4d3531 Added new ascii commands of "stats proxy sub-command".
Joon(JunHyun Park) authored
570 }
7a2d764 @steveyen removed JHP_STATS conditional code
steveyen authored
571
f4d3531 Added new ascii commands of "stats proxy sub-command".
Joon(JunHyun Park) authored
572 return m;
573 }
574
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
575 proxy_behavior cproxy_parse_behavior(char *behavior_str,
576 proxy_behavior behavior_default) {
1c049cd @steveyen parsing for binary downstream protocol flag in cmdline
steveyen authored
577 // These are the default proxy behaviors.
578 //
005a5e1 @steveyen added sasl_mech/auth to proxy behavior, which is now more inheritable
steveyen authored
579 struct proxy_behavior behavior = behavior_default;
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
580
581 if (behavior_str == NULL ||
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
582 strlen(behavior_str) <= 0) {
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
583 return behavior;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
584 }
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
585
1c049cd @steveyen parsing for binary downstream protocol flag in cmdline
steveyen authored
586 // Parse the key-value behavior_str, to override the defaults.
587 //
3d67f5e @steveyen trimstrdup()
steveyen authored
588 char *buff = trimstrdup(behavior_str);
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
589 char *next = buff;
590
591 while (next != NULL) {
947c762 @steveyen trimstr()
steveyen authored
592 char *key_val = trimstr(strsep(&next, ","));
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
593 if (key_val != NULL) {
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
594 cproxy_parse_behavior_key_val_str(key_val, &behavior);
44353a5 @steveyen refactor misc config slots into a proxy_behavior struct
steveyen authored
595 }
596 }
597
598 free(buff);
599
600 return behavior;
601 }
602
947c762 @steveyen trimstr()
steveyen authored
603 /** Note: the key_val param buffer is modified.
604 */
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
605 void cproxy_parse_behavior_key_val_str(char *key_val,
606 proxy_behavior *behavior) {
607 assert(behavior != NULL);
608
609 if (key_val != NULL) {
610 char *key = strsep(&key_val, "=");
611 char *val = key_val;
612 cproxy_parse_behavior_key_val(key, val, behavior);
613 }
614 }
615
947c762 @steveyen trimstr()
steveyen authored
616 /** Note: the key and val param buffers are modified.
617 */
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
618 void cproxy_parse_behavior_key_val(char *key,
619 char *val,
620 proxy_behavior *behavior) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
621 uint32_t ms = 0;
622 uint32_t x = 0;
623 bool ok = false;
624
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
625 assert(behavior != NULL);
626
627 if (key != NULL &&
628 val != NULL) {
947c762 @steveyen trimstr()
steveyen authored
629 key = trimstr(key);
630 val = trimstr(val);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
631
632 if (wordeq(key, "cycle")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
633 ok = safe_strtoul(val, &behavior->cycle);
477259b @steveyen MB-2807 - moxi configuration synonyms
steveyen authored
634 } else if (wordeq(key, "downstream_max") ||
635 wordeq(key, "concurrency")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
636 ok = safe_strtoul(val, &behavior->downstream_max);
739a491 @steveyen added downstream_conn_max config parsing
steveyen authored
637 } else if (wordeq(key, "downstream_conn_max")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
638 ok = safe_strtoul(val, &behavior->downstream_conn_max);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
639 } else if (wordeq(key, "weight") ||
640 wordeq(key, "downstream_weight")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
641 ok = safe_strtoul(val, &behavior->downstream_weight);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
642 } else if (wordeq(key, "retry") ||
643 wordeq(key, "downstream_retry")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
644 ok = safe_strtoul(val, &behavior->downstream_retry);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
645 } else if (wordeq(key, "protocol") ||
646 wordeq(key, "downstream_protocol")) {
4a02c85 @steveyen added more specific protocol string names
steveyen authored
647 if (wordeq(val, "ascii") ||
785ec78 @steveyen allowing protocol to be membase-ascii or membase-binary
steveyen authored
648 wordeq(val, "memcached-ascii") ||
649 wordeq(val, "membase-ascii")) {
987091c @steveyen renamed downstream_prot to downstream_protocol
steveyen authored
650 behavior->downstream_protocol =
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
651 proxy_downstream_ascii_prot;
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
652 ok = true;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
653 } else if (wordeq(val, "binary") ||
785ec78 @steveyen allowing protocol to be membase-ascii or membase-binary
steveyen authored
654 wordeq(val, "memcached-binary") ||
655 wordeq(val, "membase-binary")) {
987091c @steveyen renamed downstream_prot to downstream_protocol
steveyen authored
656 behavior->downstream_protocol =
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
657 proxy_downstream_binary_prot;
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
658 ok = true;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
659 } else {
660 if (settings.verbose > 1) {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
661 moxi_log_write("unknown behavior prot: %s\n", val);
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
662 }
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
663 }
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
664 } else if (wordeq(key, "timeout") ||
477259b @steveyen MB-2807 - moxi configuration synonyms
steveyen authored
665 wordeq(key, "downstream_timeout") ||
666 wordeq(key, "downstream_conn_timeout")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
667 ok = safe_strtoul(val, &ms);
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
668 behavior->downstream_timeout.tv_sec = floor(ms / 1000.0);
669 behavior->downstream_timeout.tv_usec = (ms % 1000) * 1000;
026a9b7 @steveyen MB-2825 - downstream_conn_queue_timeout
steveyen authored
670 } else if (wordeq(key, "downstream_conn_queue_timeout")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
671 ok = safe_strtoul(val, &ms);
026a9b7 @steveyen MB-2825 - downstream_conn_queue_timeout
steveyen authored
672 behavior->downstream_conn_queue_timeout.tv_sec = floor(ms / 1000.0);
673 behavior->downstream_conn_queue_timeout.tv_usec = (ms % 1000) * 1000;
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
674 } else if (wordeq(key, "wait_queue_timeout")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
675 ok = safe_strtoul(val, &ms);
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
676 behavior->wait_queue_timeout.tv_sec = floor(ms / 1000.0);
677 behavior->wait_queue_timeout.tv_usec = (ms % 1000) * 1000;
0229813 @steveyen MB-2806 - connect_timeout is now -Z configurable
steveyen authored
678 } else if (wordeq(key, "connect_timeout")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
679 ok = safe_strtoul(val, &ms);
0229813 @steveyen MB-2806 - connect_timeout is now -Z configurable
steveyen authored
680 behavior->connect_timeout.tv_sec = floor(ms / 1000.0);
681 behavior->connect_timeout.tv_usec = (ms % 1000) * 1000;
646bff3 @steveyen MB-2724 - configurable auth_timeout with auth timeout blacklisting
steveyen authored
682 } else if (wordeq(key, "auth_timeout")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
683 ok = safe_strtoul(val, &ms);
646bff3 @steveyen MB-2724 - configurable auth_timeout with auth timeout blacklisting
steveyen authored
684 behavior->auth_timeout.tv_sec = floor(ms / 1000.0);
685 behavior->auth_timeout.tv_usec = (ms % 1000) * 1000;
d38ecbc @steveyen bug 1911 - time_stats flag to capture more timing info
steveyen authored
686 } else if (wordeq(key, "time_stats")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
687 ok = safe_strtoul(val, &x);
688 behavior->time_stats = x;
167ac24 @steveyen MB-3798 - moxi option for ketama/weighted/modula item distributions
steveyen authored
689 } else if (wordeq(key, "mcs_opts")) {
690 if (strlen(val) < sizeof(behavior->mcs_opts)) {
691 strcpy(behavior->mcs_opts, val);
692 ok = true;
693 }
58e3c07 @steveyen connect timeout and retry interval are now runtime configurable
steveyen authored
694 } else if (wordeq(key, "connect_max_errors")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
695 ok = safe_strtoul(val, &behavior->connect_max_errors);
58e3c07 @steveyen connect timeout and retry interval are now runtime configurable
steveyen authored
696 } else if (wordeq(key, "connect_retry_interval")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
697 ok = safe_strtoul(val, &behavior->connect_retry_interval);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
698 } else if (wordeq(key, "front_cache_max")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
699 ok = safe_strtoul(val, &behavior->front_cache_max);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
700 } else if (wordeq(key, "front_cache_lifespan")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
701 ok = safe_strtoul(val, &behavior->front_cache_lifespan);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
702 } else if (wordeq(key, "front_cache_spec")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
703 if (strlen(val) < sizeof(behavior->front_cache_spec)) {
7197f19 @steveyen front_cache_spec in behavior
steveyen authored
704 strcpy(behavior->front_cache_spec, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
705 ok = true;
7197f19 @steveyen front_cache_spec in behavior
steveyen authored
706 }
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
707 } else if (wordeq(key, "front_cache_unspec")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
708 if (strlen(val) < sizeof(behavior->front_cache_unspec)) {
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
709 strcpy(behavior->front_cache_unspec, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
710 ok = true;
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
711 }
e5910ca @steveyen started key_stats
steveyen authored
712 } else if (wordeq(key, "key_stats_max")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
713 ok = safe_strtoul(val, &behavior->key_stats_max);
e5910ca @steveyen started key_stats
steveyen authored
714 } else if (wordeq(key, "key_stats_lifespan")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
715 ok = safe_strtoul(val, &behavior->key_stats_lifespan);
e5910ca @steveyen started key_stats
steveyen authored
716 } else if (wordeq(key, "key_stats_spec")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
717 if (strlen(val) < sizeof(behavior->key_stats_spec)) {
e5910ca @steveyen started key_stats
steveyen authored
718 strcpy(behavior->key_stats_spec, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
719 ok = true;
e5910ca @steveyen started key_stats
steveyen authored
720 }
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
721 } else if (wordeq(key, "key_stats_unspec")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
722 if (strlen(val) < sizeof(behavior->key_stats_unspec)) {
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
723 strcpy(behavior->key_stats_unspec, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
724 ok = true;
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
725 }
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
726 } else if (wordeq(key, "optimize_set")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
727 if (strlen(val) < sizeof(behavior->optimize_set)) {
5971996 @steveyen matcher refactor with lock
steveyen authored
728 strcpy(behavior->optimize_set, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
729 ok = true;
5971996 @steveyen matcher refactor with lock
steveyen authored
730 }
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
731 } else if (wordeq(key, "usr")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
732 if (strlen(val) < sizeof(behavior->usr)) {
629370a @steveyen no more host:port meaning in svr name
steveyen authored
733 strcpy(behavior->usr, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
734 ok = true;
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
735 }
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
736 } else if (wordeq(key, "pwd")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
737 if (strlen(val) < sizeof(behavior->pwd)) {
629370a @steveyen no more host:port meaning in svr name
steveyen authored
738 strcpy(behavior->pwd, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
739 ok = true;
629370a @steveyen no more host:port meaning in svr name
steveyen authored
740 }
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
741 } else if (wordeq(key, "host")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
742 if (strlen(val) < sizeof(behavior->host)) {
629370a @steveyen no more host:port meaning in svr name
steveyen authored
743 strcpy(behavior->host, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
744 ok = true;
629370a @steveyen no more host:port meaning in svr name
steveyen authored
745 }
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
746 } else if (wordeq(key, "port")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
747 ok = safe_strtol(val, &behavior->port);
9a34bc5 @steveyen wordeq and skipspace()
steveyen authored
748 } else if (wordeq(key, "bucket")) {
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
749 if (strlen(val) < sizeof(behavior->bucket)) {
629370a @steveyen no more host:port meaning in svr name
steveyen authored
750 strcpy(behavior->bucket, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
751 ok = true;
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
752 }
f93e1b3 @steveyen port_listen and proxy name is part of identifier
steveyen authored
753 } else if (wordeq(key, "port_listen")) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
754 ok = safe_strtol(val, &behavior->port_listen);
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
755 } else if (wordeq(key, "default_bucket_name")) {
756 if (strlen(val) < sizeof(behavior->default_bucket_name)) {
757 strcpy(behavior->default_bucket_name, val);
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
758 ok = true;
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
759 }
bce9d23 @steveyen Allow comment characters in -Z config files
steveyen authored
760 } else if (key[0] == '#') { // Comment.
761 ok = true;
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
762 } else {
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
763 if (settings.verbose > 1) {
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
764 moxi_log_write("ERROR: unknown behavior key: %s\n", key);
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
765 }
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
766 }
767 }
1d2c2fe @steveyen MB-2899 - parsing config using safe_strtoul functions
steveyen authored
768
769 if (ok == false) {
770 moxi_log_write("ERROR: config error in key: %s value: %s\n",
771 key, val);
772 }
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
773 }
774
36cc25b @steveyen cproxy_copy_behaviors handles drain array, 2x size, properly
steveyen authored
775 /**
568c436 @steveyen revert drain code to attempt more general expand/shrink code
steveyen authored
776 * Size of array should be arr_size.
36cc25b @steveyen cproxy_copy_behaviors handles drain array, 2x size, properly
steveyen authored
777 */
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
778 proxy_behavior *cproxy_copy_behaviors(int arr_size, proxy_behavior *arr) {
522ddf0 @steveyen added a NULL_BUCKET placeholder for SaaS use-case
steveyen authored
779 int arr_size_alloc = arr_size > 0 ? arr_size : 1;
780 proxy_behavior *rv = calloc(arr_size_alloc, sizeof(proxy_behavior));
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
781 if (rv != NULL) {
568c436 @steveyen revert drain code to attempt more general expand/shrink code
steveyen authored
782 memcpy(rv, arr, arr_size * sizeof(proxy_behavior));
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
783 }
45cb61e @steveyen Turned behaviors into an array.
steveyen authored
784 return rv;
785 }
786
36cc25b @steveyen cproxy_copy_behaviors handles drain array, 2x size, properly
steveyen authored
787 /**
568c436 @steveyen revert drain code to attempt more general expand/shrink code
steveyen authored
788 * Size of x/y array should be x/y_size.
34ec4d7 @steveyen behaviors array is effectively 2x larger for potential drain info
steveyen authored
789 */
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
790 bool cproxy_equal_behaviors(int x_size, proxy_behavior *x,
791 int y_size, proxy_behavior *y) {
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
792 if (x_size != y_size) {
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
793 return false;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
794 }
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
795
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
796 if (x == NULL && y == NULL) {
6e776de @steveyen better check during cproxy_equal_behaviors
steveyen authored
797 return true;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
798 }
6e776de @steveyen better check during cproxy_equal_behaviors
steveyen authored
799
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
800 if (x == NULL || y == NULL) {
6e776de @steveyen better check during cproxy_equal_behaviors
steveyen authored
801 return false;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
802 }
6e776de @steveyen better check during cproxy_equal_behaviors
steveyen authored
803
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
804 for (int i = 0; i < x_size; i++) {
fbc73db @steveyen cproxy_dump_behavior
steveyen authored
805 if (cproxy_equal_behavior(&x[i], &y[i]) == false) {
806 if (settings.verbose > 1) {
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
807 moxi_log_write("behaviors not equal (%d)\n", i);
c1506ae @steveyen parsing front_cache_lifespan behavior
steveyen authored
808 cproxy_dump_behavior(&x[i], "x", 0);
809 cproxy_dump_behavior(&y[i], "y", 0);
fbc73db @steveyen cproxy_dump_behavior
steveyen authored
810 }
811
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
812 return false;
fbc73db @steveyen cproxy_dump_behavior
steveyen authored
813 }
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
814 }
815
816 return true;
817 }
818
819 bool cproxy_equal_behavior(proxy_behavior *x,
820 proxy_behavior *y) {
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
821 if (x == NULL && y == NULL) {
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
822 return true;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
823 }
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
824
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
825 if (x == NULL || y == NULL) {
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
826 return false;
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
827 }
6534a5a @steveyen Removed behaviors_str and no parser-in-a-parser.
steveyen authored
828
829 return memcmp(x, y, sizeof(proxy_behavior)) == 0;
830 }
831
c1506ae @steveyen parsing front_cache_lifespan behavior
steveyen authored
832 void cproxy_dump_behavior(proxy_behavior *b, char *prefix, int level) {
c6938b8 @steveyen reusing cproxy_dump_behavior_ex() in agent stats
steveyen authored
833 cproxy_dump_behavior_ex(b, prefix, level,
834 cproxy_dump_behavior_stderr, NULL);
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
835 }
836
837 void cproxy_dump_behavior_ex(proxy_behavior *b, char *prefix, int level,
38458c4 @steveyen added memcached settings to proxy stats output
steveyen authored
838 void (*dump)(const void *dump_opaque,
839 const char *prefix,
840 const char *key,
841 const char *buf),
842 const void *dump_opaque) {
c6938b8 @steveyen reusing cproxy_dump_behavior_ex() in agent stats
steveyen authored
843 assert(b);
844 assert(dump);
845
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
846 char vbuf[8000];
847
c6938b8 @steveyen reusing cproxy_dump_behavior_ex() in agent stats
steveyen authored
848 #define vdump(key, vfmt, val) { \
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
849 snprintf(vbuf, sizeof(vbuf), vfmt, val); \
c6938b8 @steveyen reusing cproxy_dump_behavior_ex() in agent stats
steveyen authored
850 dump(dump_opaque, prefix, key, vbuf); \
851 }
c1506ae @steveyen parsing front_cache_lifespan behavior
steveyen authored
852
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
853 if (level >= 2) {
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
854 vdump("cycle", "%u", b->cycle);
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
855 }
856 if (level >= 1) {
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
857 vdump("downstream_max", "%u", b->downstream_max);
739a491 @steveyen added downstream_conn_max config parsing
steveyen authored
858 vdump("downstream_conn_max", "%u", b->downstream_conn_max);
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
859 }
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
860
861 vdump("downstream_weight", "%u", b->downstream_weight);
862 vdump("downstream_retry", "%u", b->downstream_retry);
863 vdump("downstream_protocol", "%d", b->downstream_protocol);
864 vdump("downstream_timeout", "%ld", // In millisecs.
865 (b->downstream_timeout.tv_sec * 1000 +
866 b->downstream_timeout.tv_usec / 1000));
026a9b7 @steveyen MB-2825 - downstream_conn_queue_timeout
steveyen authored
867 vdump("downstream_conn_queue_timeout", "%ld", // In millisecs.
868 (b->downstream_conn_queue_timeout.tv_sec * 1000 +
869 b->downstream_conn_queue_timeout.tv_usec / 1000));
c1506ae @steveyen parsing front_cache_lifespan behavior
steveyen authored
870
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
871 if (level >= 1) {
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
872 vdump("wait_queue_timeout", "%ld", // In millisecs.
873 (b->wait_queue_timeout.tv_sec * 1000 +
874 b->wait_queue_timeout.tv_usec / 1000));
0229813 @steveyen MB-2806 - connect_timeout is now -Z configurable
steveyen authored
875 vdump("connect_timeout", "%ld", // In millisecs.
876 (b->connect_timeout.tv_sec * 1000 +
877 b->connect_timeout.tv_usec / 1000));
646bff3 @steveyen MB-2724 - configurable auth_timeout with auth timeout blacklisting
steveyen authored
878 vdump("auth_timeout", "%ld", // In millisecs.
879 (b->auth_timeout.tv_sec * 1000 +
880 b->auth_timeout.tv_usec / 1000));
d38ecbc @steveyen bug 1911 - time_stats flag to capture more timing info
steveyen authored
881 vdump("time_stats", "%d", b->time_stats);
167ac24 @steveyen MB-3798 - moxi option for ketama/weighted/modula item distributions
steveyen authored
882 vdump("mcs_opts", "%s", b->mcs_opts);
58e3c07 @steveyen connect timeout and retry interval are now runtime configurable
steveyen authored
883 vdump("connect_max_errors", "%u", b->connect_max_errors);
884 vdump("connect_retry_interval", "%u", b->connect_retry_interval);
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
885 vdump("front_cache_max", "%u", b->front_cache_max);
886 vdump("front_cache_lifespan", "%u", b->front_cache_lifespan);
887 vdump("front_cache_spec", "%s", b->front_cache_spec);
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
888 vdump("front_cache_unspec", "%s", b->front_cache_unspec);
e5910ca @steveyen started key_stats
steveyen authored
889 vdump("key_stats_max", "%u", b->key_stats_max);
890 vdump("key_stats_lifespan", "%u", b->key_stats_lifespan);
891 vdump("key_stats_spec", "%s", b->key_stats_spec);
30e7a4a @steveyen added unmatcher for front cache and key stats
steveyen authored
892 vdump("key_stats_unspec", "%s", b->key_stats_unspec);
5971996 @steveyen matcher refactor with lock
steveyen authored
893 vdump("optimize_set", "%s", b->optimize_set);
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
894 }
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
895
896 vdump("usr", "%s", b->usr);
897 vdump("host", "%s", b->host);
898 vdump("port", "%d", b->port);
899 vdump("bucket", "%s", b->bucket);
f93e1b3 @steveyen port_listen and proxy name is part of identifier
steveyen authored
900
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
901 if (level >= 1) {
f93e1b3 @steveyen port_listen and proxy name is part of identifier
steveyen authored
902 vdump("port_listen", "%d", b->port_listen);
eeb6174 @steveyen added default_bucket_name is a config param
steveyen authored
903 vdump("default_bucket_name", "%s", b->default_bucket_name);
904 }
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
905 }
906
38458c4 @steveyen added memcached settings to proxy stats output
steveyen authored
907 void cproxy_dump_behavior_stderr(const void *dump_opaque,
908 const char *prefix,
909 const char *key,
910 const char *val) {
e1ae2ef @alk fixes tons of warnings produced on GNU/Linux
alk authored
911 (void)dump_opaque;
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
912 assert(key);
913 assert(val);
914
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
915 if (prefix == NULL) {
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
916 prefix = "";
cf6d49a @steveyen coding style of if statements with braces
steveyen authored
917 }
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
918
6a48c21 @mtaneja Migrate to using moxi log
mtaneja authored
919 moxi_log_write("%s %s: %s\n",
d18522f @steveyen cproxy_dump_behavior() more generalized
steveyen authored
920 prefix, key, val);
fbc73db @steveyen cproxy_dump_behavior
steveyen authored
921 }
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
922
923 // ---------------------------------------
924
6b4a7e7 @steveyen stats for usec spent with a reserved downstream or on retries
steveyen authored
925 uint64_t usec_now(void) {
926 struct timeval timer;
927 gettimeofday(&timer, NULL);
928 return ((timer.tv_sec - process_started) * 1000000) + timer.tv_usec;
929 }
930
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
931 /* Time-sensitive callers can call it by hand with this,
932 * outside the normal subsecond timer
933 */
934 void msec_set_current_time(void) {
935 struct timeval timer;
936 gettimeofday(&timer, NULL);
937 msec_current_time =
938 (timer.tv_sec - process_started) * 1000 + (timer.tv_usec / 1000);
939 }
940
941 void msec_clock_handler(const int fd, const short which, void *arg) {
e1ae2ef @alk fixes tons of warnings produced on GNU/Linux
alk authored
942 (void)fd;
943 (void)which;
944 (void)arg;
21cb663 @steveyen msec_clock_handler() configured off by default
steveyen authored
945
946 if (msec_cycle <= 0) {
947 return;
948 }
949
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
950 // Subsecond resolution timer.
951 //
c3efc27 @steveyen configurable retries max, and clock resolution
steveyen authored
952 struct timeval t = { .tv_sec = 0,
953 .tv_usec = msec_cycle * 1000 };
954
0b2bf82 @steveyen msec_clock_handler for sub-second timeouts
steveyen authored
955 static bool initialized = false;
956
957 if (initialized) {
958 /* only delete the event if it's actually there. */
959 evtimer_del(&msec_clockevent);
960 } else {
961 initialized = true;
962 }
963
964 evtimer_set(&msec_clockevent, msec_clock_handler, 0);
965 event_base_set(msec_clockevent_base, &msec_clockevent);
966 evtimer_add(&msec_clockevent, &t);
967
968 msec_set_current_time();
969 }
970
286f08e @steveyen jid/pswd can optionally be read from a secure file
steveyen authored
971 // ---------------------------------------
972
973 static char *readfile(char *path) {
974 FILE *fp = fopen(path, "r");
975 if (fp != NULL) {
976 if (fseek(fp, 0, SEEK_END) == 0) {
977 long len = ftell(fp);
978 if (len > 0 &&
979 fseek(fp, 0, SEEK_SET) == 0) {
980 char *buf = (char *) malloc(len + 1);
981 if (buf != NULL) {
982 if (fread(buf, len, 1, fp) == 1) {
983 fclose(fp);
984 buf[len] = '\0';
985 return buf;
986 }
987 free(buf);
988 }
989 }
990 }
991 fclose(fp);
992 }
993 return NULL;
994 }
Something went wrong with that request. Please try again.