trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From duke8...@apache.org
Subject [trafficserver] branch master updated: Removed add/prepend. Use append only since we don't have priority implemented yet
Date Mon, 12 Aug 2019 13:48:38 GMT
This is an automated email from the ASF dual-hosted git repository.

duke8253 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 3cea219  Removed add/prepend. Use append only since we don't have priority implemented
yet
3cea219 is described below

commit 3cea21977b0729633b141682f50b297cb5369463
Author: dyrock <zeyuany@gmail.com>
AuthorDate: Thu Jul 26 17:07:16 2018 -0500

    Removed add/prepend. Use append only since we don't have priority implemented yet
---
 iocore/cache/test/stub.cc    |  16 ++++--
 iocore/net/libinknet_stub.cc |  11 +++-
 proxy/InkAPIInternal.h       |  99 ++++++++++++++++++++++++++--------
 proxy/ProxySession.cc        |  78 +++++++++++----------------
 proxy/ProxySession.h         |  15 +++---
 proxy/ProxyTransaction.cc    |  10 +++-
 proxy/ProxyTransaction.h     |   3 +-
 proxy/Transform.cc           |   2 +-
 proxy/http/HttpSM.cc         |  94 +++++++++++++-------------------
 proxy/http/HttpSM.h          |  15 ++----
 src/traffic_server/InkAPI.cc | 124 +++++++++++++++++++++++++++++++++++--------
 11 files changed, 290 insertions(+), 177 deletions(-)

diff --git a/iocore/cache/test/stub.cc b/iocore/cache/test/stub.cc
index 69205a9..2e5adc2 100644
--- a/iocore/cache/test/stub.cc
+++ b/iocore/cache/test/stub.cc
@@ -39,7 +39,7 @@ APIHooks::append(INKContInternal *cont)
 }
 
 int
-APIHook::invoke(int, void *)
+APIHook::invoke(int, void *) const
 {
   ink_assert(false);
   return 0;
@@ -53,21 +53,29 @@ APIHook::next() const
 }
 
 APIHook *
-APIHooks::get() const
+APIHooks::head() const
 {
   return nullptr;
 }
 
 void
-APIHooks::prepend(INKContInternal *cont)
+APIHooks::clear()
 {
 }
 
+HttpHookState::HttpHookState() {}
+
 void
-APIHooks::clear()
+HttpHookState::init(TSHttpHookID id, HttpAPIHooks const *global, HttpAPIHooks const *ssn,
HttpAPIHooks const *txn)
 {
 }
 
