nghttpx: Periodically remove expired DNS cache entries
This commit is contained in:
parent
fd403a85c8
commit
c487cd888f
|
@ -28,9 +28,21 @@
|
|||
|
||||
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() {
|
||||
ev_timer_stop(loop_, &gc_timer_);
|
||||
|
||||
for (auto &p : ents_) {
|
||||
auto &qlist = p.second.qlist;
|
||||
while (!qlist.empty()) {
|
||||
|
@ -94,6 +106,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
|||
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
||||
DNS_STATUS_ERROR, nullptr));
|
||||
|
||||
start_gc_timer();
|
||||
|
||||
return DNS_STATUS_ERROR;
|
||||
}
|
||||
|
||||
|
@ -107,6 +121,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
|||
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
||||
DNS_STATUS_ERROR, nullptr));
|
||||
|
||||
start_gc_timer();
|
||||
|
||||
return DNS_STATUS_ERROR;
|
||||
}
|
||||
case DNS_STATUS_OK: {
|
||||
|
@ -118,6 +134,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
|||
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
||||
DNS_STATUS_OK, result));
|
||||
|
||||
start_gc_timer();
|
||||
|
||||
return DNS_STATUS_OK;
|
||||
}
|
||||
case DNS_STATUS_RUNNING: {
|
||||
|
@ -127,6 +145,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
|||
make_entry(std::move(resolv), std::move(host_copy),
|
||||
DNS_STATUS_RUNNING, nullptr));
|
||||
|
||||
start_gc_timer();
|
||||
|
||||
auto &ent = (*p.first).second;
|
||||
|
||||
add_to_qlist(ent, dnsq);
|
||||
|
@ -260,4 +280,33 @@ void DNSTracker::cancel(DNSQuery *dnsq) {
|
|||
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
|
||||
|
|
|
@ -88,6 +88,10 @@ public:
|
|||
int resolve(Address *result, DNSQuery *dnsq);
|
||||
// Cancels name lookup requested by |dnsq|.
|
||||
void cancel(DNSQuery *dnsq);
|
||||
// Removes expired entries from ents_.
|
||||
void gc();
|
||||
// Starts GC timer.
|
||||
void start_gc_timer();
|
||||
|
||||
private:
|
||||
ResolverEntry make_entry(std::unique_ptr<DualDNSResolver> resolv,
|
||||
|
@ -100,6 +104,10 @@ private:
|
|||
void add_to_qlist(ResolverEntry &ent, DNSQuery *dnsq);
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue