You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ok...@apache.org on 2019/01/22 13:54:44 UTC

[trafficserver] branch master updated: Do not call dns_result repeatedly for a valid dns result.

This is an automated email from the ASF dual-hosted git repository.

oknet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new f7f6d7e  Do not call dns_result repeatedly for a valid dns result.
f7f6d7e is described below

commit f7f6d7e4a2de4c2d3e26e3fd9aea93c9974a23f8
Author: Oknet Xu <xu...@skyguard.com.cn>
AuthorDate: Mon Jan 21 20:48:22 2019 +0800

    Do not call dns_result repeatedly for a valid dns result.
---
 iocore/dns/DNS.cc           | 93 ++++++++++++++++++++++++---------------------
 iocore/dns/P_DNSProcessor.h |  3 +-
 2 files changed, 52 insertions(+), 44 deletions(-)

diff --git a/iocore/dns/DNS.cc b/iocore/dns/DNS.cc
index 5db7f67..6deb3dc 100644
--- a/iocore/dns/DNS.cc
+++ b/iocore/dns/DNS.cc
@@ -1307,7 +1307,16 @@ dns_result(DNSHandler *h, DNSEntry *e, HostEnt *ent, bool retry, bool tcp_retry)
       DNS_SUM_DYN_STAT(dns_success_time_stat, Thread::get_hrtime() - e->submit_time);
     }
   }
+
+  // Remove head node from DNSHandler::entries queue
   h->entries.remove(e);
+  // Release Query ID from DNSHandler
+  for (int i : e->id) {
+    if (i < 0) {
+      break;
+    }
+    h->release_query_id(i);
+  }
 
   if (is_debug_tag_set("dns")) {
     if (is_addr_query(e->qtype)) {
@@ -1334,52 +1343,50 @@ dns_result(DNSHandler *h, DNSEntry *e, HostEnt *ent, bool retry, bool tcp_retry)
     DNS_INCREMENT_DYN_STAT(dns_lookup_fail_stat);
   }
 
-  DNSEntry *dup = nullptr;
-  while ((dup = e->dups.dequeue())) {
-    if (dup->post(h, ent)) {
-      e->dups.enqueue(dup);
-      goto Lretry;
-    }
-  }
-
-  if (e->timeout) {
-    e->timeout->cancel(e);
-    e->timeout = nullptr;
-  }
+  // Save HostEnt to the head node
   e->result_ent = ent;
+  e->retries    = 0;
+  SET_CONTINUATION_HANDLER(e, &DNSEntry::postAllEvent);
+  e->handleEvent(EVENT_NONE, nullptr);
+}
 
-  if (h->mutex->thread_holding == e->submit_thread) {
-    MUTEX_TRY_LOCK(lock, e->action.mutex, h->mutex->thread_holding);
-    if (!lock.is_locked()) {
-      Debug("dns", "failed lock for result %s", e->qname);
-      goto Lretry;
-    }
-    for (int i : e->id) {
-      if (i < 0) {
-        break;
-      }
-      h->release_query_id(i);
-    }
-    e->postEvent(0, nullptr);
-  } else {
-    for (int i : e->id) {
-      if (i < 0) {
-        break;
+int
+DNSEntry::postAllEvent(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */)
+{
+  /* Traverse the DNSEntry queue and callback
+   *
+   * The first DNSEntry object is head node,
+   *   - Pushed into DNSHandler::entries queue,
+   *   - Initial a DNS request and send to named server,
+   *   - Maintained a dups queue which holds the DNSEntry object for the same DNS request,
+   *   - All the DNSEntry in the queue share the same HostEnt result
+   *
+   * The head node callback the HostEnt result to the Continuation of all nodes one by one,
+   *   - If one of the callback fails, put the node back to the dups queue and try again later by reschedule the head node,
+   *   - Always call back the head node until the dups queue is empty.
+   */
+  DNSEntry *dup = nullptr;
+  while ((dup = dups.dequeue())) {
+    if (dup->post(dnsH, result_ent.get())) {
+      // If one of the callback fails, put the node back to the dups queue
+      dups.enqueue(dup);
+      // Try again by reschedule the head node
+      if (timeout) {
+        timeout->cancel();
       }
-      h->release_query_id(i);
+      timeout = dnsH->mutex->thread_holding->schedule_in(this, MUTEX_RETRY_DELAY);
+      return EVENT_DONE;
     }
-    e->mutex = e->action.mutex;
-    SET_CONTINUATION_HANDLER(e, &DNSEntry::postEvent);
-    e->submit_thread->schedule_imm_signal(e);
   }
-  return;
-Lretry:
-  e->result_ent = ent;
-  e->retries    = 0;
-  if (e->timeout) {
-    e->timeout->cancel();
+
+  // Process the head node at last
+  if (post(dnsH, result_ent.get())) {
+    // If the callback fails, switch the handler to DNSEntry::postOneEvent and reschedule it.
+    mutex = action.mutex;
+    SET_HANDLER(&DNSEntry::postOneEvent);
+    submit_thread->schedule_imm(this);
   }
-  e->timeout = h->mutex->thread_holding->schedule_in(e, MUTEX_RETRY_DELAY);
+  return EVENT_DONE;
 }
 
 int
@@ -1396,17 +1403,17 @@ DNSEntry::post(DNSHandler *h, HostEnt *ent)
       Debug("dns", "failed lock for result %s", qname);
       return 1;
     }
-    postEvent(0, nullptr);
+    postOneEvent(0, nullptr);
   } else {
     mutex = action.mutex;
-    SET_HANDLER(&DNSEntry::postEvent);
+    SET_HANDLER(&DNSEntry::postOneEvent);
     submit_thread->schedule_imm_signal(this);
   }
   return 0;
 }
 
 int
-DNSEntry::postEvent(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */)
+DNSEntry::postOneEvent(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */)
 {
   if (!action.cancelled) {
     Debug("dns", "called back continuation for %s", qname);
diff --git a/iocore/dns/P_DNSProcessor.h b/iocore/dns/P_DNSProcessor.h
index 86e6bdb..391f534 100644
--- a/iocore/dns/P_DNSProcessor.h
+++ b/iocore/dns/P_DNSProcessor.h
@@ -159,8 +159,9 @@ struct DNSEntry : public Continuation {
 
   int mainEvent(int event, Event *e);
   int delayEvent(int event, Event *e);
+  int postAllEvent(int event, Event *e);
   int post(DNSHandler *h, HostEnt *ent);
-  int postEvent(int event, Event *e);
+  int postOneEvent(int event, Event *e);
   void init(const char *x, int len, int qtype_arg, Continuation *acont, DNSProcessor::Options const &opt);
 
   DNSEntry()