#include "dnsdist-carbon.hh"
#include "dnsdist.hh"
+#include "dnsdist-backoff.hh"
#ifndef DISABLE_CARBON
#include "dolog.hh"
{
setThreadName("dnsdist/carbon");
const auto intervalUSec = endpoint.interval * 1000 * 1000;
+ /* maximum interval between two attempts is 10 minutes */
+ const ExponentialBackOffTimer backOffTimer(10 * 60);
try {
uint8_t consecutiveFailures = 0;
consecutiveFailures = 0;
}
else {
- /* maximum interval between two attempts is 10 minutes */
- const time_t maxBackOff = 10 * 60;
- time_t backOff = 1;
- double backOffTmp = std::pow(2.0, static_cast<double>(consecutiveFailures));
- if (backOffTmp != HUGE_VAL && static_cast<uint64_t>(backOffTmp) <= static_cast<uint64_t>(std::numeric_limits<time_t>::max())) {
- backOff = static_cast<time_t>(backOffTmp);
- if (backOff > maxBackOff) {
- backOff = maxBackOff;
- }
- }
+ const auto backOff = backOffTimer.get(consecutiveFailures);
if (consecutiveFailures < std::numeric_limits<decltype(consecutiveFailures)>::max()) {
consecutiveFailures++;
}
dnscrypt.cc dnscrypt.hh \
dnsdist-async.cc dnsdist-async.hh \
dnsdist-backend.cc \
+ dnsdist-backoff.hh \
dnsdist-cache.cc dnsdist-cache.hh \
dnsdist-carbon.cc dnsdist-carbon.hh \
dnsdist-concurrent-connections.hh \
dnscrypt.cc dnscrypt.hh \
dnsdist-async.cc dnsdist-async.hh \
dnsdist-backend.cc \
+ dnsdist-backoff.hh \
dnsdist-cache.cc dnsdist-cache.hh \
dnsdist-concurrent-connections.hh \
dnsdist-dnsparser.cc dnsdist-dnsparser.hh \
test-dnsdist_cc.cc \
test-dnsdistasync.cc \
test-dnsdistbackend_cc.cc \
+ test-dnsdistbackoff.cc \
test-dnsdistdynblocks_hh.cc \
test-dnsdistkvs_cc.cc \
test-dnsdistlbpolicies_cc.cc \
*/
#include "dnsdist.hh"
+#include "dnsdist-backoff.hh"
#include "dnsdist-nghttp2.hh"
#include "dnsdist-random.hh"
#include "dnsdist-rings.hh"
}
time_t backOff = d_config.d_lazyHealthCheckMaxBackOff;
- double backOffCoeffTmp = std::pow(2.0, failedTests);
- if (backOffCoeffTmp != HUGE_VAL && static_cast<uint64_t>(backOffCoeffTmp) <= static_cast<uint64_t>(std::numeric_limits<time_t>::max())) {
- time_t backOffCoeff = static_cast<time_t>(backOffCoeffTmp);
- if ((std::numeric_limits<time_t>::max() / d_config.d_lazyHealthCheckFailedInterval) >= backOffCoeff) {
- backOff = d_config.d_lazyHealthCheckFailedInterval * backOffCoeff;
- if (backOff > d_config.d_lazyHealthCheckMaxBackOff || (std::numeric_limits<time_t>::max() - now) <= backOff) {
- backOff = d_config.d_lazyHealthCheckMaxBackOff;
- }
+ const ExponentialBackOffTimer backOffTimer(d_config.d_lazyHealthCheckMaxBackOff);
+ auto backOffCoeffTmp = backOffTimer.get(failedTests);
+ /* backOffCoeffTmp cannot be higher than d_config.d_lazyHealthCheckMaxBackOff */
+ const auto backOffCoeff = static_cast<time_t>(backOffCoeffTmp);
+ if ((std::numeric_limits<time_t>::max() / d_config.d_lazyHealthCheckFailedInterval) >= backOffCoeff) {
+ backOff = d_config.d_lazyHealthCheckFailedInterval * backOffCoeff;
+ if (backOff > d_config.d_lazyHealthCheckMaxBackOff || (std::numeric_limits<time_t>::max() - now) <= backOff) {
+ backOff = d_config.d_lazyHealthCheckMaxBackOff;
}
}
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+class ExponentialBackOffTimer
+{
+public:
+ ExponentialBackOffTimer(unsigned int maxBackOff) :
+ d_maxBackOff(maxBackOff)
+ {
+ }
+
+ unsigned int get(size_t consecutiveFailures) const
+ {
+ unsigned int backOff = d_maxBackOff;
+ if (consecutiveFailures <= 31) {
+ backOff = 1U << consecutiveFailures;
+ backOff = std::min(d_maxBackOff, backOff);
+ }
+ return backOff;
+ }
+
+private:
+ const unsigned int d_maxBackOff;
+};
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_NO_MAIN
+
+#include <boost/test/unit_test.hpp>
+
+#include "dnsdist-backoff.hh"
+
+BOOST_AUTO_TEST_SUITE(dnsdistbackoff)
+
+BOOST_AUTO_TEST_CASE(test_ExponentialBackOffTimer)
+{
+ const unsigned int maxBackOff = 10 * 60;
+ const ExponentialBackOffTimer ebot(maxBackOff);
+ const std::vector<std::pair<size_t, unsigned int>> testVector{
+ {0U, 1U},
+ {1U, 2U},
+ {2U, 4U},
+ {3U, 8U},
+ {4U, 16U},
+ {5U, 32U},
+ {6U, 64U},
+ {7U, 128U},
+ {8U, 256U},
+ {9U, 512U},
+ {10U, maxBackOff}};
+ for (const auto& entry : testVector) {
+ BOOST_CHECK_EQUAL(ebot.get(entry.first), entry.second);
+ }
+
+ /* the behaviour is identical after 32 but let's go to 1024 to be safe */
+ for (size_t consecutiveFailures = testVector.size(); consecutiveFailures < 1024; consecutiveFailures++) {
+ BOOST_CHECK_EQUAL(ebot.get(consecutiveFailures), maxBackOff);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()