void addServerToPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server);
void removeServerFromPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server);
-ServerPolicy::NumberedServerVector getDownstreamCandidates(const map<std::string,std::shared_ptr<ServerPool>>& pools, const std::string& poolName);
+const std::shared_ptr<ServerPolicy::NumberedServerVector> getDownstreamCandidates(const map<std::string,std::shared_ptr<ServerPool>>& pools, const std::string& poolName);
std::shared_ptr<DownstreamState> firstAvailable(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq);
});
g_lua.writeFunction("getPoolServers", [](string pool) {
- return getDownstreamCandidates(g_pools.getCopy(), pool);
+ const auto poolServers = getDownstreamCandidates(g_pools.getCopy(), pool);
+ return *poolServers;
});
g_lua.writeFunction("getServer", [client](boost::variant<unsigned int, std::string> i) {
}
string servers;
- for (const auto& server: pool->getServers()) {
+ const auto poolServers = pool->getServers();
+ for (const auto& server: *poolServers) {
if (!servers.empty()) {
servers += ", ";
}
if (serverPool->policy != nullptr) {
policy = *(serverPool->policy);
}
- auto servers = serverPool->getServers();
- selectedBackend = getSelectedBackendFromPolicy(policy, servers, dq);
+ const auto servers = serverPool->getServers();
+ selectedBackend = getSelectedBackendFromPolicy(policy, *servers, dq);
uint16_t cachedResponseSize = dq.size;
uint32_t allowExpired = selectedBackend ? 0 : g_staleCacheEntriesTTL;
struct ServerPool
{
- ServerPool()
+ ServerPool(): d_servers(std::make_shared<ServerPolicy::NumberedServerVector>())
{
}
+
~ServerPool()
{
}
{
size_t count = 0;
ReadLock rl(&d_lock);
- for (const auto& server : d_servers) {
+ for (const auto& server : *d_servers) {
if (!upOnly || std::get<1>(server)->isUp() ) {
count++;
}
return count;
}
- ServerPolicy::NumberedServerVector getServers()
+ const std::shared_ptr<ServerPolicy::NumberedServerVector> getServers()
{
- ServerPolicy::NumberedServerVector result;
+ std::shared_ptr<ServerPolicy::NumberedServerVector> result;
{
ReadLock rl(&d_lock);
result = d_servers;
void addServer(shared_ptr<DownstreamState>& server)
{
WriteLock wl(&d_lock);
- unsigned int count = (unsigned int) d_servers.size();
- d_servers.push_back(make_pair(++count, server));
+ /* we can't update the content of the shared pointer directly even when holding the lock,
+ as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */
+ unsigned int count = static_cast<unsigned int>(d_servers->size());
+ auto newServers = std::make_shared<ServerPolicy::NumberedServerVector>(*d_servers);
+ newServers->push_back(make_pair(++count, server));
/* we need to reorder based on the server 'order' */
- std::stable_sort(d_servers.begin(), d_servers.end(), [](const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& a, const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& b) {
+ std::stable_sort(newServers->begin(), newServers->end(), [](const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& a, const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& b) {
return a.second->order < b.second->order;
});
/* and now we need to renumber for Lua (custom policies) */
size_t idx = 1;
- for (auto& serv : d_servers) {
+ for (auto& serv : *newServers) {
serv.first = idx++;
}
+ d_servers = newServers;
}
void removeServer(shared_ptr<DownstreamState>& server)
{
WriteLock wl(&d_lock);
+ /* we can't update the content of the shared pointer directly even when holding the lock,
+ as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */
+ auto newServers = std::make_shared<ServerPolicy::NumberedServerVector>(*d_servers);
size_t idx = 1;
bool found = false;
- for (auto it = d_servers.begin(); it != d_servers.end();) {
+ for (auto it = newServers->begin(); it != newServers->end();) {
if (found) {
/* we need to renumber the servers placed
after the removed one, for Lua (custom policies) */
it++;
}
else if (it->second == server) {
- it = d_servers.erase(it);
+ it = newServers->erase(it);
found = true;
} else {
idx++;
it++;
}
}
+ d_servers = newServers;
}
private:
- ServerPolicy::NumberedServerVector d_servers;
+ std::shared_ptr<ServerPolicy::NumberedServerVector> d_servers;
ReadWriteLock d_lock;
bool d_useECS{false};
};