}
const string base = "dnsdist." + hostname + ".main.pools." + poolName + ".";
const std::shared_ptr<ServerPool> pool = entry.second;
- str<<base<<"servers" << " " << pool->servers.size() << " " << now << "\r\n";
- str<<base<<"servers-up" << " " << pool->countServersUp() << " " << now << "\r\n";
+ str<<base<<"servers" << " " << pool->countServers(false) << " " << now << "\r\n";
+ str<<base<<"servers-up" << " " << pool->countServers(true) << " " << now << "\r\n";
if (pool->packetCache != nullptr) {
const auto& cache = pool->packetCache;
str<<base<<"cache-size" << " " << cache->getMaxEntries() << " " << now << "\r\n";
});
/* ServerPolicy */
- g_lua.writeFunction("newServerPolicy", [](string name, policyfunc_t policy) { return ServerPolicy{name, policy};});
+ g_lua.writeFunction("newServerPolicy", [](string name, policyfunc_t policy) { return ServerPolicy{name, policy, true};});
g_lua.registerMember("name", &ServerPolicy::name);
g_lua.registerMember("policy", &ServerPolicy::policy);
+ g_lua.registerMember("isLua", &ServerPolicy::isLua);
- g_lua.writeVariable("firstAvailable", ServerPolicy{"firstAvailable", firstAvailable});
- g_lua.writeVariable("roundrobin", ServerPolicy{"roundrobin", roundrobin});
- g_lua.writeVariable("wrandom", ServerPolicy{"wrandom", wrandom});
- g_lua.writeVariable("whashed", ServerPolicy{"whashed", whashed});
- g_lua.writeVariable("leastOutstanding", ServerPolicy{"leastOutstanding", leastOutstanding});
+ g_lua.writeVariable("firstAvailable", ServerPolicy{"firstAvailable", firstAvailable, false});
+ g_lua.writeVariable("roundrobin", ServerPolicy{"roundrobin", roundrobin, false});
+ g_lua.writeVariable("wrandom", ServerPolicy{"wrandom", wrandom, false});
+ g_lua.writeVariable("whashed", ServerPolicy{"whashed", whashed, false});
+ g_lua.writeVariable("leastOutstanding", ServerPolicy{"leastOutstanding", leastOutstanding, false});
/* ServerPool */
g_lua.registerFunction<void(std::shared_ptr<ServerPool>::*)(std::shared_ptr<DNSDistPacketCache>)>("setCache", [](std::shared_ptr<ServerPool> pool, std::shared_ptr<DNSDistPacketCache> cache) {
});
g_lua.writeFunction("setServerPolicyLua", [](string name, policyfunc_t policy) {
setLuaSideEffect();
- g_policy.setState(ServerPolicy{name, policy});
+ g_policy.setState(ServerPolicy{name, policy, true});
});
g_lua.writeFunction("showServerPolicy", []() {
}
string servers;
- for (const auto& server: pool->servers) {
+ for (const auto& server: pool->getServers()) {
if (!servers.empty()) {
servers += ", ";
}
g_lua.writeFunction("setPoolServerPolicyLua", [](string name, policyfunc_t policy, string pool) {
setLuaSideEffect();
auto localPools = g_pools.getCopy();
- setPoolPolicy(localPools, pool, std::make_shared<ServerPolicy>(ServerPolicy{name, policy}));
+ setPoolPolicy(localPools, pool, std::make_shared<ServerPolicy>(ServerPolicy{name, policy, true}));
g_pools.setState(localPools);
});
}
std::shared_ptr<ServerPool> serverPool = getPool(*holders.pools, poolname);
- std::shared_ptr<DNSDistPacketCache> packetCache = nullptr;
- auto policy = holders.policy->policy;
+ std::shared_ptr<DNSDistPacketCache> packetCache = serverPool->packetCache;
+
+ auto policy = *(holders.policy);
if (serverPool->policy != nullptr) {
- policy = serverPool->policy->policy;
+ policy = *(serverPool->policy);
}
- {
+ auto servers = serverPool->getServers();
+ if (policy.isLua) {
std::lock_guard<std::mutex> lock(g_luamutex);
- ds = policy(serverPool->servers, &dq);
- packetCache = serverPool->packetCache;
+ ds = policy.policy(servers, &dq);
+ }
+ else {
+ ds = policy.policy(servers, &dq);
}
if (dq.useECS && ds && ds->useECS) {
Json::object entry {
{ "id", num++ },
{ "name", pool.first },
- { "serversCount", (int) pool.second->servers.size() },
+ { "serversCount", (int) pool.second->countServers(false) },
{ "cacheSize", (double) (cache ? cache->getMaxEntries() : 0) },
{ "cacheEntries", (double) (cache ? cache->getEntriesCount() : 0) },
{ "cacheHits", (double) (cache ? cache->getHits() : 0) },
void addServerToPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server)
{
std::shared_ptr<ServerPool> pool = createPoolIfNotExists(pools, poolName);
- unsigned int count = (unsigned int) pool->servers.size();
if (!poolName.empty()) {
vinfolog("Adding server to pool %s", poolName);
} else {
vinfolog("Adding server to default pool");
}
- pool->servers.push_back(make_pair(++count, server));
- /* we need to reorder based on the server 'order' */
- std::stable_sort(pool->servers.begin(), pool->servers.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 : pool->servers) {
- serv.first = idx++;
- }
+ pool->addServer(server);
}
void removeServerFromPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server)
vinfolog("Removing server from default pool");
}
- size_t idx = 1;
- bool found = false;
- for (NumberedVector<shared_ptr<DownstreamState> >::iterator it = pool->servers.begin(); it != pool->servers.end();) {
- if (found) {
- /* we need to renumber the servers placed
- after the removed one, for Lua (custom policies) */
- it->first = idx++;
- it++;
- }
- else if (it->second == server) {
- it = pool->servers.erase(it);
- found = true;
- } else {
- idx++;
- it++;
- }
- }
+ pool->removeServer(server);
}
std::shared_ptr<ServerPool> getPool(const pools_t& pools, const std::string& poolName)
return it->second;
}
-const NumberedServerVector& getDownstreamCandidates(const pools_t& pools, const std::string& poolName)
+NumberedServerVector getDownstreamCandidates(const pools_t& pools, const std::string& poolName)
{
std::shared_ptr<ServerPool> pool = getPool(pools, poolName);
- return pool->servers;
+ return pool->getServers();
}
// goal in life - if you send us a reasonably normal packet, we'll get Z for you, otherwise 0
DownstreamState* ss = nullptr;
std::shared_ptr<ServerPool> serverPool = getPool(*holders.pools, poolname);
- std::shared_ptr<DNSDistPacketCache> packetCache = nullptr;
- auto policy = holders.policy->policy;
+ std::shared_ptr<DNSDistPacketCache> packetCache = serverPool->packetCache;
+ auto policy = *(holders.policy);
if (serverPool->policy != nullptr) {
- policy = serverPool->policy->policy;
+ policy = *(serverPool->policy);
}
- {
+ auto servers = serverPool->getServers();
+ if (policy.isLua) {
std::lock_guard<std::mutex> lock(g_luamutex);
- ss = policy(serverPool->servers, &dq).get();
- packetCache = serverPool->packetCache;
+ ss = policy.policy(servers, &dq).get();
+ }
+ else {
+ ss = policy.policy(servers, &dq).get();
}
bool ednsAdded = false;
const auto localPools = g_pools.getCopy();
std::shared_ptr<DNSDistPacketCache> packetCache = nullptr;
for (const auto& entry : localPools) {
- {
- std::lock_guard<std::mutex> lock(g_luamutex);
- packetCache = entry.second->packetCache;
- }
+ packetCache = entry.second->packetCache;
if (packetCache) {
size_t upTo = (packetCache->getMaxEntries()* (100 - g_cacheCleaningPercentage)) / 100;
packetCache->purgeExpired(upTo);
}
}
- ServerPolicy leastOutstandingPol{"leastOutstanding", leastOutstanding};
+ ServerPolicy leastOutstandingPol{"leastOutstanding", leastOutstanding, false};
g_policy.setState(leastOutstandingPol);
if(g_cmdLine.beClient || !g_cmdLine.command.empty()) {
{
string name;
policyfunc_t policy;
+ bool isLua;
};
struct ServerPool
{
+ ServerPool()
+ {
+ pthread_rwlock_init(&d_lock, nullptr);
+ }
+
const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
- NumberedVector<shared_ptr<DownstreamState>> servers;
std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
std::shared_ptr<ServerPolicy> policy{nullptr};
- size_t countServersUp() const {
- size_t upFound = 0;
- for (const auto& server : servers) {
- if (std::get<1>(server)->isUp() ) {
- upFound++;
+ size_t countServers(bool upOnly)
+ {
+ size_t count = 0;
+ ReadLock rl(&d_lock);
+ for (const auto& server : d_servers) {
+ if (!upOnly || std::get<1>(server)->isUp() ) {
+ count++;
};
};
- return upFound;
- };
+ return count;
+ }
+
+ NumberedVector<shared_ptr<DownstreamState>> getServers()
+ {
+ NumberedVector<shared_ptr<DownstreamState>> result;
+ {
+ ReadLock rl(&d_lock);
+ result = d_servers;
+ }
+ return result;
+ }
+
+ 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 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) {
+ 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) {
+ serv.first = idx++;
+ }
+ }
+
+ void removeServer(shared_ptr<DownstreamState>& server)
+ {
+ WriteLock wl(&d_lock);
+ size_t idx = 1;
+ bool found = false;
+ for (auto it = d_servers.begin(); it != d_servers.end();) {
+ if (found) {
+ /* we need to renumber the servers placed
+ after the removed one, for Lua (custom policies) */
+ it->first = idx++;
+ it++;
+ }
+ else if (it->second == server) {
+ it = d_servers.erase(it);
+ found = true;
+ } else {
+ idx++;
+ it++;
+ }
+ }
+ }
+
+private:
+ NumberedVector<shared_ptr<DownstreamState>> d_servers;
+ pthread_rwlock_t d_lock;
};
using pools_t=map<std::string,std::shared_ptr<ServerPool>>;
void setPoolPolicy(pools_t& pools, const string& poolName, std::shared_ptr<ServerPolicy> policy);
vector<std::function<void(void)>> setupLua(bool client, const std::string& config);
std::shared_ptr<ServerPool> getPool(const pools_t& pools, const std::string& poolName);
std::shared_ptr<ServerPool> createPoolIfNotExists(pools_t& pools, const string& poolName);
-const NumberedServerVector& getDownstreamCandidates(const pools_t& pools, const std::string& poolName);
+NumberedServerVector getDownstreamCandidates(const pools_t& pools, const std::string& poolName);
std::shared_ptr<DownstreamState> firstAvailable(const NumberedServerVector& servers, const DNSQuestion* dq);