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 <[email protected]> Authored: Thu Jul 18 09:25:42 2013 -0500 Committer: Alan M. Carroll <[email protected]> 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 = "[email protected]"; + + 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:
