p9y: bsd
[m6w6/libmemcached] / src / libmemcached / behavior.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 "libmemcached/common.h"
17 #include "libmemcached/options.hpp"
18 #include "libmemcached/virtual_bucket.h"
19 #include "p9y/random.hpp"
20
21 #include <ctime>
22 #include <sys/types.h>
23
24 bool memcached_is_consistent_distribution(const Memcached *memc) {
25 switch (memc->distribution) {
26 case MEMCACHED_DISTRIBUTION_CONSISTENT:
27 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
28 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
29 case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
30 return true;
31
32 case MEMCACHED_DISTRIBUTION_MODULA:
33 case MEMCACHED_DISTRIBUTION_RANDOM:
34 case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
35 case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
36 break;
37 }
38
39 return false;
40 }
41
42 /*
43 This function is used to modify the behavior of running client.
44
45 We quit all connections so we can reset the sockets.
46 */
47
48 memcached_return_t memcached_behavior_set(memcached_st *shell, const memcached_behavior_t flag,
49 uint64_t data) {
50 Memcached *ptr = memcached2Memcached(shell);
51 if (ptr == NULL) {
52 return MEMCACHED_INVALID_ARGUMENTS;
53 }
54
55 switch (flag) {
56 case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
57 ptr->number_of_replicas = (uint32_t) data;
58 break;
59
60 case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
61 ptr->io_msg_watermark = (uint32_t) data;
62 break;
63
64 case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
65 ptr->io_bytes_watermark = (uint32_t) data;
66 break;
67
68 case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
69 ptr->io_key_prefetch = (uint32_t) data;
70 break;
71
72 case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
73 ptr->snd_timeout = (int32_t) data;
74 break;
75
76 case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
77 ptr->rcv_timeout = (int32_t) data;
78 break;
79
80 case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS:
81 ptr->flags.auto_eject_hosts = bool(data);
82 break;
83
84 case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
85 if (data == 0) {
86 return memcached_set_error(
87 *ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
88 memcached_literal_param(
89 "MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT requires a value greater then zero."));
90 }
91 ptr->server_failure_limit = uint32_t(data);
92 break;
93
94 case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
95 ptr->server_timeout_limit = uint32_t(data);
96 break;
97
98 case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
99 send_quit(
100 ptr); // We need t shutdown all of the connections to make sure we do the correct protocol
101 if (data) {
102 ptr->flags.verify_key = false;
103 }
104 ptr->flags.binary_protocol = bool(data);
105 break;
106
107 case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
108 ptr->flags.support_cas = bool(data);
109 break;
110
111 case MEMCACHED_BEHAVIOR_NO_BLOCK:
112 ptr->flags.no_block = bool(data);
113 send_quit(ptr);
114 break;
115
116 case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
117 if (memcached_is_udp(ptr)) {
118 return memcached_set_error(
119 *ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
120 memcached_literal_param("MEMCACHED_BEHAVIOR_BUFFER_REQUESTS cannot be set while "
121 "MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
122 }
123 ptr->flags.buffer_requests = bool(data);
124 send_quit(ptr);
125 break;
126
127 case MEMCACHED_BEHAVIOR_USE_UDP:
128 send_quit(
129 ptr); // We need t shutdown all of the connections to make sure we do the correct protocol
130 ptr->flags.use_udp = bool(data);
131 if (bool(data)) {
132 ptr->flags.reply = false;
133 ptr->flags.buffer_requests = false;
134 } else {
135 ptr->flags.reply = true;
136 }
137 break;
138
139 case MEMCACHED_BEHAVIOR_TCP_NODELAY:
140 ptr->flags.tcp_nodelay = bool(data);
141 send_quit(ptr);
142 break;
143
144 case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE:
145 ptr->flags.tcp_keepalive = bool(data);
146 send_quit(ptr);
147 break;
148
149 case MEMCACHED_BEHAVIOR_DISTRIBUTION:
150 return memcached_behavior_set_distribution(ptr, (memcached_server_distribution_t) data);
151
152 case MEMCACHED_BEHAVIOR_KETAMA: {
153 if (data) // Turn on
154 {
155 return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA);
156 }
157
158 return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_MODULA);
159 }
160
161 case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: {
162 if (bool(data) == false) {
163 return memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_KETAMA, true);
164 }
165
166 (void) memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5);
167 (void) memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5);
168 /**
169 @note We try to keep the same distribution going. This should be deprecated and rewritten.
170 */
171 return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED);
172 }
173
174 case MEMCACHED_BEHAVIOR_HASH:
175 return memcached_behavior_set_key_hash(ptr, (memcached_hash_t)(data));
176
177 case MEMCACHED_BEHAVIOR_KETAMA_HASH:
178 return memcached_behavior_set_distribution_hash(ptr, (memcached_hash_t)(data));
179
180 case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
181 return memcached_set_error(
182 *ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
183 memcached_literal_param("MEMCACHED_BEHAVIOR_CACHE_LOOKUPS has been deprecated."));
184
185 case MEMCACHED_BEHAVIOR_VERIFY_KEY:
186 if (ptr->flags.binary_protocol) {
187 return memcached_set_error(
188 *ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
189 memcached_literal_param(
190 "MEMCACHED_BEHAVIOR_VERIFY_KEY if the binary protocol has been enabled."));
191 }
192 ptr->flags.verify_key = bool(data);
193 break;
194
195 case MEMCACHED_BEHAVIOR_SORT_HOSTS: {
196 ptr->flags.use_sort_hosts = bool(data);
197 return run_distribution(ptr);
198 }
199
200 case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
201 ptr->poll_timeout = (int32_t) data;
202 break;
203
204 case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
205 ptr->connect_timeout = (int32_t) data;
206 break;
207
208 case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
209 ptr->retry_timeout = int32_t(data);
210 break;
211
212 case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
213 ptr->dead_timeout = int32_t(data);
214 break;
215
216 case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
217 ptr->send_size = (int32_t) data;
218 send_quit(ptr);
219 break;
220
221 case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
222 ptr->recv_size = (int32_t) data;
223 send_quit(ptr);
224 break;
225
226 case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE:
227 ptr->tcp_keepidle = (uint32_t) data;
228 send_quit(ptr);
229 break;
230
231 case MEMCACHED_BEHAVIOR_USER_DATA:
232 return memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
233 memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated."));
234
235 case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
236 ptr->flags.hash_with_namespace = bool(data);
237 break;
238
239 case MEMCACHED_BEHAVIOR_NOREPLY:
240 if (memcached_is_udp(ptr) and bool(data) == false) {
241 return memcached_set_error(
242 *ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
243 memcached_literal_param("MEMCACHED_BEHAVIOR_NOREPLY cannot be disabled while "
244 "MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
245 }
246 // We reverse the logic here to make it easier to understand throughout the
247 // code.
248 ptr->flags.reply = bool(data) ? false : true;
249 break;
250
251 case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
252 ptr->flags.auto_eject_hosts = bool(data);
253 break;
254
255 case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
256 srandom((uint32_t) time(NULL));
257 ptr->flags.randomize_replica_read = bool(data);
258 break;
259
260 case MEMCACHED_BEHAVIOR_CORK:
261 return memcached_set_error(
262 *ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
263 memcached_literal_param(
264 "MEMCACHED_BEHAVIOR_CORK is now incorporated into the driver by default."));
265
266 case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE:
267 return memcached_set_error(
268 *ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
269 memcached_literal_param(
270 "MEMCACHED_BEHAVIOR_LOAD_FROM_FILE can not be set with memcached_behavior_set()"));
271
272 case MEMCACHED_BEHAVIOR_MAX:
273 default:
274 /* Shouldn't get here */
275 assert_msg(0, "Invalid behavior passed to memcached_behavior_set()");
276 return memcached_set_error(
277 *ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
278 memcached_literal_param("Invalid behavior passed to memcached_behavior_set()"));
279 }
280
281 return MEMCACHED_SUCCESS;
282 }
283
284 bool _is_auto_eject_host(const memcached_st *ptr) {
285 return ptr->flags.auto_eject_hosts;
286 }
287
288 uint64_t memcached_behavior_get(memcached_st *shell, const memcached_behavior_t flag) {
289 Memcached *ptr = memcached2Memcached(shell);
290 if (ptr == NULL) {
291 return MEMCACHED_INVALID_ARGUMENTS;
292 }
293
294 switch (flag) {
295 case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
296 return ptr->number_of_replicas;
297
298 case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
299 return ptr->io_msg_watermark;
300
301 case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
302 return ptr->io_bytes_watermark;
303
304 case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
305 return ptr->io_key_prefetch;
306
307 case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
308 return ptr->flags.binary_protocol;
309
310 case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
311 return ptr->flags.support_cas;
312
313 case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
314 return true;
315
316 case MEMCACHED_BEHAVIOR_NO_BLOCK:
317 return ptr->flags.no_block;
318
319 case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
320 return ptr->flags.buffer_requests;
321
322 case MEMCACHED_BEHAVIOR_USE_UDP:
323 return memcached_is_udp(ptr);
324
325 case MEMCACHED_BEHAVIOR_TCP_NODELAY:
326 return ptr->flags.tcp_nodelay;
327
328 case MEMCACHED_BEHAVIOR_VERIFY_KEY:
329 return ptr->flags.verify_key;
330
331 case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
332 if (memcached_is_consistent_distribution(ptr)) {
333 return memcached_is_weighted_ketama(ptr);
334 }
335 return false;
336
337 case MEMCACHED_BEHAVIOR_DISTRIBUTION:
338 return ptr->distribution;
339
340 case MEMCACHED_BEHAVIOR_KETAMA:
341 return memcached_is_consistent_distribution(ptr);
342
343 case MEMCACHED_BEHAVIOR_HASH:
344 return hashkit_get_function(&ptr->hashkit);
345
346 case MEMCACHED_BEHAVIOR_KETAMA_HASH:
347 return hashkit_get_distribution_function(&ptr->hashkit);
348
349 case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS:
350 return ptr->flags.auto_eject_hosts;
351
352 case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
353 return ptr->server_failure_limit;
354
355 case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
356 return ptr->server_timeout_limit;
357
358 case MEMCACHED_BEHAVIOR_SORT_HOSTS:
359 return ptr->flags.use_sort_hosts;
360
361 case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
362 return (uint64_t) ptr->poll_timeout;
363
364 case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
365 return (uint64_t) ptr->connect_timeout;
366
367 case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
368 return (uint64_t) ptr->retry_timeout;
369
370 case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
371 return uint64_t(ptr->dead_timeout);
372
373 case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
374 return (uint64_t) ptr->snd_timeout;
375
376 case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
377 return (uint64_t) ptr->rcv_timeout;
378
379 case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE:
380 return (uint64_t) ptr->tcp_keepidle;
381
382 case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: {
383 int sock_size = 0;
384 socklen_t sock_length = sizeof(int);
385
386 if (ptr->send_size != -1) // If value is -1 then we are using the default
387 {
388 return (uint64_t) ptr->send_size;
389 }
390
391 memcached_instance_st *instance = memcached_instance_fetch(ptr, 0);
392
393 if (instance) // If we have an instance we test, otherwise we just set and pray
394 {
395 /* REFACTOR */
396 /* We just try the first host, and if it is down we return zero */
397 if (memcached_failed(memcached_connect(instance))) {
398 return 0;
399 }
400
401 if (memcached_failed(memcached_io_wait_for_write(instance))) {
402 return 0;
403 }
404
405 if (getsockopt(instance->fd, SOL_SOCKET, SO_SNDBUF, (char *) &sock_size, &sock_length) < 0) {
406 memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
407 return 0; /* Zero means error */
408 }
409 }
410
411 return (uint64_t) sock_size;
412 }
413
414 case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: {
415 int sock_size = 0;
416 socklen_t sock_length = sizeof(int);
417
418 if (ptr->recv_size != -1) // If value is -1 then we are using the default
419 return (uint64_t) ptr->recv_size;
420
421 memcached_instance_st *instance = memcached_instance_fetch(ptr, 0);
422
423 /**
424 @note REFACTOR
425 */
426 if (instance) {
427 /* We just try the first host, and if it is down we return zero */
428 if (memcached_failed(memcached_connect(instance))) {
429 return 0;
430 }
431
432 if (memcached_failed(memcached_io_wait_for_write(instance))) {
433 return 0;
434 }
435
436 if (getsockopt(instance->fd, SOL_SOCKET, SO_RCVBUF, (char *) &sock_size, &sock_length) < 0) {
437 memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
438 return 0; /* Zero means error */
439 }
440 }
441
442 return (uint64_t) sock_size;
443 }
444
445 case MEMCACHED_BEHAVIOR_USER_DATA:
446 memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
447 memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated."));
448 return 0;
449
450 case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
451 return ptr->flags.hash_with_namespace;
452
453 case MEMCACHED_BEHAVIOR_NOREPLY:
454 return ptr->flags.reply ? false : true;
455
456 case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
457 return ptr->flags.auto_eject_hosts;
458
459 case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
460 return ptr->flags.randomize_replica_read;
461
462 case MEMCACHED_BEHAVIOR_CORK:
463 #ifdef HAVE_MSG_MORE
464 return true;
465 #else
466 return false;
467 #endif
468
469 case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE:
470 return ptr->flags.tcp_keepalive;
471
472 case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE:
473 return bool(memcached_parse_filename(ptr));
474
475 case MEMCACHED_BEHAVIOR_MAX:
476 default:
477 assert_msg(0, "Invalid behavior passed to memcached_behavior_get()");
478 return 0;
479 }
480
481 /* NOTREACHED */
482 }
483
484 memcached_return_t memcached_behavior_set_distribution(memcached_st *shell,
485 memcached_server_distribution_t type) {
486 Memcached *ptr = memcached2Memcached(shell);
487 if (ptr) {
488 switch (type) {
489 case MEMCACHED_DISTRIBUTION_MODULA:
490 break;
491
492 case MEMCACHED_DISTRIBUTION_CONSISTENT:
493 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
494 memcached_set_weighted_ketama(ptr, false);
495 break;
496
497 case MEMCACHED_DISTRIBUTION_RANDOM:
498 break;
499
500 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
501 break;
502
503 case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
504 memcached_set_weighted_ketama(ptr, true);
505 break;
506
507 case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
508 break;
509
510 default:
511 case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
512 return memcached_set_error(
513 *ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
514 memcached_literal_param("Invalid memcached_server_distribution_t"));
515 }
516 ptr->distribution = type;
517
518 return run_distribution(ptr);
519 }
520
521 return MEMCACHED_INVALID_ARGUMENTS;
522 }
523
524 memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *shell) {
525 Memcached *ptr = memcached2Memcached(shell);
526 if (ptr) {
527 return ptr->distribution;
528 }
529
530 return MEMCACHED_DISTRIBUTION_CONSISTENT_MAX;
531 }
532
533 memcached_return_t memcached_behavior_set_key_hash(memcached_st *shell, memcached_hash_t type) {
534 Memcached *ptr = memcached2Memcached(shell);
535 if (ptr) {
536 if (hashkit_success(hashkit_set_function(&ptr->hashkit, (hashkit_hash_algorithm_t) type))) {
537 return MEMCACHED_SUCCESS;
538 }
539
540 return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
541 memcached_literal_param("Invalid memcached_hash_t()"));
542 }
543
544 return MEMCACHED_INVALID_ARGUMENTS;
545 }
546
547 memcached_hash_t memcached_behavior_get_key_hash(memcached_st *shell) {
548 Memcached *ptr = memcached2Memcached(shell);
549 if (ptr) {
550 return (memcached_hash_t) hashkit_get_function(&ptr->hashkit);
551 }
552
553 return MEMCACHED_HASH_MAX;
554 }
555
556 memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *shell,
557 memcached_hash_t type) {
558 Memcached *ptr = memcached2Memcached(shell);
559 if (ptr) {
560 if (hashkit_success(
561 hashkit_set_distribution_function(&ptr->hashkit, (hashkit_hash_algorithm_t) type)))
562 {
563 return MEMCACHED_SUCCESS;
564 }
565
566 return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
567 memcached_literal_param("Invalid memcached_hash_t()"));
568 }
569
570 return MEMCACHED_INVALID_ARGUMENTS;
571 }
572
573 memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *shell) {
574 Memcached *ptr = memcached2Memcached(shell);
575 if (ptr) {
576 return (memcached_hash_t) hashkit_get_function(&ptr->hashkit);
577 }
578
579 return MEMCACHED_HASH_MAX;
580 }
581
582 const char *libmemcached_string_behavior(const memcached_behavior_t flag) {
583 switch (flag) {
584 case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
585 return "MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT";
586 case MEMCACHED_BEHAVIOR_NO_BLOCK:
587 return "MEMCACHED_BEHAVIOR_NO_BLOCK";
588 case MEMCACHED_BEHAVIOR_TCP_NODELAY:
589 return "MEMCACHED_BEHAVIOR_TCP_NODELAY";
590 case MEMCACHED_BEHAVIOR_HASH:
591 return "MEMCACHED_BEHAVIOR_HASH";
592 case MEMCACHED_BEHAVIOR_KETAMA:
593 return "MEMCACHED_BEHAVIOR_KETAMA";
594 case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
595 return "MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE";
596 case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
597 return "MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE";
598 case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
599 return "MEMCACHED_BEHAVIOR_CACHE_LOOKUPS";
600 case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
601 return "MEMCACHED_BEHAVIOR_SUPPORT_CAS";
602 case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
603 return "MEMCACHED_BEHAVIOR_POLL_TIMEOUT";
604 case MEMCACHED_BEHAVIOR_DISTRIBUTION:
605 return "MEMCACHED_BEHAVIOR_DISTRIBUTION";
606 case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
607 return "MEMCACHED_BEHAVIOR_BUFFER_REQUESTS";
608 case MEMCACHED_BEHAVIOR_USER_DATA:
609 return "MEMCACHED_BEHAVIOR_USER_DATA";
610 case MEMCACHED_BEHAVIOR_SORT_HOSTS:
611 return "MEMCACHED_BEHAVIOR_SORT_HOSTS";
612 case MEMCACHED_BEHAVIOR_VERIFY_KEY:
613 return "MEMCACHED_BEHAVIOR_VERIFY_KEY";
614 case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
615 return "MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT";
616 case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
617 return "MEMCACHED_BEHAVIOR_RETRY_TIMEOUT";
618 case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
619 return "MEMCACHED_BEHAVIOR_DEAD_TIMEOUT";
620 case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
621 return "MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED";
622 case MEMCACHED_BEHAVIOR_KETAMA_HASH:
623 return "MEMCACHED_BEHAVIOR_KETAMA_HASH";
624 case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
625 return "MEMCACHED_BEHAVIOR_BINARY_PROTOCOL";
626 case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
627 return "MEMCACHED_BEHAVIOR_SND_TIMEOUT";
628 case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
629 return "MEMCACHED_BEHAVIOR_RCV_TIMEOUT";
630 case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
631 return "MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT";
632 case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
633 return "MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK";
634 case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
635 return "MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK";
636 case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
637 return "MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH";
638 case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
639 return "MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY";
640 case MEMCACHED_BEHAVIOR_NOREPLY:
641 return "MEMCACHED_BEHAVIOR_NOREPLY";
642 case MEMCACHED_BEHAVIOR_USE_UDP:
643 return "MEMCACHED_BEHAVIOR_USE_UDP";
644 case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
645 return "MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS";
646 case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS:
647 return "MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS";
648 case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
649 return "MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS";
650 case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
651 return "MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ";
652 case MEMCACHED_BEHAVIOR_CORK:
653 return "MEMCACHED_BEHAVIOR_CORK";
654 case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE:
655 return "MEMCACHED_BEHAVIOR_TCP_KEEPALIVE";
656 case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE:
657 return "MEMCACHED_BEHAVIOR_TCP_KEEPIDLE";
658 case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE:
659 return "MEMCACHED_BEHAVIOR_LOAD_FROM_FILE";
660 default:
661 case MEMCACHED_BEHAVIOR_MAX:
662 return "INVALID memcached_behavior_t";
663 }
664 }
665
666 const char *libmemcached_string_distribution(const memcached_server_distribution_t flag) {
667 switch (flag) {
668 case MEMCACHED_DISTRIBUTION_MODULA:
669 return "MEMCACHED_DISTRIBUTION_MODULA";
670 case MEMCACHED_DISTRIBUTION_CONSISTENT:
671 return "MEMCACHED_DISTRIBUTION_CONSISTENT";
672 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
673 return "MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA";
674 case MEMCACHED_DISTRIBUTION_RANDOM:
675 return "MEMCACHED_DISTRIBUTION_RANDOM";
676 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
677 return "MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY";
678 case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
679 return "MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED";
680 case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
681 return "MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET";
682 default:
683 case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
684 return "INVALID memcached_server_distribution_t";
685 }
686 }
687
688 memcached_return_t memcached_bucket_set(memcached_st *shell, const uint32_t *host_map,
689 const uint32_t *forward_map, const uint32_t buckets,
690 const uint32_t replicas) {
691 Memcached *self = memcached2Memcached(shell);
692 memcached_return_t rc;
693
694 if (self == NULL) {
695 return MEMCACHED_INVALID_ARGUMENTS;
696 }
697
698 if (host_map == NULL) {
699 return MEMCACHED_INVALID_ARGUMENTS;
700 }
701
702 memcached_server_distribution_t old = memcached_behavior_get_distribution(self);
703
704 if (memcached_failed(
705 rc = memcached_behavior_set_distribution(self, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET)))
706 {
707 return rc;
708 }
709
710 if (memcached_failed(
711 rc = memcached_virtual_bucket_create(self, host_map, forward_map, buckets, replicas)))
712 {
713 memcached_behavior_set_distribution(self, old);
714 }
715
716 return rc;
717 }