You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2013/07/19 00:32:57 UTC

git commit: TS-1487: Fix startup order, add lifecycle hooks

Updated Branches:
  refs/heads/master ea560cecc -> 941784b2a


TS-1487: Fix startup order, add lifecycle hooks


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/941784b2
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/941784b2
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/941784b2

Branch: refs/heads/master
Commit: 941784b2a1ff3bcaf8a9a78337dbf121d6a21cf6
Parents: ea560ce
Author: Alan M. Carroll <am...@network-geographics.com>
Authored: Thu Jul 18 09:25:42 2013 -0500
Committer: Alan M. Carroll <am...@network-geographics.com>
Committed: Thu Jul 18 17:32:21 2013 -0500

----------------------------------------------------------------------
 CHANGES                                     |   2 +
 configure.ac                                |  13 --
 example/Makefile.am                         |   2 +
 example/app-template/app-template.cc        |   4 -
 example/lifecycle-plugin/lifecycle-plugin.c | 116 +++++++++++++++
 example/lifecycle-plugin/readme.txt         |   1 +
 iocore/cache/Cache.cc                       |   3 +
 iocore/cache/I_Cache.h                      |  25 ++++
 lib/ts/ink_config.h.in                      |   7 -
 mgmt/RecordsConfig.cc                       |   2 +
 proxy/IPAllow.h                             |   1 -
 proxy/InkAPI.cc                             |  73 +++-------
 proxy/InkAPIInternal.h                      |  89 ++++++++++--
 proxy/Main.cc                               |  65 +++++++--
 proxy/Transform.cc                          |   4 -
 proxy/api/ts/ts.h.in                        |  55 +++++++
 proxy/http/HttpClientSession.cc             |   2 +-
 proxy/http/HttpProxyServerMain.cc           | 176 +++++++++++++++--------
 proxy/http/HttpProxyServerMain.h            |   8 +-
 proxy/http/HttpSM.cc                        |   2 +-
 proxy/http/HttpTransact.cc                  |   4 -
 proxy/http/HttpUpdateSM.cc                  |   2 -
 22 files changed, 476 insertions(+), 180 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 599f7bf..d6889d8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 3.3.5
 
+  *) [TS-1487] [TS-2035] Moved plugin init, added plugin lifecycle hooks, added delay listen for cache. Removed TS_NO_API defined/build option.
+
   *) [TS-2047] Schedule RamCacheCLFUSCompressor in RamCacheCLFUS::init instead
    of immediatly after instantiation.
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 0bc7a00..0d2285a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -279,19 +279,6 @@ AC_MSG_RESULT([$enable_remote_cov_commit])
 AC_SUBST([enable_remote_cov_commit])
 
 #
-# API
-#
-AC_MSG_CHECKING([whether to enable API and plugin support])
-AC_ARG_ENABLE([api],
-  [AS_HELP_STRING([--disable-api],[do not enable API and plugin support])],
-  [],
-  [enable_api=yes]
-)
-AC_MSG_RESULT([$enable_api])
-AS_IF([test "x$enable_api" = "xyes"], [has_inkapi=1], [has_inkapi=0])
-AC_SUBST(has_inkapi)
-
-#
 # WCCP
 #
 AC_MSG_CHECKING([whether to enable WCCP v2 support])

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/example/Makefile.am
----------------------------------------------------------------------
diff --git a/example/Makefile.am b/example/Makefile.am
index e0939e0..193e1c4 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -28,6 +28,7 @@ noinst_LTLIBRARIES = \
 	cache-scan.la \
 	file-1.la \
 	hello.la \
+        lifecycle-plugin.la \
 	null-transform.la \
 	output-header.la \
 	protocol.la \
@@ -48,6 +49,7 @@ bnull_transform_la_SOURCES = bnull-transform/bnull-transform.c
 cache_scan_la_SOURCES = cache-scan/cache-scan.cc
 file_1_la_SOURCES = file-1/file-1.c
 hello_la_SOURCES = hello/hello.c
+lifecycle_plugin_la_SOURCES = lifecycle-plugin/lifecycle-plugin.c
 null_transform_la_SOURCES = null-transform/null-transform.c
 output_header_la_SOURCES = output-header/output-header.c
 protocol_la_SOURCES = protocol/Protocol.c protocol/TxnSM.c

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/example/app-template/app-template.cc
----------------------------------------------------------------------
diff --git a/example/app-template/app-template.cc b/example/app-template/app-template.cc
index cb1d9c3..d4d63cd 100644
--- a/example/app-template/app-template.cc
+++ b/example/app-template/app-template.cc
@@ -232,11 +232,7 @@ int main(int argc, char * argv[])
   // initialize logging (after event and net processor)
   //Log::init(system_remote_management_flag ? 0 : Log::NO_REMOTE_MANAGEMENT);
 
-#ifndef TS_NO_API
   //plugin_init(system_config_directory); // plugin.config
-#else
-  //api_init();  // still need to initialize some of the data structure other module needs.
-#endif
 
   // Create accept continuation
   MyAccept *a = new MyAccept;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/example/lifecycle-plugin/lifecycle-plugin.c
----------------------------------------------------------------------
diff --git a/example/lifecycle-plugin/lifecycle-plugin.c b/example/lifecycle-plugin/lifecycle-plugin.c
new file mode 100644
index 0000000..e08fbc3
--- /dev/null
+++ b/example/lifecycle-plugin/lifecycle-plugin.c
@@ -0,0 +1,116 @@
+/** @file
+
+  A brief file description
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+/* lifecycle-plugin.c: an example plugin to demonstrate the lifecycle hooks.
+ *                    of response body content
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <ts/ts.h>
+
+// This gets the PRI*64 types
+# define __STDC_FORMAT_MACROS 1
+# include <inttypes.h>
+
+int
+CallbackHandler(TSCont this, TSEvent id, void* no_data) {
+  (void) this;
+  (void) no_data;
+  switch (id) {
+  case TS_EVENT_LIFECYCLE_PORTS_INITIALIZED:
+    TSDebug("lifecycle-plugin", "Proxy ports initialized");
+    break;
+  case TS_EVENT_LIFECYCLE_PORTS_READY:
+    TSDebug("lifecycle-plugin", "Proxy ports active");
+    break;
+  case TS_EVENT_LIFECYCLE_CACHE_READY:
+    TSDebug("lifecycle-plugin", "Cache ready");
+    break;
+  default:
+    TSDebug("lifecycle-plugin", "Unexpected event %d", id);
+    break;
+  }
+  return TS_EVENT_NONE;
+}
+
+int
+CheckVersion()
+{
+  const char *ts_version = TSTrafficServerVersionGet();
+  int result = 0;
+
+  if (ts_version) {
+    int major_ts_version = 0;
+    int minor_ts_version = 0;
+    int patch_ts_version = 0;
+
+    if (sscanf(ts_version, "%d.%d.%d", &major_ts_version, &minor_ts_version, &patch_ts_version) != 3) {
+      return 0;
+    }
+
+    /* Need at least TS 3.3.5 */
+    if (major_ts_version > 3 ||
+	(major_ts_version == 3 &&
+	 (minor_ts_version > 3 ||
+	  (minor_ts_version == 3 && patch_ts_version >= 5)))) {
+      result = 1;
+    }
+  }
+  return result;
+}
+
+void
+TSPluginInit(int argc, const char *argv[])
+{
+  TSPluginRegistrationInfo info;
+  TSCont cb;
+
+  (void)argc;
+  (void)argv;
+
+  info.plugin_name = "lifecycle-plugin";
+  info.vendor_name = "My Company";
+  info.support_email = "ts-api-support@MyCompany.com";
+
+  if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
+    TSError("[lifecycle-plugin] Plugin registration failed.\n");
+    goto Lerror;
+  }
+
+  if (!CheckVersion()) {
+    TSError("[lifecycle-plugin] Plugin requires Traffic Server 3.3.5 " "or later\n");
+    goto Lerror;
+  }
+
+  cb = TSContCreate(CallbackHandler, NULL);
+
+  TSLifecycleHookAdd(TS_LIFECYCLE_PORTS_INITIALIZED_HOOK, cb);
+  TSLifecycleHookAdd(TS_LIFECYCLE_PORTS_READY_HOOK, cb);
+  TSLifecycleHookAdd(TS_LIFECYCLE_CACHE_READY_HOOK, cb);
+
+  return;
+
+Lerror:
+  TSError("[amc-tranform] Unable to initialize plugin (disabled).\n");
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/example/lifecycle-plugin/readme.txt
----------------------------------------------------------------------
diff --git a/example/lifecycle-plugin/readme.txt b/example/lifecycle-plugin/readme.txt
new file mode 100644
index 0000000..eba37fe
--- /dev/null
+++ b/example/lifecycle-plugin/readme.txt
@@ -0,0 +1 @@
+This prints debug messages about the lifecycle hooks.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/iocore/cache/Cache.cc
----------------------------------------------------------------------
diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc
index 9f482fd..06e7edf 100644
--- a/iocore/cache/Cache.cc
+++ b/iocore/cache/Cache.cc
@@ -1084,6 +1084,9 @@ CacheProcessor::cacheInitialized()
     CacheProcessor::initialized = CACHE_INIT_FAILED;
     Note("cache disabled");
   }
