size_t ConsistentHashingLoadBalancer::AddServersInBatch( const std::vector<ServerId> &servers) { std::vector<Node> add_nodes; add_nodes.reserve(servers.size() * _num_replicas); for (size_t i = 0; i < servers.size(); ++i) { SocketUniquePtr ptr; if (Socket::AddressFailedAsWell(servers[i].id, &ptr) == -1) { continue; } for (size_t rep = 0; rep < _num_replicas; ++rep) { char host[32]; // To be compatible with libmemcached, we formulate the key of // a virtual node as `|address|-|replica_index|', see // http://fe.baidu.com/-1bszwnf at line 297. int len = snprintf(host, sizeof(host), "%s-%lu", endpoint2str(ptr->remote_side()).c_str(), rep); Node node; node.hash = _hash(host, len); node.server_sock = servers[i]; node.server_addr = ptr->remote_side(); add_nodes.push_back(node); } } std::sort(add_nodes.begin(), add_nodes.end()); bool executed = false; const size_t ret = _db_hash_ring.ModifyWithForeground(AddBatch, add_nodes, &executed); CHECK(ret % _num_replicas == 0); const size_t n = ret / _num_replicas; LOG_IF(ERROR, n != servers.size()) << "Fail to AddServersInBatch, expected " << servers.size() << " actually " << n; return n; }
bool ConsistentHashingLoadBalancer::AddServer(const ServerId& server) { std::vector<Node> add_nodes; add_nodes.reserve(_num_replicas); SocketUniquePtr ptr; if (Socket::AddressFailedAsWell(server.id, &ptr) == -1) { return false; } for (size_t i = 0; i < _num_replicas; ++i) { char host[32]; int len = snprintf(host, sizeof(host), "%s-%lu", endpoint2str(ptr->remote_side()).c_str(), i); Node node; node.hash = _hash(host, len); node.server_sock = server; node.server_addr = ptr->remote_side(); add_nodes.push_back(node); } std::sort(add_nodes.begin(), add_nodes.end()); bool executed = false; const size_t ret = _db_hash_ring.ModifyWithForeground( AddBatch, add_nodes, &executed); CHECK(ret == 0 || ret == _num_replicas) << ret; return ret != 0; }