diff --git a/src/Common/isLocalAddress.cpp b/src/Common/isLocalAddress.cpp index 7569c6fc14e..902505404a6 100644 --- a/src/Common/isLocalAddress.cpp +++ b/src/Common/isLocalAddress.cpp @@ -1,9 +1,14 @@ #include #include +#include #include +#include +#include +#include #include #include +#include #include #include #include @@ -20,7 +25,7 @@ namespace ErrorCodes namespace { -struct NetworkInterfaces +struct NetworkInterfaces : public boost::noncopyable { ifaddrs * ifaddr; NetworkInterfaces() @@ -31,6 +36,13 @@ struct NetworkInterfaces } } + void swap(NetworkInterfaces && other) + { + auto * tmp = ifaddr; + ifaddr = other.ifaddr; + other.ifaddr = tmp; + } + bool hasAddress(const Poco::Net::IPAddress & address) const { ifaddrs * iface; @@ -74,6 +86,32 @@ struct NetworkInterfaces { freeifaddrs(ifaddr); } + + static const NetworkInterfaces & instance() + { + static constexpr int NET_INTERFACE_VALID_PERIOD_MS = 30000; + static NetworkInterfaces nf; + static std::atomic last_updated_time = std::chrono::steady_clock::now(); + static std::shared_mutex nf_mtx; + + auto now = std::chrono::steady_clock::now(); + auto last_updated_time_snapshot = last_updated_time.load(); + + if (std::chrono::duration_cast(now - last_updated_time_snapshot).count() > NET_INTERFACE_VALID_PERIOD_MS) + { + std::unique_lock lock(nf_mtx); + if (last_updated_time.load() != last_updated_time_snapshot) /// it's possible that last_updated_time after we get the snapshot + return nf; + nf.swap(NetworkInterfaces()); + last_updated_time.store(now); + return nf; + } + else + { + std::shared_lock lock(nf_mtx); + return nf; + } + } }; } @@ -111,8 +149,7 @@ bool isLocalAddress(const Poco::Net::IPAddress & address) } } - NetworkInterfaces interfaces; - return interfaces.hasAddress(address); + return NetworkInterfaces::instance().hasAddress(address); }