+  // Fire callback to signal initialization finished.
+  if (cb_after_init)
+    cb_after_init();
 }
 
 void

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/iocore/cache/I_Cache.h
----------------------------------------------------------------------
diff --git a/iocore/cache/I_Cache.h b/iocore/cache/I_Cache.h
index 4b1a3af..00e4791 100644
--- a/iocore/cache/I_Cache.h
+++ b/iocore/cache/I_Cache.h
@@ -65,6 +65,10 @@ typedef HTTPInfo CacheHTTPInfo;
 
 struct CacheProcessor:public Processor
 {
+  CacheProcessor()
+    : cb_after_init(0)
+  {}
+
   virtual int start(int n_cache_threads = 0, size_t stacksize = DEFAULT_STACKSIZE);
   virtual int start_internal(int flags = 0);
   void stop();
@@ -132,6 +136,20 @@ struct CacheProcessor:public Processor
 
   static unsigned int IsCacheReady(CacheFragType type);
 
+  /// Type for callback function.
+  typedef void (*CALLBACK_FUNC)();
+  /** Lifecycle callback.
+
+      The function @a cb is called after cache initialization has
+      finished and the cache is ready or has failed.
+
+      @internal If we need more lifecycle callbacks, this should be
+      generalized ala the standard hooks style, with a type enum used
+      to specific the callback type and passed to the callback
+      function.
+  */
+  void set_after_init_callback(CALLBACK_FUNC cb);
+
   // private members
   void diskInitialized();
 
@@ -144,8 +162,15 @@ struct CacheProcessor:public Processor
   static int fix;
   static int start_internal_flags;
   static int auto_clear_flag;
+  CALLBACK_FUNC cb_after_init;
 };
 
+inline void
+CacheProcessor::set_after_init_callback(CALLBACK_FUNC cb)
+{
+  cb_after_init = cb;
+}
+
 struct CacheVConnection:public VConnection
 {
   VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) = 0;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/lib/ts/ink_config.h.in
----------------------------------------------------------------------
diff --git a/lib/ts/ink_config.h.in b/lib/ts/ink_config.h.in
index 111c241..b8e59c4 100644
--- a/lib/ts/ink_config.h.in
+++ b/lib/ts/ink_config.h.in
@@ -85,7 +85,6 @@
 /* API */
 #define TS_IS_MICRO_BUILD              @is_micro_build@
 #define TS_HAS_STANDALONE_IOCORE       @has_standalone_iocore@
-#define TS_HAS_INKAPI                  @has_inkapi@
 #define TS_HAS_DEMANGLE                @has_demangle@
 #define TS_HAS_TESTS                   @has_tests@
 #define TS_HAS_WCCP                    @has_wccp@
@@ -111,13 +110,7 @@
 
 #define TS_MAX_HOST_NAME_LEN           @max_host_name_len@
 
-#if TS_HAS_INKAPI
 # define TS_MAX_API_STATS               @max_api_stats@
-/* XXX: Should make those individually selectable ? */
-#else
-# define TS_NO_TRANSFORM                1
-# define TS_NO_API                      1
-#endif
 
 #if TS_HAS_STANDALONE_IOCORE
 # define STANDALONE_IOCORE              1

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/mgmt/RecordsConfig.cc
----------------------------------------------------------------------
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index f0cc3c8..66102f4 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -390,6 +390,8 @@ RecordElement RecordsConfig[] = {
   ,
   {RECT_CONFIG, "proxy.config.http.server_other_ports", RECD_STRING, NULL, RECU_RESTART_TM, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.http.wait_for_cache", RECD_INT, "1", RECU_RESTART_TM, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
+  ,
   {RECT_CONFIG, "proxy.config.http.insert_request_via_str", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
   {RECT_CONFIG, "proxy.config.http.insert_response_via_str", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/IPAllow.h
----------------------------------------------------------------------
diff --git a/proxy/IPAllow.h b/proxy/IPAllow.h
index 941a7e7..76ecdf4 100644
--- a/proxy/IPAllow.h
+++ b/proxy/IPAllow.h
@@ -34,7 +34,6 @@
 #include "Main.h"
 #include "hdrs/HTTP.h"
 #include "ts/IpMap.h"
-#include "vector"
 #include "ts/Vec.h"
 #include "ProxyConfig.h"
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/InkAPI.cc
----------------------------------------------------------------------
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index cabab42..540bec8 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -21,8 +21,6 @@
   limitations under the License.
  */
 
-#ifndef TS_NO_API
-
 // Avoid complaining about the deprecated APIs.
 // #define TS_DEPRECATED
 
@@ -369,6 +367,7 @@ tsapi const char * TS_NPN_PROTOCOL_SPDY_3   = "spdy/3";   // upcoming
 tsapi const TSMLoc TS_NULL_MLOC = (TSMLoc)NULL;
 
 HttpAPIHooks *http_global_hooks = NULL;
+LifecycleAPIHooks* lifecycle_hooks = NULL;
 ConfigUpdateCbTable *global_config_cbs = NULL;
 
 static char traffic_server_version[128] = "";
@@ -630,6 +629,13 @@ sdk_sanity_check_hook_id(TSHttpHookID id)
   return TS_SUCCESS;
 }
 
+TSReturnCode
+sdk_sanity_check_lifecycle_hook_id(TSLifecycleHookID id)
+{
+  if (id<TS_LIFECYCLE_PORTS_INITIALIZED_HOOK || id> TS_LIFECYCLE_LAST_HOOK)
+    return TS_ERROR;
+  return TS_SUCCESS;
+}
 
 TSReturnCode
 sdk_sanity_check_null_ptr(void *ptr)
@@ -1241,58 +1247,15 @@ APIHooks::get()
   return m_hooks.head;
 }
 
-
-HttpAPIHooks::HttpAPIHooks():
-hooks_set(0)
-{
-}
-
-HttpAPIHooks::~HttpAPIHooks()
-{
-  clear();
-}
-
-
-
 void
-HttpAPIHooks::clear()
+APIHooks::clear()
 {
-  APIHook *api_hook;
-  APIHook *next_hook;
-  int i;
-
-  for (i = 0; i < TS_HTTP_LAST_HOOK; i++) {
-    api_hook = m_hooks[i].get();
-    while (api_hook) {
-      next_hook = api_hook->m_link.next;
-      apiHookAllocator.free(api_hook);
-      api_hook = next_hook;
-    }
+  APIHook* hook;
+  while (0 != (hook = m_hooks.pop())) {
+    apiHookAllocator.free(hook);
   }
-  hooks_set = 0;
 }
 
-void
-HttpAPIHooks::prepend(TSHttpHookID id, INKContInternal *cont)
-{
-  hooks_set = 1;
-  m_hooks[id].prepend(cont);
-}
-
-void
-HttpAPIHooks::append(TSHttpHookID id, INKContInternal *cont)
-{
-  hooks_set = 1;
-  m_hooks[id].append(cont);
-}
-
-APIHook *
-HttpAPIHooks::get(TSHttpHookID id)
-{
-  return m_hooks[id].get();
-}
-
-
 ////////////////////////////////////////////////////////////////////
 //
 // ConfigUpdateCbTable
@@ -1616,6 +1579,7 @@ api_init()
     TS_HTTP_LEN_S_MAXAGE = HTTP_LEN_S_MAXAGE;
 
     http_global_hooks = NEW(new HttpAPIHooks);
+    lifecycle_hooks = NEW(new LifecycleAPIHooks);
     global_config_cbs = NEW(new ConfigUpdateCbTable);
 
     if (TS_MAX_API_STATS > 0) {
@@ -4416,6 +4380,15 @@ TSHttpHookAdd(TSHttpHookID id, TSCont contp)
 }
 
 void
+TSLifecycleHookAdd(TSLifecycleHookID id, TSCont contp)
+{
+  sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
+  sdk_assert(sdk_sanity_check_lifecycle_hook_id(id) == TS_SUCCESS);
+
+  lifecycle_hooks->append(id, (INKContInternal *)contp);
+}
+
+void
 TSHttpIcpDynamicSet(int value)
 {
   int32_t old_value, new_value;
@@ -8193,5 +8166,3 @@ TSHttpTxnBackgroundFillStarted(TSHttpTxn txnp)
 
   return (s->background_fill == BACKGROUND_FILL_STARTED);
 }
-
-#endif //TS_NO_API

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/InkAPIInternal.h
----------------------------------------------------------------------
diff --git a/proxy/InkAPIInternal.h b/proxy/InkAPIInternal.h
index 4aabd1b..f40af8e 100644
--- a/proxy/InkAPIInternal.h
+++ b/proxy/InkAPIInternal.h
@@ -133,36 +133,100 @@ public:
   LINK(APIHook, m_link);
 };
 
-
 class APIHooks
 {
 public:
   void prepend(INKContInternal * cont);
   void append(INKContInternal * cont);
   APIHook *get();
+  void clear();
 
 private:
   Que(APIHook, m_link) m_hooks;
 };
 
-
-class HttpAPIHooks
+/** Container for API hooks for a specific feature.
+ */
+template <
+  typename ID, ///< Type of hook ID
+  ID MAX_ID ///< Maximum value for ID
+>
+class FeatureAPIHooks
 {
 public:
-  HttpAPIHooks();
-  ~HttpAPIHooks();
+  FeatureAPIHooks();
+  ~FeatureAPIHooks();
 
   void clear();
-  void prepend(TSHttpHookID id, INKContInternal * cont);
-  void append(TSHttpHookID id, INKContInternal * cont);
-  APIHook *get(TSHttpHookID id);
+  void prepend(ID id, INKContInternal * cont);
+  void append(ID id, INKContInternal * cont);
+  APIHook *get(ID id);
 
-  // A boolean value to quickly see if
-  //   any hooks are set
-  int hooks_set;
+  bool has_hooks() const;
 
 private:
-  APIHooks m_hooks[TS_HTTP_LAST_HOOK];
+  bool hooks_p; ///< Enable fast check for any hooks.
+  APIHooks m_hooks[MAX_ID];
+};
+
+template < typename ID, ID MAX_ID >
+FeatureAPIHooks<ID,MAX_ID>::FeatureAPIHooks():
+hooks_p(false)
+{
+}
+
+template < typename ID, ID MAX_ID >
+FeatureAPIHooks<ID,MAX_ID>::~FeatureAPIHooks()
+{
+  this->clear();
+}
+
+template < typename ID, ID MAX_ID >
+void
+FeatureAPIHooks<ID,MAX_ID>::clear()
+{
+  for (int i = 0; i < MAX_ID; ++i) {
+    m_hooks->clear();
+  }
+  hooks_p = false;
+}
+
+template < typename ID, ID MAX_ID >
+void
+FeatureAPIHooks<ID,MAX_ID>::prepend(ID id, INKContInternal *cont)
+{
+  hooks_p = true;
+  m_hooks[id].prepend(cont);
+}
+
+template < typename ID, ID MAX_ID >
+void
+FeatureAPIHooks<ID,MAX_ID>::append(ID id, INKContInternal *cont)
+{
+  hooks_p = true;
+  m_hooks[id].append(cont);
+}
+
+template < typename ID, ID MAX_ID >
+APIHook *
+FeatureAPIHooks<ID,MAX_ID>::get(ID id)
+{
+  return m_hooks[id].get();
+}
+
+template < typename ID, ID MAX_ID >
+bool
+FeatureAPIHooks<ID,MAX_ID>::has_hooks() const
+{
+  return hooks_p;
+}
+
+class HttpAPIHooks : public FeatureAPIHooks<TSHttpHookID, TS_HTTP_LAST_HOOK>
+{
+};
+
+class LifecycleAPIHooks : public FeatureAPIHooks<TSLifecycleHookID, TS_LIFECYCLE_LAST_HOOK>
+{
 };
 
 
@@ -214,6 +278,7 @@ private:
 void api_init();
 
 extern HttpAPIHooks *http_global_hooks;
+extern LifecycleAPIHooks* lifecycle_hooks;
 extern ConfigUpdateCbTable *global_config_cbs;
 
 #endif /* __INK_API_INTERNAL_H__ */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/Main.cc
----------------------------------------------------------------------
diff --git a/proxy/Main.cc b/proxy/Main.cc
index 9e9b4db..10804cd 100644
--- a/proxy/Main.cc
+++ b/proxy/Main.cc
@@ -159,7 +159,12 @@ static inkcoreapi DiagsConfig *diagsConfig = NULL;
 HttpBodyFactory *body_factory = NULL;
 
 static int accept_mss = 0;
-static int cmd_line_dprintf_level = 0;  // default debug output level fro ink_dprintf function
+static int cmd_line_dprintf_level = 0;  // default debug output level from ink_dprintf function
+
+// 1: delay listen, wait for cache.
+// 0: Do not delay, start listen ASAP.
+// -1: cache is already initialized, don't delay.
+static volatile int delay_listen_for_cache_p = 0;
 
 AppVersionInfo appVersionInfo;  // Build info for this application
 
@@ -435,6 +440,26 @@ skip(char *cmd, int null_ok = 0)
   return cmd;
 }
 
+// Handler for things that need to wait until the cache is initialized.
+static void
+CB_After_Cache_Init()
+{
+  APIHook* hook;
+  int start;
+
+  start = ink_atomic_swap(&delay_listen_for_cache_p, -1);
+  if (1 == start) {
+    Debug("http_listen", "Delayed listen enable, cache initialization finished");
+    start_HttpProxyServer();
+  }
+  // Alert the plugins the cache is initialized.
+  hook = lifecycle_hooks->get(TS_LIFECYCLE_CACHE_READY_HOOK);
+  while (hook) {
+    hook->invoke(TS_EVENT_LIFECYCLE_CACHE_READY, NULL);
+    hook = hook->next();
+  }
+}
+
 struct CmdCacheCont: public Continuation
 {
 
@@ -485,7 +510,7 @@ struct CmdCacheCont: public Continuation
     return EVENT_CONT;
   }
 
-CmdCacheCont(bool check, bool fix = false):Continuation(new_ProxyMutex()) {
+  CmdCacheCont(bool check, bool fix = false):Continuation(new_ProxyMutex()) {
     cache_fix = fix;
     if (check)
       SET_HANDLER(&CmdCacheCont::CheckEvent);
@@ -551,7 +576,6 @@ cmd_repair(char *cmd)
 }
 #endif
 
-
 static int
 cmd_clear(char *cmd)
 {
@@ -1555,6 +1579,7 @@ main(int /* argc ATS_UNUSED */, char **argv)
       HttpProxyPort::loadConfig();
     HttpProxyPort::loadDefaultIfEmpty();
 
+    cacheProcessor.set_after_init_callback(&CB_After_Cache_Init);
     cacheProcessor.start();
 
     // UDP net-threads are turned off by default.
@@ -1601,11 +1626,13 @@ main(int /* argc ATS_UNUSED */, char **argv)
     // main server logic initiated here //
     //////////////////////////////////////
 
-#ifndef TS_NO_TRANSFORM
+    plugin_init(system_config_directory);        // plugin.config
+    pmgmt->registerPluginCallbacks(global_config_cbs);
+
     transformProcessor.start();
-#endif
 
-    init_HttpProxyServer();
+    init_HttpProxyServer(num_accept_threads);
+
     int http_enabled = 1;
     TS_ReadConfigInteger(http_enabled, "proxy.config.http.enabled");
 
@@ -1614,21 +1641,29 @@ main(int /* argc ATS_UNUSED */, char **argv)
       int icp_enabled = 0;
       TS_ReadConfigInteger(icp_enabled, "proxy.config.icp.enabled");
 #endif
-      start_HttpProxyServer(num_accept_threads);
+      // call the ready hooks before we start accepting connections.
+      APIHook* hook = lifecycle_hooks->get(TS_LIFECYCLE_PORTS_INITIALIZED_HOOK);
+      while (hook) {
+        hook->invoke(TS_EVENT_LIFECYCLE_PORTS_INITIALIZED, NULL);
+        hook = hook->next();
+      }
+
+      int delay_p = 0;
+      TS_ReadConfigInteger(delay_p, "proxy.config.http.wait_for_cache");
+
+      // Delay only if config value set and flag value is zero
+      // (-1 => cache already initialized)
+      if (delay_p && ink_atomic_cas(&delay_listen_for_cache_p, 0, 1)) {
+        Debug("http_listen", "Delaying listen, waiting for cache initialization");
+      } else {
+        start_HttpProxyServer(); // PORTS_READY_HOOK called from in here
+      }
 #ifndef INK_NO_ICP
       if (icp_enabled)
         icpProcessor.start();
 #endif
     }
 
-#ifdef TS_NO_API
-    api_init();                 // we still need to initialize some of the data structure other module needs.
-    // i.e. http_global_hooks
-#else
-    plugin_init(system_config_directory);        // plugin.config
-    pmgmt->registerPluginCallbacks(global_config_cbs);
-#endif
-
     // "Task" processor, possibly with its own set of task threads
     tasksProcessor.start(num_task_threads, stacksize);
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/Transform.cc
----------------------------------------------------------------------
diff --git a/proxy/Transform.cc b/proxy/Transform.cc
index eb5cfe4..2da3301 100644
--- a/proxy/Transform.cc
+++ b/proxy/Transform.cc
@@ -59,8 +59,6 @@
 
 */
 
-#ifndef TS_NO_TRANSFORM
-
 #include "ProxyConfig.h"
 #include "P_Net.h"
 #include "MimeTable.h"
@@ -1040,5 +1038,3 @@ RangeTransform::change_response_header()
 }
 
 #undef RANGE_NUMBERS_LENGTH
-
-#endif // TS_NO_TRANSFORM

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/api/ts/ts.h.in
----------------------------------------------------------------------
diff --git a/proxy/api/ts/ts.h.in b/proxy/api/ts/ts.h.in
index 5ba4ebe..fc65e0e 100644
--- a/proxy/api/ts/ts.h.in
+++ b/proxy/api/ts/ts.h.in
@@ -276,6 +276,55 @@ extern "C"
   } TSHttpHookID;
   #define TS_HTTP_READ_REQUEST_PRE_REMAP_HOOK TS_HTTP_PRE_REMAP_HOOK  /* backwards compat */
 
+  /** Plugin lifecycle hooks.
+
+      These are called during lifecycle events of a plugin. They
+      should be set in the plugin initialization function. The
+      continuation is invoked with an event ID specified for each hook
+      and @c NULL for the event data.
+
+      TS_LIFECYCLE_PORTS_INITIALIZED_HOOK
+
+        called once, after the HTTP proxy port data structures have
+        been initialized. In particular, SSL related calls that depend
+        on accept endpoints may be invoked. After this hook is
+        finished, the proxy port sockets are opened and connections
+        are accepted.
+
+        Event: TS_EVENT_LIFECYCLE_PORTS_INITIALIZED
+
+      TS_LIFECYCLE_PORTS_READY_HOOK
+
+        called once, after the sockets have been opened and the accept
+        threads have been started. That is, the ports are ready to
+        accept connections. This is *not* guaranteed to be called
+        before the first connection is accepted.
+
+        Event: TS_EVENT_LIFECYCLE_PORTS_READY_HOOK
+
+      TS_LIFECYCLE_CACHE_READY_HOOK
+
+        called once, after the cache has finished its
+        initialization. It is either online or has failed when this
+        hook is called.
+
+        Event: TS_EVENT_LIFECYCLE_CACHE_READY
+
+      Ordering guarantees:
+
+      - TS_LIFECYCLE_PORTS_INITIALIZED_HOOK before TS_LIFECYCLE_PORTS_READY_HOOK.
+
+      NOTE! ONLY the orderings EXPLICITLY mentioned above are guaranteed.
+      
+   */
+  typedef enum
+  {
+    TS_LIFECYCLE_PORTS_INITIALIZED_HOOK,
+    TS_LIFECYCLE_PORTS_READY_HOOK,
+    TS_LIFECYCLE_CACHE_READY_HOOK,
+    TS_LIFECYCLE_LAST_HOOK
+  } TSLifecycleHookID;
+
   /**
       TSEvents are sent to continuations when they are called back.
       The TSEvent provides the continuation's handler function with
@@ -361,6 +410,9 @@ extern "C"
     TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE = 60015,
     TS_EVENT_HTTP_PRE_REMAP = 60016,
     TS_EVENT_HTTP_POST_REMAP = 60017,
+    TS_EVENT_LIFECYCLE_PORTS_INITIALIZED = 60018,
+    TS_EVENT_LIFECYCLE_PORTS_READY = 60019,
+    TS_EVENT_LIFECYCLE_CACHE_READY = 60020,
     TS_EVENT_MGMT_UPDATE = 60100,
 
     /* EVENTS 60200 - 60202 for internal use */
@@ -2191,6 +2243,9 @@ extern "C"
   tsapi TSMutex TSContMutexGet(TSCont contp);
 
   /* --------------------------------------------------------------------------
+     Plugin lifecycle  hooks */
+  tsapi void TSLifecycleHookAdd(TSLifecycleHookID id, TSCont contp);
+  /* --------------------------------------------------------------------------
      HTTP hooks */
   tsapi void TSHttpHookAdd(TSHttpHookID id, TSCont contp);
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpClientSession.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpClientSession.cc b/proxy/http/HttpClientSession.cc
index 21cc5ea..2601242 100644
--- a/proxy/http/HttpClientSession.cc
+++ b/proxy/http/HttpClientSession.cc
@@ -225,7 +225,7 @@ HttpClientSession::new_connection(NetVConnection * new_vc, bool backdoor)
   }
 
   // Record api hook set state
-  hooks_set = http_global_hooks->hooks_set;
+  hooks_set = http_global_hooks->has_hooks();
 
 #ifdef USE_HTTP_DEBUG_LISTS
   ink_mutex_acquire(&debug_cs_list_mutex);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpProxyServerMain.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpProxyServerMain.cc b/proxy/http/HttpProxyServerMain.cc
index 007fb90..485ce96 100644
--- a/proxy/http/HttpProxyServerMain.cc
+++ b/proxy/http/HttpProxyServerMain.cc
@@ -39,7 +39,6 @@
 HttpAccept *plugin_http_accept = NULL;
 HttpAccept *plugin_http_transparent_accept = 0;
 
-#if !defined(TS_NO_API)
 static SLL<SSLNextProtocolAccept> ssl_plugin_acceptors;
 static ProcessMutex ssl_plugin_mutex;
 
@@ -73,47 +72,43 @@ ssl_unregister_protocol(const char * protocol, Continuation * contp)
   return true;
 }
 
-#endif /* !defined(TS_NO_API) */
-
 /////////////////////////////////////////////////////////////////
 //
 //  main()
 //
 /////////////////////////////////////////////////////////////////
-void
-init_HttpProxyServer(void)
-{
-#ifndef INK_NO_REVERSE
-  init_reverse_proxy();
-#endif
-//  HttpConfig::startup();
-  httpSessionManager.init();
-  http_pages_init();
-  ink_mutex_init(&debug_sm_list_mutex, "HttpSM Debug List");
-  ink_mutex_init(&debug_cs_list_mutex, "HttpCS Debug List");
-  // DI's request to disable/reenable ICP on the fly
-  icp_dynamic_enabled = 1;
 
-#ifndef TS_NO_API
-  // Used to give plugins the ability to create http requests
-  //   The equivalent of the connecting to localhost on the  proxy
-  //   port but without going through the operating system
-  //
-  if (plugin_http_accept == NULL) {
-    plugin_http_accept = NEW(new HttpAccept);
-    plugin_http_accept->mutex = new_ProxyMutex();
-  }
-  // Same as plugin_http_accept except outbound transparent.
-  if (! plugin_http_transparent_accept) {
-    HttpAccept::Options ha_opt;
-    ha_opt.setOutboundTransparent(true);
-    plugin_http_transparent_accept = NEW(new HttpAccept(ha_opt));
-    plugin_http_transparent_accept->mutex = new_ProxyMutex();
-  }
-  ink_mutex_init(&ssl_plugin_mutex, "SSL Acceptor List");
-#endif
-}
+/** Data about an acceptor.
+
+    This is used to separate setting up the proxy ports and
+    starting to accept on them.
+
+*/
+struct HttpProxyAcceptor {
+  /// Accept continuation.
+  Continuation* _accept;
+  /// Options for @c NetProcessor.
+  NetProcessor::AcceptOptions _net_opt;
+
+  /// Default constructor.
+  HttpProxyAcceptor()
+    : _accept(0)
+    {
+    }
+};
 
+/** Global acceptors.
+    
+    This is parallel to @c HttpProxyPort::global(), each generated
+    from the corresponding port descriptor.
+
+    @internal We use @c Continuation instead of @c HttpAccept because
+    @c SSLNextProtocolAccept is a subclass of @c Cont instead of @c
+    HttpAccept.
+*/
+Vec<HttpProxyAcceptor> HttpProxyAcceptors;
+
+// Called from InkAPI.cc
 NetProcessor::AcceptOptions
 make_net_accept_options(const HttpProxyPort& port, unsigned nthreads)
 {
@@ -136,67 +131,116 @@ make_net_accept_options(const HttpProxyPort& port, unsigned nthreads)
   return net;
 }
 
-static bool
-start_HttpProxyPort(const HttpProxyPort& port, unsigned nthreads)
+static void
+MakeHttpProxyAcceptor(HttpProxyAcceptor& acceptor, HttpProxyPort& port, unsigned nthreads)
 {
-  NetProcessor::AcceptOptions net(make_net_accept_options(port, nthreads));
-  HttpAccept::Options         http;
+  NetProcessor::AcceptOptions& net_opt = acceptor._net_opt;
+  HttpAccept::Options         accept_opt;
 
-  REC_ReadConfigInteger(net.recv_bufsize, "proxy.config.net.sock_recv_buffer_size_in");
-  REC_ReadConfigInteger(net.send_bufsize, "proxy.config.net.sock_send_buffer_size_in");
-  REC_ReadConfigInteger(net.packet_mark, "proxy.config.net.sock_packet_mark_in");
-  REC_ReadConfigInteger(net.packet_tos, "proxy.config.net.sock_packet_tos_in");
+  net_opt = make_net_accept_options(port, nthreads);
+  REC_ReadConfigInteger(net_opt.recv_bufsize, "proxy.config.net.sock_recv_buffer_size_in");
+  REC_ReadConfigInteger(net_opt.send_bufsize, "proxy.config.net.sock_send_buffer_size_in");
+  REC_ReadConfigInteger(net_opt.packet_mark, "proxy.config.net.sock_packet_mark_in");
+  REC_ReadConfigInteger(net_opt.packet_tos, "proxy.config.net.sock_packet_tos_in");
 
-  http.f_outbound_transparent = port.m_outbound_transparent_p;
-  http.transport_type = port.m_type;
-  http.setHostResPreference(port.m_host_res_preference);
-  http.setTransparentPassthrough(port.m_transparent_passthrough);
+  accept_opt.f_outbound_transparent = port.m_outbound_transparent_p;
+  accept_opt.transport_type = port.m_type;
+  accept_opt.setHostResPreference(port.m_host_res_preference);
+  accept_opt.setTransparentPassthrough(port.m_transparent_passthrough);
 
   if (port.m_outbound_ip4.isValid()) {
-    http.outbound_ip4 = port.m_outbound_ip4;
+    accept_opt.outbound_ip4 = port.m_outbound_ip4;
   } else if (HttpConfig::m_master.outbound_ip4.isValid()) {
-    http.outbound_ip4 = HttpConfig::m_master.outbound_ip4;
+    accept_opt.outbound_ip4 = HttpConfig::m_master.outbound_ip4;
   }
 
   if (port.m_outbound_ip6.isValid()) {
-    http.outbound_ip6 = port.m_outbound_ip6;
+    accept_opt.outbound_ip6 = port.m_outbound_ip6;
   } else if (HttpConfig::m_master.outbound_ip6.isValid()) {
-    http.outbound_ip6 = HttpConfig::m_master.outbound_ip6;
+    accept_opt.outbound_ip6 = HttpConfig::m_master.outbound_ip6;
   }
 
   if (port.isSSL()) {
-    HttpAccept * accept = NEW(new HttpAccept(http));
+    HttpAccept * accept = NEW(new HttpAccept(accept_opt));
     SSLNextProtocolAccept * ssl = NEW(new SSLNextProtocolAccept(accept));
     ssl->registerEndpoint(TS_NPN_PROTOCOL_HTTP_1_0, accept);
     ssl->registerEndpoint(TS_NPN_PROTOCOL_HTTP_1_1, accept);
 
-#ifndef TS_NO_API
     ink_scoped_mutex lock(ssl_plugin_mutex);
     ssl_plugin_acceptors.push(ssl);
-#endif
 
-    return sslNetProcessor.main_accept(ssl, port.m_fd, net) != NULL;
+    acceptor._accept = ssl;
   } else {
-    return netProcessor.main_accept(NEW(new HttpAccept(http)), port.m_fd, net) != NULL;
+    acceptor._accept = NEW(new HttpAccept(accept_opt));
+  }
+}
+
+/** Set up all the accepts and sockets.
+ */
+void
+init_HttpProxyServer(int n_accept_threads)
+{
+  HttpProxyPort::Group& proxy_ports = HttpProxyPort::global();
+
+#ifndef INK_NO_REVERSE
+  init_reverse_proxy();
+#endif
+  httpSessionManager.init();
+  http_pages_init();
+  ink_mutex_init(&debug_sm_list_mutex, "HttpSM Debug List");
+  ink_mutex_init(&debug_cs_list_mutex, "HttpCS Debug List");
+  // DI's request to disable/reenable ICP on the fly
+  icp_dynamic_enabled = 1;
+
+  // Used to give plugins the ability to create http requests
+  //   The equivalent of the connecting to localhost on the  proxy
+  //   port but without going through the operating system
+  //
+  if (plugin_http_accept == NULL) {
+    plugin_http_accept = NEW(new HttpAccept);
+    plugin_http_accept->mutex = new_ProxyMutex();
   }
+  // Same as plugin_http_accept except outbound transparent.
+  if (! plugin_http_transparent_accept) {
+    HttpAccept::Options ha_opt;
+    ha_opt.setOutboundTransparent(true);
+    plugin_http_transparent_accept = NEW(new HttpAccept(ha_opt));
+    plugin_http_transparent_accept->mutex = new_ProxyMutex();
+  }
+  ink_mutex_init(&ssl_plugin_mutex, "SSL Acceptor List");
 
-  // XXX although we make a good pretence here, I don't believe that NetProcessor::main_accept() ever actually returns
-  // NULL. It would be useful to be able to detect errors and spew them here though.
+  // Do the configuration defined ports.
+  for ( int i = 0 , n = proxy_ports.length() ; i < n ; ++i ) {
+    MakeHttpProxyAcceptor(HttpProxyAcceptors.add(), proxy_ports[i], n_accept_threads);
+  }
+  
 }
 
 void
-start_HttpProxyServer(int accept_threads)
+start_HttpProxyServer()
 {
   static bool called_once = false;
+  HttpProxyPort::Group& proxy_ports = HttpProxyPort::global();
 
   ///////////////////////////////////
   // start accepting connections   //
   ///////////////////////////////////
 
   ink_assert(!called_once);
-
-  for ( int i = 0 , n = HttpProxyPort::global().length() ; i < n ; ++i ) {
-    start_HttpProxyPort(HttpProxyPort::global()[i], accept_threads);
+  ink_assert(proxy_ports.length() == HttpProxyAcceptors.length());
+
+  for ( int i = 0 , n = proxy_ports.length() ; i < n ; ++i ) {
+    HttpProxyAcceptor& acceptor = HttpProxyAcceptors[i];
+    HttpProxyPort& port = proxy_ports[i];
+    if (port.isSSL()) {
+      if (NULL == sslNetProcessor.main_accept(acceptor._accept, port.m_fd, acceptor._net_opt))
+        return;
+    } else {
+      if (NULL == netProcessor.main_accept(acceptor._accept, port.m_fd, acceptor._net_opt))
+        return;
+    }
+    // XXX although we make a good pretence here, I don't believe that NetProcessor::main_accept() ever actually returns
+    // NULL. It would be useful to be able to detect errors and spew them here though.
   }
 
 #if TS_HAS_TESTS
@@ -204,6 +248,14 @@ start_HttpProxyServer(int accept_threads)
     init_http_update_test();
   }
 #endif
+
+  // Alert plugins that connections will be accepted.
+  APIHook* hook = lifecycle_hooks->get(TS_LIFECYCLE_PORTS_READY_HOOK);
+  while (hook) {
+    hook->invoke(TS_EVENT_LIFECYCLE_PORTS_READY, NULL);
+    hook = hook->next();
+  }
+
 }
 
 void

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpProxyServerMain.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpProxyServerMain.h b/proxy/http/HttpProxyServerMain.h
index 1d0502e..98769ff 100644
--- a/proxy/http/HttpProxyServerMain.h
+++ b/proxy/http/HttpProxyServerMain.h
@@ -23,12 +23,14 @@
 
 struct HttpProxyPort;
 
-void init_HttpProxyServer(void);
+/** Initialize all HTTP proxy port data structures needed to run.
+ */
+void init_HttpProxyServer(int n_accept_threads = 0);
 
 /** Start the proxy server. 
-    The ports are contained in the HttpProxyPort global data.
+    The port data should have been created by @c init_HttpProxyServer().
 */
-void start_HttpProxyServer(int accept_threads = 0);
+void start_HttpProxyServer();
 
 void start_HttpProxyServerBackDoor(int port, int accept_threads = 0);
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 1ebf842..4cfe0d1 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -612,7 +612,7 @@ HttpSM::attach_client_session(HttpClientSession * client_vc, IOBufferReader * bu
   HTTP_INCREMENT_DYN_STAT(http_current_client_transactions_stat);
 
   // Record api hook set state
-  hooks_set = http_global_hooks->hooks_set | client_vc->hooks_set;
+  hooks_set = http_global_hooks->has_hooks() || client_vc->hooks_set;
 
   // Setup for parsing the header
   ua_buffer_reader = buffer_reader;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpTransact.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 820663a..c8cc90f 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -4617,7 +4617,6 @@ HttpTransact::handle_transform_ready(State* s)
 void
 HttpTransact::set_header_for_transform(State* s, HTTPHdr* base_header)
 {
-#ifndef TS_NO_TRANSFORM
   s->hdr_info.transform_response.create(HTTP_TYPE_RESPONSE);
   s->hdr_info.transform_response.copy(base_header);
 
@@ -4628,9 +4627,6 @@ HttpTransact::set_header_for_transform(State* s, HTTPHdr* base_header)
 
   if (!s->cop_test_page)
     DUMP_HEADER("http_hdrs", &s->hdr_info.transform_response, s->state_machine_id, "Header To Transform");
-#else
-  ink_assert(!"transformation not supported\n");
-#endif // TS_NO_TRANSFORM
 }
 
 void

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpUpdateSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpUpdateSM.cc b/proxy/http/HttpUpdateSM.cc
index 7b5eddf..6b47881 100644
--- a/proxy/http/HttpUpdateSM.cc
+++ b/proxy/http/HttpUpdateSM.cc
@@ -116,7 +116,6 @@ HttpUpdateSM::handle_api_return()
   }
 
   switch (t_state.next_action) {
-#ifndef TS_NO_TRANSFORM
   case HttpTransact::TRANSFORM_READ:
     {
       if (t_state.cache_info.transform_action == HttpTransact::CACHE_DO_WRITE) {
@@ -154,7 +153,6 @@ HttpUpdateSM::handle_api_return()
       }
       break;
     }
-#endif //TS_NO_TRANSFORM
   case HttpTransact::PROXY_INTERNAL_CACHE_WRITE:
   case HttpTransact::SERVER_READ:
   case HttpTransact::PROXY_INTERNAL_CACHE_NOOP:


Re: git commit: TS-1487: Fix startup order, add lifecycle hooks

Posted by "Alan M. Carroll" <am...@network-geographics.com>.
Friday, July 19, 2013, 5:49:33 AM, you wrote:

>>  Changes with Apache Traffic Server 3.3.5
>>  
>> +  *) [TS-1487] [TS-2035] Moved plugin init, added plugin lifecycle
>> hooks, added delay listen for cache. Removed TS_NO_API defined/build
>> option.
>> +

> Why are those three changes all munged into one commit?

Because TS-2035 is a duplicate of TS-1487 and the rest of that is part of the proposed fix for TS-1487. The TS_NO_API is in there because it was getting in my way while I was fixing this and I solved it zwoop-style.


Re: git commit: TS-1487: Fix startup order, add lifecycle hooks

Posted by Igor Galić <i....@brainsware.org>.

----- Original Message -----
> Updated Branches:
>   refs/heads/master ea560cecc -> 941784b2a
> 
> 
> TS-1487: Fix startup order, add lifecycle hooks
vs

> ----------------------------------------------------------------------
> diff --git a/CHANGES b/CHANGES
> index 599f7bf..d6889d8 100644
> --- a/CHANGES
> +++ b/CHANGES
> @@ -1,6 +1,8 @@
>                                                           -*- coding:
>                                                           utf-8 -*-
>  Changes with Apache Traffic Server 3.3.5
>  
> +  *) [TS-1487] [TS-2035] Moved plugin init, added plugin lifecycle
> hooks, added delay listen for cache. Removed TS_NO_API defined/build
> option.
> +

Why are those three changes all munged into one commit?

>    *) [TS-2047] Schedule RamCacheCLFUSCompressor in
>    RamCacheCLFUS::init instead
>     of immediatly after instantiation.
>  
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/configure.ac
> ----------------------------------------------------------------------
> diff --git a/configure.ac b/configure.ac
> index 0bc7a00..0d2285a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -279,19 +279,6 @@ AC_MSG_RESULT([$enable_remote_cov_commit])
>  AC_SUBST([enable_remote_cov_commit])
>  
>  #
> -# API
> -#
> -AC_MSG_CHECKING([whether to enable API and plugin support])
> -AC_ARG_ENABLE([api],
> -  [AS_HELP_STRING([--disable-api],[do not enable API and plugin
> support])],
> -  [],
> -  [enable_api=yes]
> -)
> -AC_MSG_RESULT([$enable_api])
> -AS_IF([test "x$enable_api" = "xyes"], [has_inkapi=1],
> [has_inkapi=0])
> -AC_SUBST(has_inkapi)
> -
> -#
>  # WCCP
>  #
>  AC_MSG_CHECKING([whether to enable WCCP v2 support])
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/example/Makefile.am
> ----------------------------------------------------------------------
> diff --git a/example/Makefile.am b/example/Makefile.am
> index e0939e0..193e1c4 100644
> --- a/example/Makefile.am
> +++ b/example/Makefile.am
> @@ -28,6 +28,7 @@ noinst_LTLIBRARIES = \
>  	cache-scan.la \
>  	file-1.la \
>  	hello.la \
> +        lifecycle-plugin.la \

tab vs spaces

