}
#endif
+struct speedOrderCA
+{
+ speedOrderCA(std::map<ComboAddress,double>& speeds): d_speeds(speeds) {}
+ bool operator()(const ComboAddress& a, const ComboAddress& b) const
+ {
+ return d_speeds[a] < d_speeds[b];
+ }
+ std::map<ComboAddress, double>& d_speeds;
+};
+
/** This function explicitly goes out for A or AAAA addresses
*/
vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere)
d_DNSSECValidationRequested = oldValidationRequested;
if(ret.size() > 1) {
- random_shuffle(ret.begin(), ret.end(), dns_random);
+ map<ComboAddress, double> speeds;
- // move 'best' address for this nameserver name up front
- nsspeeds_t::iterator best = t_sstorage.nsSpeeds.find(qname);
+ auto& collection = t_sstorage.nsSpeeds[qname].d_collection;
+ for(const auto& val: ret) {
+ double speed;
+ speed=collection[val].get(&d_now);
+ speeds[val]=speed;
+ }
- if(best != t_sstorage.nsSpeeds.end())
- for(ret_t::iterator i=ret.begin(); i != ret.end(); ++i) {
- if(*i==best->second.d_best) { // got the fastest one
- if(i!=ret.begin()) {
- *i=*ret.begin();
- *ret.begin()=best->second.d_best;
- }
- break;
+ t_sstorage.nsSpeeds[qname].purge(speeds);
+
+ random_shuffle(ret.begin(), ret.end(), dns_random);
+ speedOrderCA so(speeds);
+ stable_sort(ret.begin(), ret.end(), so);
+
+ if(doLog()) {
+ string prefix=d_prefix;
+ prefix.append(depth, ' ');
+ LOG(prefix<<"Nameserver "<<qname<<" IPs: ");
+ bool first = true;
+ for(const auto& addr : ret) {
+ if (first) {
+ first = false;
}
+ else {
+ LOG(", ");
+ }
+ LOG((addr.toString())<<"(" << (boost::format("%0.2f") % (speeds[addr]/1000.0)).str() <<"ms)");
}
+ LOG(endl);
+ }
}
return ret;
{
void submit(const ComboAddress& remote, int usecs, const struct timeval* now)
{
- collection_t::iterator pos;
- for(pos=d_collection.begin(); pos != d_collection.end(); ++pos)
- if(pos->first==remote)
- break;
- if(pos!=d_collection.end()) {
- pos->second.submit(usecs, now);
- }
- else {
- DecayingEwma de;
- de.submit(usecs, now);
- d_collection.push_back(make_pair(remote, de));
- }
+ d_collection[remote].submit(usecs, now);
}
double get(const struct timeval* now)
return 0;
double ret=std::numeric_limits<double>::max();
double tmp;
- for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) {
- if((tmp=pos->second.get(now)) < ret) {
+ for (auto& entry : d_collection) {
+ if((tmp = entry.second.get(now)) < ret) {
ret=tmp;
- d_best=pos->first;
+ d_best=entry.first;
}
}
bool stale(time_t limit) const
{
- for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos)
- if(!pos->second.stale(limit))
+ for(const auto& entry : d_collection)
+ if(!entry.second.stale(limit))
return false;
return true;
}
- typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
+ void purge(const std::map<ComboAddress, double>& keep)
+ {
+ for (auto iter = d_collection.begin(); iter != d_collection.end(); ) {
+ if (keep.find(iter->first) != keep.end()) {
+ ++iter;
+ }
+ else {
+ iter = d_collection.erase(iter);
+ }
+ }
+ }
+
+ typedef std::map<ComboAddress, DecayingEwma> collection_t;
collection_t d_collection;
ComboAddress d_best;
};