Commit c487cd88 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttpx: Periodically remove expired DNS cache entries

parent fd403a85
...@@ -28,9 +28,21 @@ ...@@ -28,9 +28,21 @@
namespace shrpx { namespace shrpx {
DNSTracker::DNSTracker(struct ev_loop *loop) : loop_(loop) {} namespace {
void gccb(struct ev_loop *loop, ev_timer *w, int revents) {
auto dns_tracker = static_cast<DNSTracker *>(w->data);
dns_tracker->gc();
}
} // namespace
DNSTracker::DNSTracker(struct ev_loop *loop) : loop_(loop) {
ev_timer_init(&gc_timer_, gccb, 0., 12_h);
gc_timer_.data = this;
}
DNSTracker::~DNSTracker() { DNSTracker::~DNSTracker() {
ev_timer_stop(loop_, &gc_timer_);
for (auto &p : ents_) { for (auto &p : ents_) {
auto &qlist = p.second.qlist; auto &qlist = p.second.qlist;
while (!qlist.empty()) { while (!qlist.empty()) {
...@@ -94,6 +106,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) { ...@@ -94,6 +106,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
ents_.emplace(host, make_entry(nullptr, std::move(host_copy), ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
DNS_STATUS_ERROR, nullptr)); DNS_STATUS_ERROR, nullptr));
start_gc_timer();
return DNS_STATUS_ERROR; return DNS_STATUS_ERROR;
} }
...@@ -107,6 +121,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) { ...@@ -107,6 +121,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
ents_.emplace(host, make_entry(nullptr, std::move(host_copy), ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
DNS_STATUS_ERROR, nullptr)); DNS_STATUS_ERROR, nullptr));
start_gc_timer();
return DNS_STATUS_ERROR; return DNS_STATUS_ERROR;
} }
case DNS_STATUS_OK: { case DNS_STATUS_OK: {
...@@ -118,6 +134,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) { ...@@ -118,6 +134,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
ents_.emplace(host, make_entry(nullptr, std::move(host_copy), ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
DNS_STATUS_OK, result)); DNS_STATUS_OK, result));
start_gc_timer();
return DNS_STATUS_OK; return DNS_STATUS_OK;
} }
case DNS_STATUS_RUNNING: { case DNS_STATUS_RUNNING: {
...@@ -127,6 +145,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) { ...@@ -127,6 +145,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
make_entry(std::move(resolv), std::move(host_copy), make_entry(std::move(resolv), std::move(host_copy),
DNS_STATUS_RUNNING, nullptr)); DNS_STATUS_RUNNING, nullptr));
start_gc_timer();
auto &ent = (*p.first).second; auto &ent = (*p.first).second;
add_to_qlist(ent, dnsq); add_to_qlist(ent, dnsq);
...@@ -260,4 +280,33 @@ void DNSTracker::cancel(DNSQuery *dnsq) { ...@@ -260,4 +280,33 @@ void DNSTracker::cancel(DNSQuery *dnsq) {
dnsq->in_qlist = false; dnsq->in_qlist = false;
} }
void DNSTracker::start_gc_timer() {
if (ev_is_active(&gc_timer_)) {
return;
}
ev_timer_again(loop_, &gc_timer_);
}
void DNSTracker::gc() {
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "Starting removing expired DNS cache entries";
}
auto now = ev_now(loop_);
for (auto it = std::begin(ents_); it != std::end(ents_);) {
auto &ent = (*it).second;
if (ent.expiry >= now) {
++it;
continue;
}
it = ents_.erase(it);
}
if (ents_.empty()) {
ev_timer_stop(loop_, &gc_timer_);
}
}
} // namespace shrpx } // namespace shrpx
...@@ -88,6 +88,10 @@ public: ...@@ -88,6 +88,10 @@ public:
int resolve(Address *result, DNSQuery *dnsq); int resolve(Address *result, DNSQuery *dnsq);
// Cancels name lookup requested by |dnsq|. // Cancels name lookup requested by |dnsq|.
void cancel(DNSQuery *dnsq); void cancel(DNSQuery *dnsq);
// Removes expired entries from ents_.
void gc();
// Starts GC timer.
void start_gc_timer();
private: private:
ResolverEntry make_entry(std::unique_ptr<DualDNSResolver> resolv, ResolverEntry make_entry(std::unique_ptr<DualDNSResolver> resolv,
...@@ -100,6 +104,10 @@ private: ...@@ -100,6 +104,10 @@ private:
void add_to_qlist(ResolverEntry &ent, DNSQuery *dnsq); void add_to_qlist(ResolverEntry &ent, DNSQuery *dnsq);
std::map<StringRef, ResolverEntry> ents_; std::map<StringRef, ResolverEntry> ents_;
// Periodically iterates ents_, and removes expired entries to avoid
// excessive use of memory. Since only backend API can potentially
// increase memory consumption, interval could be very long.
ev_timer gc_timer_;
struct ev_loop *loop_; struct ev_loop *loop_;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment