• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

PowerDNS / pdns / 18743945403

23 Oct 2025 09:29AM UTC coverage: 65.845% (+0.02%) from 65.829%
18743945403

Pull #16356

github

web-flow
Merge 8a2027ef1 into efa3637e8
Pull Request #16356: auth 5.0: backport "pdnsutil: fix b2b-migrate to from sql to non-sql"

42073 of 92452 branches covered (45.51%)

Branch coverage included in aggregate %.

128008 of 165855 relevant lines covered (77.18%)

6379935.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.12
/pdns/recursordist/rec-nsspeeds.hh
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#pragma once
23

24
#include <boost/multi_index_container.hpp>
25
#include <boost/multi_index/ordered_index.hpp>
26
#include <boost/multi_index/hashed_index.hpp>
27
#include <boost/multi_index/key_extractors.hpp>
28
#include <boost/multi_index/sequenced_index.hpp>
29

30
#include "iputils.hh"
31

32
using namespace ::boost::multi_index;
33

34
/** Class that implements a decaying EWMA.
35
    This class keeps an exponentially weighted moving average which, additionally, decays over time.
36
    The decaying is only done on get.
37
*/
38

39
//! This represents a number of decaying Ewmas, used to store performance per nameserver-name.
40
/** Modelled to work mostly like the underlying DecayingEwma */
41
class DecayingEwmaCollection
42
{
43
private:
44
  struct DecayingEwma
45
  {
46
  public:
47
    void submit(int arg, const struct timeval& last, const struct timeval& now)
48
    {
12,975✔
49
      d_last = arg;
12,975✔
50
      auto val = static_cast<float>(arg);
12,975✔
51
      if (d_val == 0) {
12,975✔
52
        d_val = val;
6,009✔
53
      }
6,009✔
54
      else {
6,966✔
55
        auto diff = makeFloat(last - now);
6,966✔
56
        auto factor = expf(diff) / 2.0F; // might be '0.5', or 0.0001
6,966✔
57
        d_val = (1.0F - factor) * val + factor * d_val;
6,966✔
58
      }
6,966✔
59
    }
12,975✔
60

61
    float get(float factor)
62
    {
55,832✔
63
      return d_val *= factor;
55,832✔
64
    }
55,832✔
65

66
    [[nodiscard]] float peek() const
67
    {
52✔
68
      return d_val;
52✔
69
    }
52✔
70

71
    [[nodiscard]] int last() const
72
    {
32✔
73
      return d_last;
32✔
74
    }
32✔
75

76
    float d_val{0};
77
    int d_last{0};
78
  };
79

80
public:
81
  DecayingEwmaCollection(DNSName name, const struct timeval val = {0, 0}) :
82
    d_name(std::move(name)), d_lastget(val)
83
  {
97,326✔
84
  }
97,326✔
85

86
  void submit(const ComboAddress& remote, int usecs, const struct timeval& now) const
87
  {
12,975✔
88
    d_collection[remote].submit(usecs, d_lastget, now);
12,975✔
89
  }
12,975✔
90

91
  float getFactor(const struct timeval& now) const
92
  {
53,567✔
93
    float diff = makeFloat(d_lastget - now);
53,567✔
94
    return expf(diff / 60.0F); // is 1.0 or less
53,567✔
95
  }
53,567✔
96

97
  bool stale(time_t limit) const
98
  {
32✔
99
    return limit > d_lastget.tv_sec;
32✔
100
  }
32✔
101

102
  void purge(const std::map<ComboAddress, float>& keep) const
103
  {
12,847✔
104
    for (auto iter = d_collection.begin(); iter != d_collection.end();) {
26,954✔
105
      if (keep.find(iter->first) != keep.end()) {
14,107✔
106
        ++iter;
14,106✔
107
      }
14,106✔
108
      else {
1✔
109
        iter = d_collection.erase(iter);
1✔
110
      }
1✔
111
    }
14,107✔
112
  }
12,847✔
113

114
  void insert(const ComboAddress& address, float val, int last)
115
  {
16✔
116
    d_collection.insert(std::make_pair(address, DecayingEwma{val, last}));
16✔
117
  }
16✔
118

119
  // d_collection is the modifyable part of the record, we index on DNSName and timeval, and DNSName never changes
120
  mutable std::map<ComboAddress, DecayingEwma> d_collection;
121
  DNSName d_name;
122
  struct timeval d_lastget;
123
};
124

125
class nsspeeds_t : public multi_index_container<DecayingEwmaCollection,
126
                                                indexed_by<
127
                                                  hashed_unique<tag<DNSName>, member<DecayingEwmaCollection, const DNSName, &DecayingEwmaCollection::d_name>>,
128
                                                  ordered_non_unique<tag<timeval>, member<DecayingEwmaCollection, timeval, &DecayingEwmaCollection::d_lastget>>>>
129
{
130
public:
131
  const auto& find_or_enter(const DNSName& name, const struct timeval& now)
132
  {
25,822✔
133
    const auto iter = insert(DecayingEwmaCollection{name, now}).first;
25,822✔
134
    return *iter;
25,822✔
135
  }
25,822✔
136

137
  const auto& find_or_enter(const DNSName& name)
138
  {
20✔
139
    const auto iter = insert(DecayingEwmaCollection{name}).first;
20✔
140
    return *iter;
20✔
141
  }
20✔
142

143
  float fastest(const DNSName& name, const struct timeval& now)
144
  {
71,452✔
145
    auto& ind = get<DNSName>();
71,452✔
146
    auto iter = insert(DecayingEwmaCollection{name, now}).first;
71,452✔
147
    if (iter->d_collection.empty()) {
71,452✔
148
      return 0;
30,732✔
149
    }
30,732✔
150
    // This could happen if find(DNSName) entered an entry; it's used only by test code
151
    if (iter->d_lastget.tv_sec == 0 && iter->d_lastget.tv_usec == 0) {
40,720!
152
      ind.modify(iter, [&](DecayingEwmaCollection& dec) { dec.d_lastget = now; });
×
153
    }
×
154

155
    float ret = std::numeric_limits<float>::max();
40,720✔
156
    const float factor = iter->getFactor(now);
40,720✔
157
    for (auto& entry : iter->d_collection) {
41,726✔
158
      ret = std::min(ret, entry.second.get(factor));
41,726✔
159
    }
41,726✔
160
    ind.modify(iter, [&](DecayingEwmaCollection& dec) { dec.d_lastget = now; });
40,720✔
161
    return ret;
40,720✔
162
  }
71,452✔
163

164
  size_t getPB(const string& serverID, size_t maxSize, std::string& ret) const;
165
  size_t putPB(time_t cutoff, const std::string& pbuf);
166

167
private:
168
  template <typename T, typename U>
169
  static void getPBEntry(T& message, U& entry);
170
  template <typename T>
171
  bool putPBEntry(time_t cutoff, T& message);
172
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc