Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

TS-1487: Fix startup order, add lifecycle hooks

  • Loading branch information...
commit 941784b2a1ff3bcaf8a9a78337dbf121d6a21cf6 1 parent ea560ce
@SolidWallOfCode SolidWallOfCode authored
View
2  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.
View
13 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])
View
2  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
View
4 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;
View
116 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");
+}
View
1  example/lifecycle-plugin/readme.txt
@@ -0,0 +1 @@
+This prints debug messages about the lifecycle hooks.
View
3  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
View
25 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;
View
7 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
View
2  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}
View
1  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"
View
73 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
View
89 proxy/InkAPIInternal.h
@@ -133,36 +133,100 @@ class APIHook
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 @@ class ConfigUpdateCbTable
void api_init();
extern HttpAPIHooks *http_global_hooks;
+extern LifecycleAPIHooks* lifecycle_hooks;
extern ConfigUpdateCbTable *global_config_cbs;
#endif /* __INK_API_INTERNAL_H__ */
View
65 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);
View
4 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
View
55 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);
View
2  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);
View
176 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
View
8 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);
View
2  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;
View
4 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
View
2  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:
Please sign in to comment.
Something went wrong with that request. Please try again.