3fec19c6a310e03d82ad20f26808e70192294fe2
[awesomized/libmemcached] / test / tests / memcached / ketama.cpp
1 #include "test/lib/common.hpp"
2 #include "test/lib/MemcachedCluster.hpp"
3
4 #include "testing/fixtures/ketama.hpp"
5
6 #include "libmemcached/continuum.hpp"
7 #include "libmemcached/instance.hpp"
8
9 DECLARE_STREQUAL;
10
11 TEST_CASE("memcached_ketama_compat") {
12 auto test = MemcachedCluster::network();
13 auto memc = &test.memc;
14
15 REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1));
16 REQUIRE(uint64_t(1) == memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED));
17
18 SECTION("generate hash") {
19 REQUIRE_SUCCESS(memcached_behavior_set_distribution(memc, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA));
20 REQUIRE(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA == memcached_behavior_get_distribution(memc));
21
22 memcached_server_st *server_pool = memcached_servers_parse(
23 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
24 );
25 memcached_servers_reset(memc);
26 memcached_server_push(memc, server_pool);
27
28 /* verify that the server list was parsed okay. */
29 REQUIRE(8U == memcached_server_count(memc));
30 REQUIRE(strequal(server_pool[0].hostname, "10.0.1.1"));
31 REQUIRE(in_port_t(11211) == server_pool[0].port);
32 REQUIRE(600U == server_pool[0].weight);
33 REQUIRE(strequal(server_pool[2].hostname, "10.0.1.3"));
34 REQUIRE(in_port_t(11211) == server_pool[2].port);
35 REQUIRE(200U == server_pool[2].weight);
36 REQUIRE(strequal(server_pool[7].hostname, "10.0.1.8"));
37 REQUIRE(in_port_t(11211) == server_pool[7].port);
38 REQUIRE(100U == server_pool[7].weight);
39
40 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
41 * us test the boundary wraparound.
42 */
43 REQUIRE(memcached_generate_hash(memc, (char *) "VDEAAAAA", 8) == memc->ketama.continuum[0].index);
44
45 /* verify the standard ketama set. */
46 for (uint32_t x = 0; x < 99; x++) {
47 uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
48 const memcached_instance_st *instance =
49 memcached_server_instance_by_position(memc, server_idx);
50 const char *hostname = memcached_server_name(instance);
51
52 REQUIRE(strequal(hostname, ketama_test_cases[x].server));
53 }
54
55 memcached_server_list_free(server_pool);
56 }
57
58 SECTION("user bug 18") {
59
60 REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, MEMCACHED_HASH_MD5));
61 REQUIRE(MEMCACHED_HASH_MD5 == memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH));
62
63 memcached_server_st *server_pool = memcached_servers_parse(
64 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
65 );
66 memcached_servers_reset(memc);
67 memcached_server_push(memc, server_pool);
68
69 /* verify that the server list was parsed okay. */
70 REQUIRE(memcached_server_count(memc) == 8);
71 REQUIRE(strequal(server_pool[0].hostname, "10.0.1.1"));
72 REQUIRE(server_pool[0].port == 11211);
73 REQUIRE(server_pool[0].weight == 600);
74 REQUIRE(strequal(server_pool[2].hostname, "10.0.1.3"));
75 REQUIRE(server_pool[2].port == 11211);
76 REQUIRE(server_pool[2].weight == 200);
77 REQUIRE(strequal(server_pool[7].hostname, "10.0.1.8"));
78 REQUIRE(server_pool[7].port == 11211);
79 REQUIRE(server_pool[7].weight == 100);
80
81 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
82 * us test the boundary wraparound.
83 */
84 REQUIRE(memcached_generate_hash(memc, (char *) "VDEAAAAA", 8) == memc->ketama.continuum[0].index);
85
86 /* verify the standard ketama set. */
87 for (auto x = 0; x < 99; x++) {
88 uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
89
90 const memcached_instance_st *instance =
91 memcached_server_instance_by_position(memc, server_idx);
92
93 const char *hostname = memcached_server_name(instance);
94 REQUIRE(strequal(hostname, ketama_test_cases[x].server));
95 }
96
97 memcached_server_list_free(server_pool);
98 }
99
100 SECTION("auto_eject_hosts") {
101 memcached_servers_reset(memc);
102
103 REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, MEMCACHED_HASH_MD5));
104 REQUIRE(MEMCACHED_HASH_MD5 == memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH));
105
106 /* server should be removed when in delay */
107 REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS, 1));
108 REQUIRE(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS));
109
110 memcached_server_st *server_pool;
111 server_pool = memcached_servers_parse(
112 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
113 );
114 memcached_servers_reset(memc);
115 memcached_server_push(memc, server_pool);
116
117 /* verify that the server list was parsed okay. */
118 REQUIRE(memcached_server_count(memc) == 8);
119 REQUIRE(strequal(server_pool[0].hostname, "10.0.1.1"));
120 REQUIRE(server_pool[0].port == 11211);
121 REQUIRE(server_pool[0].weight == 600);
122 REQUIRE(strequal(server_pool[2].hostname, "10.0.1.3"));
123 REQUIRE(server_pool[2].port == 11211);
124 REQUIRE(server_pool[2].weight == 200);
125 REQUIRE(strequal(server_pool[7].hostname, "10.0.1.8"));
126 REQUIRE(server_pool[7].port == 11211);
127 REQUIRE(server_pool[7].weight == 100);
128
129 const memcached_instance_st *instance = memcached_server_instance_by_position(memc, 2);
130 memcached_instance_next_retry(instance, time(nullptr) + 15);
131 memc->ketama.next_distribution_rebuild = time(nullptr) - 1;
132
133 /*
134 This would not work if there were only two hosts.
135 */
136 for (auto x = 0; x < 99; x++) {
137 memcached_autoeject(memc);
138 uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
139 REQUIRE(server_idx != 2);
140 }
141
142 /* and re-added when it's back. */
143 time_t absolute_time = time(nullptr) - 1;
144 memcached_instance_next_retry(instance, absolute_time);
145 memc->ketama.next_distribution_rebuild = absolute_time;
146 memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, memc->distribution);
147 for (auto x = 0; x < 99; x++) {
148 uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
149 // We re-use instance from above.
150 instance = memcached_server_instance_by_position(memc, server_idx);
151 const char *hostname = memcached_server_name(instance);
152 REQUIRE(strequal(hostname, ketama_test_cases[x].server));
153 }
154
155 memcached_server_list_free(server_pool);
156 }
157
158 SECTION("spymemcached") {
159 memcached_servers_reset(memc);
160 REQUIRE_SUCCESS(memcached_behavior_set_distribution(memc, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY));
161 REQUIRE(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY == memcached_behavior_get_distribution(memc));
162
163 memcached_server_st *server_pool = memcached_servers_parse(
164 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
165 );
166 REQUIRE(server_pool);
167 memcached_server_push(memc, server_pool);
168
169 /* verify that the server list was parsed okay. */
170 REQUIRE(8U == memcached_server_count(memc));
171 REQUIRE(strequal(server_pool[0].hostname, "10.0.1.1"));
172 REQUIRE(in_port_t(11211) == server_pool[0].port);
173 REQUIRE(600U == server_pool[0].weight);
174 REQUIRE(strequal(server_pool[2].hostname, "10.0.1.3"));
175 REQUIRE(in_port_t(11211) == server_pool[2].port);
176 REQUIRE(200U == server_pool[2].weight);
177 REQUIRE(strequal(server_pool[7].hostname, "10.0.1.8"));
178 REQUIRE(in_port_t(11211) == server_pool[7].port);
179 REQUIRE(100U == server_pool[7].weight);
180
181 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
182 * us test the boundary wraparound.
183 */
184 REQUIRE(memcached_generate_hash(memc, (char *) "VDEAAAAA", 8) == memc->ketama.continuum[0].index);
185
186 /* verify the standard ketama set. */
187 for (uint32_t x = 0; x < 99; x++) {
188 uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases_spy[x].key,
189 strlen(ketama_test_cases_spy[x].key));
190
191 const memcached_instance_st *instance =
192 memcached_server_instance_by_position(memc, server_idx);
193
194 const char *hostname = memcached_server_name(instance);
195 REQUIRE(strequal(hostname, ketama_test_cases_spy[x].server));
196 }
197
198 memcached_server_list_free(server_pool);
199 }
200 }