+APIHook const *
+HttpHookState::getNext()
+{
+  return nullptr;
+}
+
 void
 ConfigUpdateCbTable::invoke(const char * /* name ATS_UNUSED */)
 {
diff --git a/iocore/net/libinknet_stub.cc b/iocore/net/libinknet_stub.cc
index 000eb38..11fee25 100644
--- a/iocore/net/libinknet_stub.cc
+++ b/iocore/net/libinknet_stub.cc
@@ -86,7 +86,7 @@ Log::trace_out(sockaddr const *, unsigned short, char const *, ...)
 
 #include "InkAPIInternal.h"
 int
-APIHook::invoke(int, void *)
+APIHook::invoke(int, void *) const
 {
   ink_assert(false);
   return 0;
@@ -100,7 +100,14 @@ APIHook::next() const
 }
 
 APIHook *
-APIHooks::get() const
+APIHook::prev() const
+{
+  ink_assert(false);
+  return nullptr;
+}
+
+APIHook *
+APIHooks::head() const
 {
   ink_assert(false);
   return nullptr;
diff --git a/proxy/InkAPIInternal.h b/proxy/InkAPIInternal.h
index 17ba528..25fab38 100644
--- a/proxy/InkAPIInternal.h
+++ b/proxy/InkAPIInternal.h
@@ -31,6 +31,7 @@
 #include "ProxyConfig.h"
 #include "P_Cache.h"
 #include "I_Tasks.h"
+#include "Plugin.h"
 
 #include "ts/InkAPIPrivateIOCore.h"
 #include "ts/experimental.h"
@@ -114,8 +115,9 @@ class APIHook
 {
 public:
   INKContInternal *m_cont;
-  int invoke(int event, void *edata);
+  int invoke(int event, void *edata) const;
   APIHook *next() const;
+  APIHook *prev() const;
   LINK(APIHook, m_link);
 };
 
@@ -123,10 +125,12 @@ public:
 class APIHooks
 {
 public:
-  void prepend(INKContInternal *cont);
   void append(INKContInternal *cont);
-  APIHook *get() const;
+  /// Get the first hook.
+  APIHook *head() const;
+  /// Remove all hooks.
   void clear();
+  /// Check if there are no hooks.
   bool is_empty() const;
 
 private:
@@ -159,8 +163,6 @@ public:
 
   /// Remove all hooks.
   void clear();
-  /// Add the hook @a cont to the front of the hooks for @a id.
-  void prepend(ID id, INKContInternal *cont);
   /// Add the hook @a cont to the end of the hooks for @a id.
   void append(ID id, INKContInternal *cont);
   /// Get the list of hooks for @a id.
@@ -181,8 +183,11 @@ public:
   /// @return @c true if any hooks of type @a id are present.
   bool has_hooks_for(ID id) const;
 
+  /// Get a pointer to the set of hooks for a specific hook @id
+  APIHooks const *operator[](ID id) const;
+
 private:
-  bool hooks_p = false; ///< Flag for (not) empty container.
+  bool m_hooks_p = false; ///< Flag for (not) empty container.
   /// The array of hooks lists.
   APIHooks m_hooks[N];
 };
@@ -198,28 +203,18 @@ template <typename ID, int N>
 void
 FeatureAPIHooks<ID, N>::clear()
 {
-  for (int i = 0; i < N; ++i) {
-    m_hooks[i].clear();
-  }
-  hooks_p = false;
-}
-
-template <typename ID, int N>
-void
-FeatureAPIHooks<ID, N>::prepend(ID id, INKContInternal *cont)
-{
-  if (likely(is_valid(id))) {
-    hooks_p = true;
-    m_hooks[id].prepend(cont);
+  for (auto &h : m_hooks) {
+    h.clear();
   }
+  m_hooks_p = false;
 }
 
 template <typename ID, int N>
 void
 FeatureAPIHooks<ID, N>::append(ID id, INKContInternal *cont)
 {
-  if (likely(is_valid(id))) {
-    hooks_p = true;
+  if (is_valid(id)) {
+    m_hooks_p = true;
     m_hooks[id].append(cont);
   }
 }
@@ -228,7 +223,12 @@ template <typename ID, int N>
 APIHook *
 FeatureAPIHooks<ID, N>::get(ID id) const
 {
-  return likely(is_valid(id)) ? m_hooks[id].get() : nullptr;
+  return likely(is_valid(id)) ? m_hooks[id].head() : nullptr;
+}
+
+template <typename ID, int N> APIHooks const *FeatureAPIHooks<ID, N>::operator[](ID
id) const
+{
+  return likely(is_valid(id)) ? &(m_hooks[id]) : nullptr;
 }
 
 template <typename ID, int N>
@@ -244,7 +244,7 @@ template <typename ID, int N>
 bool
 FeatureAPIHooks<ID, N>::has_hooks() const
 {
-  return hooks_p;
+  return m_hooks_p;
 }
 
 template <typename ID, int N>
@@ -330,6 +330,59 @@ private:
   std::unordered_map<std::string, INKContInternal *> cb_table;
 };
 
+class HttpHookState
+{
+public:
+  /// Scope tags for interacting with a live instance.
+  enum ScopeTag { GLOBAL, SSN, TXN };
+
+  /// Default Constructor
+  HttpHookState();
+
+  /// Initialize the hook state to track up to 3 sources of hooks.
+  /// The argument order to this method is used to break priority ties (callbacks from earlier
args are invoked earlier)
+  /// The order in terms of @a ScopeTag is GLOBAL, SESSION, TRANSACTION.
+  void init(TSHttpHookID id, HttpAPIHooks const *global, HttpAPIHooks const *ssn = nullptr,
HttpAPIHooks const *txn = nullptr);
+
+  /// Select a hook for invocation and advance the state to the next valid hook
+  /// @return nullptr if no current hook.
+  APIHook const *getNext();
+
+  /// Get the hook ID
+  TSHttpHookID id() const;
+
+  /// Temporary function to return true. Later will be used to decide if a plugin is enabled
for the hooks
+  bool is_enabled();
+
+protected:
+  /// Track the state of one scope of hooks.
+  struct Scope {
+    APIHook const *_c; ///< Current hook (candidate for invocation).
+    APIHook const *_p; ///< Previous hook (already invoked).
+
+    /// Initialize the scope.
+    void init(HttpAPIHooks const *scope, TSHttpHookID id);
+    /// Clear the scope.
+    void clear();
+    /// Return the current candidate.
+    APIHook const *candidate();
+    /// Advance state to the next hook.
+    void operator++();
+  };
+
+private:
+  TSHttpHookID _id;
+  Scope _global; ///< Chain from global hooks.
+  Scope _ssn;    ///< Chain from session hooks.
+  Scope _txn;    ///< Chain from transaction hooks.
+};
+
+inline TSHttpHookID
+HttpHookState::id() const
+{
+  return _id;
+}
+
 void api_init();
 
 extern HttpAPIHooks *http_global_hooks;
diff --git a/proxy/ProxySession.cc b/proxy/ProxySession.cc
index 8ca3cfc..7063b9f 100644
--- a/proxy/ProxySession.cc
+++ b/proxy/ProxySession.cc
@@ -77,12 +77,6 @@ static const TSEvent eventmap[TS_HTTP_LAST_HOOK + 1] = {
   TS_EVENT_NONE,                       // TS_HTTP_LAST_HOOK
 };
 
-static bool
-is_valid_hook(TSHttpHookID hookid)
-{
-  return (hookid >= 0) && (hookid < TS_HTTP_LAST_HOOK);
-}
-
 void
 ProxySession::free()
 {
@@ -107,34 +101,28 @@ ProxySession::state_api_callout(int event, void *data)
   case EVENT_NONE:
   case EVENT_INTERVAL:
   case TS_EVENT_HTTP_CONTINUE:
-    if (likely(is_valid_hook(this->api_hookid))) {
-      if (this->api_current == nullptr && this->api_scope == API_HOOK_SCOPE_GLOBAL)
{
-        this->api_current = http_global_hooks->get(this->api_hookid);
-        this->api_scope   = API_HOOK_SCOPE_LOCAL;
-      }
+    if (nullptr == cur_hook) {
+      /// Get the next hook to invoke from HttpHookState
+      cur_hook = hook_state.getNext();
+    }
+    if (nullptr != cur_hook) {
+      APIHook const *hook = cur_hook;
 
-      if (this->api_current == nullptr && this->api_scope == API_HOOK_SCOPE_LOCAL)
{
-        this->api_current = ssn_hook_get(this->api_hookid);
-        this->api_scope   = API_HOOK_SCOPE_NONE;
-      }
+      MUTEX_TRY_LOCK(lock, hook->m_cont->mutex, mutex->thread_holding);
 
-      if (this->api_current) {
-        APIHook *hook = this->api_current;
-
-        MUTEX_TRY_LOCK(lock, hook->m_cont->mutex, mutex->thread_holding);
-        // Have a mutex but did't get the lock, reschedule
-        if (!lock.is_locked()) {
-          SET_HANDLER(&ProxySession::state_api_callout);
-          if (!schedule_event) { // Don't bother to schedule is there is already one out.
-            schedule_event = mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
-          }
-          return 0;
+      // Have a mutex but didn't get the lock, reschedule
+      if (!lock.is_locked()) {
+        SET_HANDLER(&ProxySession::state_api_callout);
+        if (!schedule_event) { // Don't bother if there is already one
+          schedule_event = mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
         }
-
-        this->api_current = this->api_current->next();
-        hook->invoke(eventmap[this->api_hookid], this);
         return 0;
       }
+
+      cur_hook = nullptr; // mark current callback at dispatched.
+      hook->invoke(eventmap[hook_state.id()], this);
+
+      return 0;
     }
 
     handle_api_return(event);
@@ -156,12 +144,10 @@ void
 ProxySession::do_api_callout(TSHttpHookID id)
 {
   ink_assert(id == TS_HTTP_SSN_START_HOOK || id == TS_HTTP_SSN_CLOSE_HOOK);
-
-  this->api_hookid  = id;
-  this->api_scope   = API_HOOK_SCOPE_GLOBAL;
-  this->api_current = nullptr;
-
-  if (this->has_hooks()) {
+  hook_state.init(id, http_global_hooks, &api_hooks);
+  /// Verify if there is any hook to invoke
+  cur_hook = hook_state.getNext();
+  if (nullptr != cur_hook) {
     SET_HANDLER(&ProxySession::state_api_callout);
     this->state_api_callout(EVENT_NONE, nullptr);
   } else {
@@ -172,13 +158,11 @@ ProxySession::do_api_callout(TSHttpHookID id)
 void
 ProxySession::handle_api_return(int event)
 {
-  TSHttpHookID hookid = this->api_hookid;
+  TSHttpHookID hookid = hook_state.id();
 
   SET_HANDLER(&ProxySession::state_api_callout);
 
-  this->api_hookid  = TS_HTTP_LAST_HOOK;
-  this->api_scope   = API_HOOK_SCOPE_NONE;
-  this->api_current = nullptr;
+  cur_hook = nullptr;
 
   switch (hookid) {
   case TS_HTTP_SSN_START_HOOK:
@@ -301,7 +285,7 @@ ProxySession::get_server_session() const
 TSHttpHookID
 ProxySession::get_hookid() const
 {
-  return api_hookid;
+  return hook_state.id();
 }
 
 void
@@ -353,21 +337,21 @@ ProxySession::get_local_addr()
 }
 
 void
-ProxySession::ssn_hook_append(TSHttpHookID id, INKContInternal *cont)
+ProxySession::hook_add(TSHttpHookID id, INKContInternal *cont)
 {
   this->api_hooks.append(id, cont);
 }
 
-void
-ProxySession::ssn_hook_prepend(TSHttpHookID id, INKContInternal *cont)
+APIHook *
+ProxySession::hook_get(TSHttpHookID id) const
 {
-  this->api_hooks.prepend(id, cont);
+  return this->api_hooks.get(id);
 }
 
-APIHook *
-ProxySession::ssn_hook_get(TSHttpHookID id) const
+HttpAPIHooks const *
+ProxySession::feature_hooks() const
 {
-  return this->api_hooks.get(id);
+  return &api_hooks;
 }
 
 bool
diff --git a/proxy/ProxySession.h b/proxy/ProxySession.h
index b0b3b56..5f40af7 100644
--- a/proxy/ProxySession.h
+++ b/proxy/ProxySession.h
@@ -101,9 +101,7 @@ public:
   virtual const char *get_protocol_string() const = 0;
   virtual bool is_transparent_passthrough_allowed() const;
 
-  virtual void ssn_hook_append(TSHttpHookID id, INKContInternal *cont);
-
-  virtual void ssn_hook_prepend(TSHttpHookID id, INKContInternal *cont);
+  virtual void hook_add(TSHttpHookID id, INKContInternal *cont);
 
   virtual bool is_chunked_encoding_supported() const;
 
@@ -146,8 +144,8 @@ public:
   TSHttpHookID get_hookid() const;
   bool has_hooks() const;
 
-  APIHook *ssn_hook_get(TSHttpHookID id) const;
-
+  APIHook *hook_get(TSHttpHookID id) const;
+  HttpAPIHooks const *feature_hooks() const;
   ////////////////////
   // Members
 
@@ -163,6 +161,9 @@ public:
   ink_hrtime ssn_last_txn_time = 0;
 
 protected:
+  // Hook dispatching state
+  HttpHookState hook_state;
+
   // XXX Consider using a bitwise flags variable for the following flags, so
   // that we can make the best use of internal alignment padding.
 
@@ -177,9 +178,7 @@ private:
   void handle_api_return(int event);
   int state_api_callout(int event, void *edata);
 
-  APIHookScope api_scope  = API_HOOK_SCOPE_NONE;
-  TSHttpHookID api_hookid = TS_HTTP_READ_REQUEST_HDR_HOOK;
-  APIHook *api_current    = nullptr;
+  APIHook const *cur_hook = nullptr;
   HttpAPIHooks api_hooks;
   void *user_args[TS_HTTP_MAX_USER_ARG];
 
diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc
index 1ece708..67b9c84 100644
--- a/proxy/ProxyTransaction.cc
+++ b/proxy/ProxyTransaction.cc
@@ -160,9 +160,15 @@ ProxyTransaction::debug() const
 }
 
 APIHook *
-ProxyTransaction::ssn_hook_get(TSHttpHookID id) const
+ProxyTransaction::hook_get(TSHttpHookID id) const
 {
-  return proxy_ssn ? proxy_ssn->ssn_hook_get(id) : nullptr;
+  return proxy_ssn ? proxy_ssn->hook_get(id) : nullptr;
+}
+
+HttpAPIHooks const *
+ProxyTransaction::feature_hooks() const
+{
+  return proxy_ssn ? proxy_ssn->feature_hooks() : nullptr;
 }
 
 bool
diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h
index 68c484b..7b16646 100644
--- a/proxy/ProxyTransaction.h
+++ b/proxy/ProxyTransaction.h
@@ -89,7 +89,8 @@ public:
 
   bool debug() const;
 
-  APIHook *ssn_hook_get(TSHttpHookID id) const;
+  APIHook *hook_get(TSHttpHookID id) const;
+  HttpAPIHooks const *feature_hooks() const;
   bool has_hooks() const;
 
   HostResStyle get_host_res_style() const;
diff --git a/proxy/Transform.cc b/proxy/Transform.cc
index 3049305..ee1c0af 100644
--- a/proxy/Transform.cc
+++ b/proxy/Transform.cc
@@ -545,7 +545,7 @@ TransformControl::handle_event(int event, void * /* edata ATS_UNUSED */)
     if (http_global_hooks && http_global_hooks->get(TS_HTTP_RESPONSE_TRANSFORM_HOOK))
{
       m_tvc = transformProcessor.open(this, http_global_hooks->get(TS_HTTP_RESPONSE_TRANSFORM_HOOK));
     } else {
-      m_tvc = transformProcessor.open(this, m_hooks.get());
+      m_tvc = transformProcessor.open(this, m_hooks.head());
     }
     ink_assert(m_tvc != nullptr);
 
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 10b82e6..a2117d4 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -1401,67 +1401,46 @@ plugins required to work with sni_routing.
     }
   // FALLTHROUGH
   case HTTP_API_CONTINUE:
-    if ((cur_hook_id >= 0) && (cur_hook_id < TS_HTTP_LAST_HOOK)) {
-      if (!cur_hook) {
-        if (cur_hooks == 0) {
-          cur_hook = http_global_hooks->get(cur_hook_id);
-          cur_hooks++;
-        }
-      }
-      // even if ua_txn is NULL, cur_hooks must
-      // be incremented otherwise cur_hooks is not set to 2 and
-      // transaction hooks (stored in api_hooks object) are not called.
-      if (!cur_hook) {
-        if (cur_hooks == 1) {
-          if (ua_txn) {
-            cur_hook = ua_txn->ssn_hook_get(cur_hook_id);
-          }
-          cur_hooks++;
-        }
+    if (nullptr == cur_hook) {
+      cur_hook = hook_state.getNext();
+    }
+    if (cur_hook) {
+      if (callout_state == HTTP_API_NO_CALLOUT) {
+        callout_state = HTTP_API_IN_CALLOUT;
       }
-      if (!cur_hook) {
-        if (cur_hooks == 2) {
-          cur_hook = api_hooks.get(cur_hook_id);
-          cur_hooks++;
-        }
+
+      MUTEX_TRY_LOCK(lock, cur_hook->m_cont->mutex, mutex->thread_holding);
+
+      // Have a mutex but didn't get the lock, reschedule
+      if (!lock.is_locked()) {
+        api_timer = -Thread::get_hrtime_updated();
+        HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_api_callout);
+        ink_assert(pending_action == nullptr);
+        pending_action = mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
+        return 0;
       }
-      if (cur_hook) {
-        if (callout_state == HTTP_API_NO_CALLOUT) {
-          callout_state = HTTP_API_IN_CALLOUT;
-        }
 
-        MUTEX_TRY_LOCK(lock, cur_hook->m_cont->mutex, mutex->thread_holding);
-        // Have a mutex but didn't get the lock, reschedule
-        if (!lock.is_locked()) {
-          api_timer = -Thread::get_hrtime_updated();
-          HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_api_callout);
-          ink_assert(pending_action == nullptr);
-          pending_action = mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
-          // Should @a callout_state be reset back to HTTP_API_NO_CALLOUT here? Because the
default
-          // handler has been changed the value isn't important to the rest of the state
machine
-          // but not resetting means there is no way to reliably detect re-entrance to this
state with an
-          // outstanding callout.
-          return 0;
-        }
-        SMDebug("http", "[%" PRId64 "] calling plugin on hook %s at hook %p", sm_id, HttpDebugNames::get_api_hook_name(cur_hook_id),
-                cur_hook);
+      SMDebug("http", "[%" PRId64 "] calling plugin on hook %s at hook %p", sm_id, HttpDebugNames::get_api_hook_name(cur_hook_id),
+              cur_hook);
 
-        APIHook *hook = cur_hook;
-        cur_hook      = cur_hook->next();
+      APIHook const *hook = cur_hook;
+      // Need to delay the next hook update until after this hook is called to handle dynamic
+      // callback manipulation. cur_hook isn't needed to track state (in hook_state).
+      cur_hook = nullptr;
 
-        if (!api_timer) {
-          api_timer = Thread::get_hrtime_updated();
-        }
-        hook->invoke(TS_EVENT_HTTP_READ_REQUEST_HDR + cur_hook_id, this);
-        if (api_timer > 0) { // true if the hook did not call TxnReenable()
-          milestone_update_api_time(milestones, api_timer);
-          api_timer = -Thread::get_hrtime_updated(); // set in order to track non-active
callout duration
-          // which means that if we get back from the invoke with api_timer < 0 we're
already
-          // tracking a non-complete callout from a chain so just let it ride. It will get
cleaned
-          // up in state_api_callback when the plugin re-enables this transaction.
-        }
-        return 0;
+      if (!api_timer) {
+        api_timer = Thread::get_hrtime();
+      }
+
+      hook->invoke(TS_EVENT_HTTP_READ_REQUEST_HDR + cur_hook_id, this);
+      if (api_timer > 0) { // true if the hook did not call TxnReenable()
+        milestone_update_api_time(milestones, api_timer);
+        api_timer = -Thread::get_hrtime(); // set in order to track non-active callout duration
+        // which means that if we get back from the invoke with api_timer < 0 we're already
+        // tracking a non-complete callout from a chain so just let it ride. It will get
cleaned
+        // up in state_api_callback when the plugin re-enables this transaction.
       }
+      return 0;
     }
     // Map the callout state into api_next
     switch (callout_state) {
@@ -5110,6 +5089,7 @@ HttpSM::do_api_callout_internal()
     ink_assert(!"not reached");
   }
 
+  hook_state.init(cur_hook_id, http_global_hooks, ua_txn ? ua_txn->feature_hooks() : nullptr,
&api_hooks);
   cur_hook  = nullptr;
   cur_hooks = 0;
   state_api_callout(0, nullptr);
@@ -5121,7 +5101,7 @@ HttpSM::do_post_transform_open()
   ink_assert(post_transform_info.vc == nullptr);
 
   if (is_action_tag_set("http_post_nullt")) {
-    txn_hook_prepend(TS_HTTP_REQUEST_TRANSFORM_HOOK, transformProcessor.null_transform(mutex.get()));
+    txn_hook_add(TS_HTTP_REQUEST_TRANSFORM_HOOK, transformProcessor.null_transform(mutex.get()));
   }
 
   post_transform_info.vc = transformProcessor.open(this, api_hooks.get(TS_HTTP_REQUEST_TRANSFORM_HOOK));
@@ -5142,7 +5122,7 @@ HttpSM::do_transform_open()
   APIHook *hooks;
 
   if (is_action_tag_set("http_nullt")) {
-    txn_hook_prepend(TS_HTTP_RESPONSE_TRANSFORM_HOOK, transformProcessor.null_transform(mutex.get()));
+    txn_hook_add(TS_HTTP_RESPONSE_TRANSFORM_HOOK, transformProcessor.null_transform(mutex.get()));
   }
 
   hooks = api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK);
diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h
index be81331..ab26c66 100644
--- a/proxy/http/HttpSM.h
+++ b/proxy/http/HttpSM.h
@@ -291,8 +291,7 @@ public:
   void dump_state_hdr(HTTPHdr *h, const char *s);
 
   // Functions for manipulating api hooks
-  void txn_hook_append(TSHttpHookID id, INKContInternal *cont);
-  void txn_hook_prepend(TSHttpHookID id, INKContInternal *cont);
+  void txn_hook_add(TSHttpHookID id, INKContInternal *cont);
   APIHook *txn_hook_get(TSHttpHookID id);
 
   bool is_private();
@@ -562,7 +561,8 @@ public:
 
 protected:
   TSHttpHookID cur_hook_id = TS_HTTP_LAST_HOOK;
-  APIHook *cur_hook        = nullptr;
+  APIHook const *cur_hook  = nullptr;
+  HttpHookState hook_state;
 
   //
   // Continuation time keeper
@@ -677,19 +677,12 @@ HttpSM::find_server_buffer_size()
 }
 
 inline void
-HttpSM::txn_hook_append(TSHttpHookID id, INKContInternal *cont)
+HttpSM::txn_hook_add(TSHttpHookID id, INKContInternal *cont)
 {
   api_hooks.append(id, cont);
   hooks_set = true;
 }
 
-inline void
-HttpSM::txn_hook_prepend(TSHttpHookID id, INKContInternal *cont)
-{
-  api_hooks.prepend(id, cont);
-  hooks_set = true;
-}
-
 inline APIHook *
 HttpSM::txn_hook_get(TSHttpHookID id)
 {
diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc
index 6d49303..edb4c31 100644
--- a/src/traffic_server/InkAPI.cc
+++ b/src/traffic_server/InkAPI.cc
@@ -1310,12 +1310,23 @@ INKVConnInternal::set_data(int id, void *data)
 
 ////////////////////////////////////////////////////////////////////
 //
-// APIHook, APIHooks, HttpAPIHooks
+// APIHook, APIHooks, HttpAPIHooks, HttpHookState
 //
 ////////////////////////////////////////////////////////////////////
+APIHook *
+APIHook::next() const
+{
+  return m_link.next;
+}
+
+APIHook *
+APIHook::prev() const
+{
+  return m_link.prev;
+}
 
 int
-APIHook::invoke(int event, void *edata)
+APIHook::invoke(int event, void *edata) const
 {
   if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL) || event == TS_EVENT_HTTP_TXN_CLOSE)
{
     if (ink_atomic_increment((int *)&m_cont->m_event_count, 1) < 0) {
@@ -1331,46 +1342,117 @@ APIHook::invoke(int event, void *edata)
 }
 
 APIHook *
-APIHook::next() const
+APIHooks::head() const
 {
-  return m_link.next;
+  return m_hooks.head;
 }
 
 void
-APIHooks::prepend(INKContInternal *cont)
+APIHooks::append(INKContInternal *cont)
 {
   APIHook *api_hook;
 
   api_hook         = apiHookAllocator.alloc();
   api_hook->m_cont = cont;
 
-  m_hooks.push(api_hook);
+  m_hooks.enqueue(api_hook);
 }
 
 void
-APIHooks::append(INKContInternal *cont)
+APIHooks::clear()
 {
-  APIHook *api_hook;
+  APIHook *hook;
+  while (nullptr != (hook = m_hooks.pop())) {
+    apiHookAllocator.free(hook);
+  }
+}
 
-  api_hook         = apiHookAllocator.alloc();
-  api_hook->m_cont = cont;
+HttpHookState::HttpHookState() : _id(TS_HTTP_LAST_HOOK) {}
 
-  m_hooks.enqueue(api_hook);
+void
+HttpHookState::init(TSHttpHookID id, HttpAPIHooks const *global, HttpAPIHooks const *ssn,
HttpAPIHooks const *txn)
+{
+  _id = id;
+
+  if (global) {
+    _global.init(global, id);
+  } else {
+    _global.clear();
+  }
+
+  if (ssn) {
+    _ssn.init(ssn, id);
+  } else {
+    _ssn.clear();
+  }
+
+  if (txn) {
+    _txn.init(txn, id);
+  } else {
+    _txn.clear();
+  }
 }
 
-APIHook *
-APIHooks::get() const
+APIHook const *
+HttpHookState::getNext()
 {
-  return m_hooks.head;
+  APIHook const *zret = nullptr;
+  do {
+    APIHook const *hg   = _global.candidate();
+    APIHook const *hssn = _ssn.candidate();
+    APIHook const *htxn = _txn.candidate();
+    zret                = nullptr;
+
+    Debug("plugin", "computing next callback for hook %d", _id);
+
+    if (hg) {
+      zret = hg;
+      ++_global;
+    } else if (hssn) {
+      zret = hssn;
+      ++_ssn;
+    } else if (htxn) {
+      zret = htxn;
+      ++_txn;
+    }
+  } while (zret != nullptr && !this->is_enabled());
+
+  return zret;
+}
+
+bool
+HttpHookState::is_enabled()
+{
+  return true;
 }
 
 void
-APIHooks::clear()
+HttpHookState::Scope::init(HttpAPIHooks const *feature_hooks, TSHttpHookID id)
 {
-  APIHook *hook;
-  while (nullptr != (hook = m_hooks.pop())) {
-    apiHookAllocator.free(hook);
-  }
+  APIHooks const *hooks = (*feature_hooks)[id];
+
+  _p = nullptr;
+  _c = hooks->head();
+}
+
+APIHook const *
+HttpHookState::Scope::candidate()
+{
+  /// Simply returns _c hook for now. Later will do priority checking here
+  return _c;
+}
+
+void
+HttpHookState::Scope::operator++()
+{
+  _p = _c;
+  _c = _c->next();
+}
+
+void
+HttpHookState::Scope::clear()
+{
+  _p = _c = nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -4760,7 +4842,7 @@ TSHttpSsnHookAdd(TSHttpSsn ssnp, TSHttpHookID id, TSCont contp)
   sdk_assert(sdk_sanity_check_hook_id(id) == TS_SUCCESS);
 
   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
-  cs->ssn_hook_append(id, (INKContInternal *)contp);
+  cs->hook_add(id, (INKContInternal *)contp);
 }
 
 int
@@ -4848,7 +4930,7 @@ TSHttpTxnHookAdd(TSHttpTxn txnp, TSHttpHookID id, TSCont contp)
     }
     hook = hook->m_link.next;
   }
-  sm->txn_hook_append(id, (INKContInternal *)contp);
+  sm->txn_hook_add(id, (INKContInternal *)contp);
 }
 
 // Private api function for gzip plugin.


Mime
View raw message