>  	null-transform.la \
>  	output-header.la \
>  	protocol.la \
> @@ -48,6 +49,7 @@ bnull_transform_la_SOURCES =
> bnull-transform/bnull-transform.c
>  cache_scan_la_SOURCES = cache-scan/cache-scan.cc
>  file_1_la_SOURCES = file-1/file-1.c
>  hello_la_SOURCES = hello/hello.c
> +lifecycle_plugin_la_SOURCES = lifecycle-plugin/lifecycle-plugin.c
>  null_transform_la_SOURCES = null-transform/null-transform.c
>  output_header_la_SOURCES = output-header/output-header.c
>  protocol_la_SOURCES = protocol/Protocol.c protocol/TxnSM.c
> 
[snip]
> ----------------------------------------------------------------------
> diff --git a/example/lifecycle-plugin/lifecycle-plugin.c
> b/example/lifecycle-plugin/lifecycle-plugin.c
> new file mode 100644
> index 0000000..e08fbc3
> --- /dev/null
> +++ b/example/lifecycle-plugin/lifecycle-plugin.c
[snip]
> +int
> +CheckVersion()
> +{
> +  const char *ts_version = TSTrafficServerVersionGet();
> +  int result = 0;
> +
> +  if (ts_version) {
> +    int major_ts_version = 0;
> +    int minor_ts_version = 0;
> +    int patch_ts_version = 0;
> +
> +    if (sscanf(ts_version, "%d.%d.%d", &major_ts_version,
> &minor_ts_version, &patch_ts_version) != 3) {
> +      return 0;
> +    }
> +
> +    /* Need at least TS 3.3.5 */
> +    if (major_ts_version > 3 ||
> +	(major_ts_version == 3 &&
> +	 (minor_ts_version > 3 ||
> +	  (minor_ts_version == 3 && patch_ts_version >= 5)))) {
> +      result = 1;
> +    }
> +  }
> +  return result;
> +}

another reminder of https://issues.apache.org/jira/browse/TS-1953


> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/mgmt/RecordsConfig.cc
> ----------------------------------------------------------------------
> diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
> index f0cc3c8..66102f4 100644
> --- a/mgmt/RecordsConfig.cc
> +++ b/mgmt/RecordsConfig.cc
> @@ -390,6 +390,8 @@ RecordElement RecordsConfig[] = {
>    ,
>    {RECT_CONFIG, "proxy.config.http.server_other_ports", RECD_STRING,
>    NULL, RECU_RESTART_TM, RR_NULL, RECC_NULL, NULL, RECA_NULL}
>    ,
> +  {RECT_CONFIG, "proxy.config.http.wait_for_cache", RECD_INT, "1", 
> RECU_RESTART_TM, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
> +  ,

maybe in CHANGES we should write what the consequence of that change
was rather than writing that we've made some change to fix TS-blah-blah


>    {RECT_CONFIG, "proxy.config.http.insert_request_via_str",
>    RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
>    ,
>    {RECT_CONFIG, "proxy.config.http.insert_response_via_str",
>    RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/IPAllow.h
> ----------------------------------------------------------------------
> diff --git a/proxy/IPAllow.h b/proxy/IPAllow.h
> index 941a7e7..76ecdf4 100644
> --- a/proxy/IPAllow.h
> +++ b/proxy/IPAllow.h
> @@ -34,7 +34,6 @@
>  #include "Main.h"
>  #include "hdrs/HTTP.h"
>  #include "ts/IpMap.h"
> -#include "vector"
>  #include "ts/Vec.h"
>  #include "ProxyConfig.h"


This seems to be part of an unrelated(?) clean-up change.

> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/InkAPI.cc
> ----------------------------------------------------------------------
> diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
> index cabab42..540bec8 100644
> --- a/proxy/InkAPI.cc
> +++ b/proxy/InkAPI.cc
> @@ -21,8 +21,6 @@
>    limitations under the License.
>   */
>  
> -#ifndef TS_NO_API
> -
>  // Avoid complaining about the deprecated APIs.
>  // #define TS_DEPRECATED
>  
> @@ -369,6 +367,7 @@ tsapi const char * TS_NPN_PROTOCOL_SPDY_3   =
> "spdy/3";   // upcoming
>  tsapi const TSMLoc TS_NULL_MLOC = (TSMLoc)NULL;
>  
>  HttpAPIHooks *http_global_hooks = NULL;
> +LifecycleAPIHooks* lifecycle_hooks = NULL;
>  ConfigUpdateCbTable *global_config_cbs = NULL;
>  
>  static char traffic_server_version[128] = "";
> @@ -630,6 +629,13 @@ sdk_sanity_check_hook_id(TSHttpHookID id)
>    return TS_SUCCESS;
>  }
>  
> +TSReturnCode
> +sdk_sanity_check_lifecycle_hook_id(TSLifecycleHookID id)
> +{
> +  if (id<TS_LIFECYCLE_PORTS_INITIALIZED_HOOK || id> TS_LIFECYCLE_LAST_HOOK)

please try to use consistent spacing for </>, see below:

[wild-snipping]
> +template < typename ID, ID MAX_ID >
> +FeatureAPIHooks<ID,MAX_ID>::FeatureAPIHooks():
> +template < typename ID, ID MAX_ID >
> +FeatureAPIHooks<ID,MAX_ID>::~FeatureAPIHooks()
> +template < typename ID, ID MAX_ID >
> +void
> +FeatureAPIHooks<ID,MAX_ID>::clear()
> +template < typename ID, ID MAX_ID >
> +FeatureAPIHooks<ID,MAX_ID>::prepend(ID id, INKContInternal *cont)
> +template < typename ID, ID MAX_ID >
> +void
> +FeatureAPIHooks<ID,MAX_ID>::append(ID id, INKContInternal *cont)
> +template < typename ID, ID MAX_ID >
> +APIHook *
> +FeatureAPIHooks<ID,MAX_ID>::get(ID id)
> +template < typename ID, ID MAX_ID >
> +bool
> +FeatureAPIHooks<ID,MAX_ID>::has_hooks() const
> +class HttpAPIHooks : public FeatureAPIHooks<TSHttpHookID, TS_HTTP_LAST_HOOK>
> +class LifecycleAPIHooks : public FeatureAPIHooks<TSLifecycleHookID, TS_LIFECYCLE_LAST_HOOK>
[/wild-snipping]


> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/api/ts/ts.h.in
> ----------------------------------------------------------------------
> diff --git a/proxy/api/ts/ts.h.in b/proxy/api/ts/ts.h.in
> index 5ba4ebe..fc65e0e 100644
> --- a/proxy/api/ts/ts.h.in
> +++ b/proxy/api/ts/ts.h.in
> @@ -276,6 +276,55 @@ extern "C"
>    } TSHttpHookID;
>    #define TS_HTTP_READ_REQUEST_PRE_REMAP_HOOK TS_HTTP_PRE_REMAP_HOOK
>    /* backwards compat */
>  
> +  /** Plugin lifecycle hooks.
> +
> +      These are called during lifecycle events of a plugin. They
> +      should be set in the plugin initialization function. The
> +      continuation is invoked with an event ID specified for each
> hook
> +      and @c NULL for the event data.
> +
> +      TS_LIFECYCLE_PORTS_INITIALIZED_HOOK
> +
> +        called once, after the HTTP proxy port data structures have
> +        been initialized. In particular, SSL related calls that
> depend
> +        on accept endpoints may be invoked. After this hook is
> +        finished, the proxy port sockets are opened and connections
> +        are accepted.
> +
> +        Event: TS_EVENT_LIFECYCLE_PORTS_INITIALIZED
> +
> +      TS_LIFECYCLE_PORTS_READY_HOOK
> +
> +        called once, after the sockets have been opened and the
> accept
> +        threads have been started. That is, the ports are ready to
> +        accept connections. This is *not* guaranteed to be called
> +        before the first connection is accepted.
> +
> +        Event: TS_EVENT_LIFECYCLE_PORTS_READY_HOOK
> +
> +      TS_LIFECYCLE_CACHE_READY_HOOK
> +
> +        called once, after the cache has finished its
> +        initialization. It is either online or has failed when this
> +        hook is called.
> +
> +        Event: TS_EVENT_LIFECYCLE_CACHE_READY
> +
> +      Ordering guarantees:
> +
> +      - TS_LIFECYCLE_PORTS_INITIALIZED_HOOK before
> TS_LIFECYCLE_PORTS_READY_HOOK.
> +
> +      NOTE! ONLY the orderings EXPLICITLY mentioned above are
> guaranteed.
> +
> +   */
> +  typedef enum
> +  {
> +    TS_LIFECYCLE_PORTS_INITIALIZED_HOOK,
> +    TS_LIFECYCLE_PORTS_READY_HOOK,
> +    TS_LIFECYCLE_CACHE_READY_HOOK,
> +    TS_LIFECYCLE_LAST_HOOK
> +  } TSLifecycleHookID;
> +

Could you, following jpeach's example add a man page for this API?


[snip]
> --- a/proxy/http/HttpProxyServerMain.cc
> +++ b/proxy/http/HttpProxyServerMain.cc
> @@ -39,7 +39,6 @@
>  HttpAccept *plugin_http_accept = NULL;
>  HttpAccept *plugin_http_transparent_accept = 0;
>  
> -#if !defined(TS_NO_API)
>  static SLL<SSLNextProtocolAccept> ssl_plugin_acceptors;
>  static ProcessMutex ssl_plugin_mutex;
>  
> @@ -73,47 +72,43 @@ ssl_unregister_protocol(const char * protocol,
> Continuation * contp)
>    return true;
>  }
>  
> -#endif /* !defined(TS_NO_API) */
> -
>  /////////////////////////////////////////////////////////////////
>  //
>  //  main()
>  //
>  /////////////////////////////////////////////////////////////////
> -void
> -init_HttpProxyServer(void)
> -{
> -#ifndef INK_NO_REVERSE
> -  init_reverse_proxy();
> -#endif

reminder: https://issues.apache.org/jira/browse/TS-819
https://issues.apache.org/jira/browse/TS-1685
[snip]
>  
> -  // XXX although we make a good pretence here, I don't believe that
> NetProcessor::main_accept() ever actually returns
> -  // NULL. It would be useful to be able to detect errors and spew
> them here though.

hah...

> +  // Do the configuration defined ports.
> +  for ( int i = 0 , n = proxy_ports.length() ; i < n ; ++i ) {
> +    MakeHttpProxyAcceptor(HttpProxyAcceptors.add(), proxy_ports[i],
> n_accept_threads);
> +  }
> +
>  }
>  
>  void
> -start_HttpProxyServer(int accept_threads)
> +start_HttpProxyServer()
>  {
>    static bool called_once = false;
> +  HttpProxyPort::Group& proxy_ports = HttpProxyPort::global();
>  
>    ///////////////////////////////////
>    // start accepting connections   //
>    ///////////////////////////////////
>  
>    ink_assert(!called_once);
> -
> -  for ( int i = 0 , n = HttpProxyPort::global().length() ; i < n ;
> ++i ) {
> -    start_HttpProxyPort(HttpProxyPort::global()[i], accept_threads);
> +  ink_assert(proxy_ports.length() == HttpProxyAcceptors.length());
> +
> +  for ( int i = 0 , n = proxy_ports.length() ; i < n ; ++i ) {
> +    HttpProxyAcceptor& acceptor = HttpProxyAcceptors[i];
> +    HttpProxyPort& port = proxy_ports[i];
> +    if (port.isSSL()) {
> +      if (NULL == sslNetProcessor.main_accept(acceptor._accept,
> port.m_fd, acceptor._net_opt))
> +        return;
> +    } else {
> +      if (NULL == netProcessor.main_accept(acceptor._accept,
> port.m_fd, acceptor._net_opt))
> +        return;
> +    }
> +    // XXX although we make a good pretence here, I don't believe
> that NetProcessor::main_accept() ever actually returns
> +    // NULL. It would be useful to be able to detect errors and spew
> them here though.

oh.. I thought you had that fixed :\

>    }
>  
>  #if TS_HAS_TESTS
> @@ -204,6 +248,14 @@ start_HttpProxyServer(int accept_threads)
>      init_http_update_test();
>    }
>  #endif
> +
> +  // Alert plugins that connections will be accepted.
> +  APIHook* hook =
> lifecycle_hooks->get(TS_LIFECYCLE_PORTS_READY_HOOK);
> +  while (hook) {
> +    hook->invoke(TS_EVENT_LIFECYCLE_PORTS_READY, NULL);
> +    hook = hook->next();
> +  }
> +
>  }
>  
>  void
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpProxyServerMain.h
> ----------------------------------------------------------------------
> diff --git a/proxy/http/HttpProxyServerMain.h
> b/proxy/http/HttpProxyServerMain.h
> index 1d0502e..98769ff 100644
> --- a/proxy/http/HttpProxyServerMain.h
> +++ b/proxy/http/HttpProxyServerMain.h
> @@ -23,12 +23,14 @@
>  
>  struct HttpProxyPort;
>  
> -void init_HttpProxyServer(void);
> +/** Initialize all HTTP proxy port data structures needed to run.
> + */
> +void init_HttpProxyServer(int n_accept_threads = 0);
>  
>  /** Start the proxy server.
> -    The ports are contained in the HttpProxyPort global data.
> +    The port data should have been created by @c
> init_HttpProxyServer().
>  */
> -void start_HttpProxyServer(int accept_threads = 0);
> +void start_HttpProxyServer();
>  
>  void start_HttpProxyServerBackDoor(int port, int accept_threads =
>  0);
>  
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpSM.cc
> ----------------------------------------------------------------------
> diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
> index 1ebf842..4cfe0d1 100644
> --- a/proxy/http/HttpSM.cc
> +++ b/proxy/http/HttpSM.cc
> @@ -612,7 +612,7 @@ HttpSM::attach_client_session(HttpClientSession *
> client_vc, IOBufferReader * bu
>    HTTP_INCREMENT_DYN_STAT(http_current_client_transactions_stat);
>  
>    // Record api hook set state
> -  hooks_set = http_global_hooks->hooks_set | client_vc->hooks_set;
> +  hooks_set = http_global_hooks->has_hooks() ||
> client_vc->hooks_set;
>  
>    // Setup for parsing the header
>    ua_buffer_reader = buffer_reader;
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpTransact.cc
> ----------------------------------------------------------------------
> diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
> index 820663a..c8cc90f 100644
> --- a/proxy/http/HttpTransact.cc
> +++ b/proxy/http/HttpTransact.cc
> @@ -4617,7 +4617,6 @@ HttpTransact::handle_transform_ready(State* s)
>  void
>  HttpTransact::set_header_for_transform(State* s, HTTPHdr*
>  base_header)
>  {
> -#ifndef TS_NO_TRANSFORM
>    s->hdr_info.transform_response.create(HTTP_TYPE_RESPONSE);
>    s->hdr_info.transform_response.copy(base_header);
>  
> @@ -4628,9 +4627,6 @@ HttpTransact::set_header_for_transform(State*
> s, HTTPHdr* base_header)
>  
>    if (!s->cop_test_page)
>      DUMP_HEADER("http_hdrs", &s->hdr_info.transform_response,
>      s->state_machine_id, "Header To Transform");
> -#else
> -  ink_assert(!"transformation not supported\n");
> -#endif // TS_NO_TRANSFORM
>  }
>  
>  void
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/941784b2/proxy/http/HttpUpdateSM.cc
> ----------------------------------------------------------------------
> diff --git a/proxy/http/HttpUpdateSM.cc b/proxy/http/HttpUpdateSM.cc
> index 7b5eddf..6b47881 100644
> --- a/proxy/http/HttpUpdateSM.cc
> +++ b/proxy/http/HttpUpdateSM.cc
> @@ -116,7 +116,6 @@ HttpUpdateSM::handle_api_return()
>    }
>  
>    switch (t_state.next_action) {
> -#ifndef TS_NO_TRANSFORM
>    case HttpTransact::TRANSFORM_READ:
>      {
>        if (t_state.cache_info.transform_action ==
>        HttpTransact::CACHE_DO_WRITE) {
> @@ -154,7 +153,6 @@ HttpUpdateSM::handle_api_return()
>        }
>        break;
>      }
> -#endif //TS_NO_TRANSFORM
>    case HttpTransact::PROXY_INTERNAL_CACHE_WRITE:
>    case HttpTransact::SERVER_READ:
>    case HttpTransact::PROXY_INTERNAL_CACHE_NOOP:
>

only now do I realize that you've not just been removing
TS_NO_API, but also TS_NO_TRANSFORM from the code as well..

-- 
Igor Galić

Tel: +43 (0) 664 886 22 883
Mail: i.galic@brainsware.org
URL: http://brainsware.org/
GPG: 6880 4155 74BD FD7C B515  2EA5 4B1D 9E08 A097 C9AE