diff --git a/doc/developer-guide/api/functions/TSHttpTxnNextHopNamedStrategyGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategyFind.en.rst similarity index 90% rename from doc/developer-guide/api/functions/TSHttpTxnNextHopNamedStrategyGet.en.rst rename to doc/developer-guide/api/functions/TSHttpTxnNextHopStrategyFind.en.rst index 949d92346dc..d51ccb2d245 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnNextHopNamedStrategyGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategyFind.en.rst @@ -18,8 +18,8 @@ .. default-domain:: cpp -TSHttpTxnNextHopNamedStrategyGet -******************************** +TSHttpTxnNextHopStrategyFind +**************************** Synopsis ======== @@ -28,7 +28,7 @@ Synopsis #include -.. function:: void const* TSHttpTxnNextHopNamedStrategyGet(TSHttpTxn txnp, const char *name) +.. function:: TSStrategy TSHttpTxnNextHopStrategyFind(TSHttpTxn txnp, const char *name) Description =========== diff --git a/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategyGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategyGet.en.rst index c609511bbe5..02399658863 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategyGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategyGet.en.rst @@ -28,7 +28,7 @@ Synopsis #include -.. function:: void const* TSHttpTxnNextHopStrategyGet(TSHttpTxn txnp) +.. function:: TSStrategy TSHttpTxnNextHopStrategyGet(TSHttpTxn txnp) Description =========== diff --git a/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategySet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategySet.en.rst index 33ca4b6266a..8a5fe268913 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategySet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnNextHopStrategySet.en.rst @@ -28,7 +28,7 @@ Synopsis #include -.. function:: void TSHttpTxnNextHopStrategySet(TSHttpTxn txnp, void const* strategy) +.. function:: void TSHttpTxnNextHopStrategySet(TSHttpTxn txnp, TSStrategy strategy) Description =========== @@ -39,7 +39,7 @@ nullptr to indicate that parent.config will be used instead. Plugins can get a strategy by name by calling :func:`TSHttpTxnNextHopStrategyGet` to get the current transaction's -active strategy or :func:`TSHttpTxnNextHopNamedStrategyGet` to +active strategy or :func:`TSHttpTxnNextHopStrategyFind` to look up a strategy by name using the transaction's pointer to the NextHopStrategyFactory strategy database. @@ -53,4 +53,4 @@ NextHopStrategyFactory strategy database. See Also ======== -:func:`TSHttpTxnNextHopStrategyGet`, :func:`TSHttpTxnNextHopNamedStrategyGet`. +:func:`TSHttpTxnNextHopStrategyGet`, :func:`TSHttpTxnNextHopStrategyFind`. diff --git a/doc/developer-guide/api/functions/TSHttpNextHopStrategyNameGet.en.rst b/doc/developer-guide/api/functions/TSNextHopStrategyNameGet.en.rst similarity index 83% rename from doc/developer-guide/api/functions/TSHttpNextHopStrategyNameGet.en.rst rename to doc/developer-guide/api/functions/TSNextHopStrategyNameGet.en.rst index 273b636fb82..a1ab5f79e03 100644 --- a/doc/developer-guide/api/functions/TSHttpNextHopStrategyNameGet.en.rst +++ b/doc/developer-guide/api/functions/TSNextHopStrategyNameGet.en.rst @@ -18,8 +18,8 @@ .. default-domain:: cpp -TSHttpNextHopStrategyNameGet -**************************** +TSNextHopStrategyNameGet +************************ Synopsis ======== @@ -28,13 +28,13 @@ Synopsis #include -.. function:: char const* TSHttpNextHopStrategyNameGet(void const* strategy) +.. function:: char const* TSNextHopStrategyNameGet(TSStrategy strategy) Description =========== -Gets the name associated with the provided strategy. -This may be nullptr indicating that parent.config is in use. +Gets the name associated with the provided strategy pointer. +This may be nullptr which indicates that parent.config is in use. .. note:: diff --git a/doc/developer-guide/api/functions/TSRemapNextHopStrategyFind.en.rst b/doc/developer-guide/api/functions/TSRemapNextHopStrategyFind.en.rst new file mode 100644 index 00000000000..2fb11ccfacd --- /dev/null +++ b/doc/developer-guide/api/functions/TSRemapNextHopStrategyFind.en.rst @@ -0,0 +1,52 @@ +.. 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. + +.. include:: ../../../common.defs + +.. default-domain:: cpp + +TSRemapNextHopStrategyFind +************************** + +Synopsis +======== + +.. code-block:: cpp + + #include + +.. function:: TSStrategy TSRemapNextHopStrategyFind(const char *name) + +Description +=========== + +Gets a pointer to the specified :arg:`name` NextHopSelectionStrategy. +This may be nullptr indicating that no strategy exists with the given name. + +This function may ONLY be called during TSRemapNewInstance. +The resulting strategy pointer is valid for all subsequent transactions. + +.. note:: + + This returned pointer must not be freed and the contents must not + be changed. + Strategy pointers held by plugins will become invalid when ATS + configs are reloaded and should be reset with :func:`TSRemapNewInstance` + +See Also +======== + +:func:`TSRemapNextHopStrategySet` diff --git a/doc/developer-guide/api/functions/TSRemapNextHopStrategyGet.en.rst b/doc/developer-guide/api/functions/TSRemapNextHopStrategyGet.en.rst new file mode 100644 index 00000000000..3302bf5645b --- /dev/null +++ b/doc/developer-guide/api/functions/TSRemapNextHopStrategyGet.en.rst @@ -0,0 +1,52 @@ +.. 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. + +.. include:: ../../../common.defs + +.. default-domain:: cpp + +TSRemapNextHopStrategyGet +************************* + +Synopsis +======== + +.. code-block:: cpp + + #include + +.. function:: TSStrategy TSRemapNextHopStrategyGet() + +Description +=========== + +Gets a pointer to the current remap rule being loaded. +This may be nullptr indicating that parent.config is in use. + +This function may ONLY be called during TSRemapNewInstance. +The resulting strategy pointer is valid for all subsequent transactions. + +.. note:: + + This strategy pointer must not be freed and the contents must not + be changed. + Strategy pointers held by plugins will become invalid when ATS + configs are reloaded and should be reset with :func:`TSRemapNewInstance` + +See Also +======== + +:func:`TSRemapNextHopStrategySet` diff --git a/doc/developer-guide/api/functions/TSRemapNextHopStrategySet.en.rst b/doc/developer-guide/api/functions/TSRemapNextHopStrategySet.en.rst new file mode 100644 index 00000000000..07611d20016 --- /dev/null +++ b/doc/developer-guide/api/functions/TSRemapNextHopStrategySet.en.rst @@ -0,0 +1,56 @@ +.. 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. + +.. include:: ../../../common.defs + +.. default-domain:: cpp + +TSRemapNextHopNameGet +*********************** + +Synopsis +======== + +.. code-block:: cpp + + #include + +.. function:: void TSRemapNextHopStrategySet(TSStrategy strategy) + +Description +=========== + +Sets the next hop strategy for the currently loading remap rule. +This :arg:`strategy` pointer must be a valid strategy and can be +nullptr to indicate that parent.config will be used instead. + +Plugins can get a strategy by name by calling +:func:`TSRemapNextHopStrategyGet` to get the current transaction's active +strategy or :func:`TSRemapNextHopStrategyFind` to look up a strategy by +name using the loading remap rule's pointer to the NextHopStrategyFactory +strategy database. + +.. note:: + + This strategy pointer must not be freed and the contents must not + be changed. + Strategy pointers held by plugins will become invalid when ATS + configs are reloaded and should be reset with :func:`TSRemapNewInstance` + +See Also +======== + +:func:`TSRemapNextHopStrategyGet`, :func:`TSRemapNextHopStrategyFind`. diff --git a/doc/developer-guide/api/functions/TSTypes.en.rst b/doc/developer-guide/api/functions/TSTypes.en.rst index 422cb0fb0e0..a638da603bb 100644 --- a/doc/developer-guide/api/functions/TSTypes.en.rst +++ b/doc/developer-guide/api/functions/TSTypes.en.rst @@ -335,6 +335,8 @@ more widely. Those are described on this page. .. type:: TSFetchSM .. type:: TSFetchEvent +.. type:: TSStrategy + .. type:: TSHttpPriority The abstract type of the various HTTP priority implementations. diff --git a/include/proxy/http/remap/UrlMapping.h b/include/proxy/http/remap/UrlMapping.h index dabab071185..b15b329959a 100644 --- a/include/proxy/http/remap/UrlMapping.h +++ b/include/proxy/http/remap/UrlMapping.h @@ -36,6 +36,7 @@ #include "tscore/List.h" class NextHopSelectionStrategy; +class NextHopStrategyFactory; /** * Used to store http referrer strings (and/or regexp) @@ -112,9 +113,15 @@ class url_mapping bool ip_allow_check_enabled_p = false; acl_filter_rule *filter = nullptr; // acl filtering (linked list of rules) LINK(url_mapping, link); // For use with the main Queue linked list holding all the mapping - NextHopSelectionStrategy *strategy = nullptr; - std::string remapKey; - std::atomic _hitCount = 0; // counter can overflow + + NextHopSelectionStrategy *strategy = nullptr; + NextHopStrategyFactory *strategyFactory = nullptr; + + std::string remapKey; + std::atomic _hitCount = 0; // counter can overflow + + // For use with the strategies API to be called during TSRemapNewInstance. + static inline url_mapping *instance = nullptr; int getRank() const diff --git a/include/ts/apidefs.h.in b/include/ts/apidefs.h.in index 0bc28141907..a201e56d92b 100644 --- a/include/ts/apidefs.h.in +++ b/include/ts/apidefs.h.in @@ -1080,6 +1080,7 @@ using TSHostLookupResult = struct tsapi_hostlookupresult *; using TSAIOCallback = struct tsapi_aiocallback *; using TSAcceptor = struct tsapi_net_accept *; using TSRemapPluginInfo = struct tsapi_remap_plugin_info *; +using TSStrategy = struct tsapi_strategy *; using TSFetchSM = struct tsapi_fetchsm *; diff --git a/include/ts/ts.h b/include/ts/ts.h index 8ea727082fe..19f2c09577d 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -1579,10 +1579,22 @@ void TSHttpTxnErrorBodySet(TSHttpTxn txnp, char *buf, size_t buflength, char *mi */ char *TSHttpTxnErrorBodyGet(TSHttpTxn txnp, size_t *buflength, char **mimetype); +/** + Retrieves a handle to the named strategy in the strategy table. + Returns nullptr if no strategy is found. + This uses the current transaction's state machine to get + access to UrlRewrite's NextHopStrategyFactory. + It's preferable to retrieve strategies during TSRemapNewInstance. + + @param txnp HTTP transaction which holds the strategy table. + @param name of the strategy to look up. + + */ +TSStrategy TSHttpTxnNextHopStrategyFind(TSHttpTxn txnp, const char *name); + /** Sets the Transaction's Next Hop Parent Strategy. - Calling this after TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK will - result in bad behavior. + Must be called before parent selection logic is required. You can get this strategy pointer by calling TSHttpTxnParentStrategyGet(). @@ -1590,7 +1602,7 @@ char *TSHttpTxnErrorBodyGet(TSHttpTxn txnp, size_t *buflength, char **mimetype); @param pointer to the given strategy. */ -void TSHttpTxnNextHopStrategySet(TSHttpTxn txnp, void const *strategy); +void TSHttpTxnNextHopStrategySet(TSHttpTxn txnp, TSStrategy strategy); /** Retrieves a pointer to the current next hop selection strategy. @@ -1601,32 +1613,55 @@ void TSHttpTxnNextHopStrategySet(TSHttpTxn txnp, void const *strategy); @param txnp HTTP transaction whose next hop strategy to get. */ -void const *TSHttpTxnNextHopStrategyGet(TSHttpTxn txnp); +TSStrategy TSHttpTxnNextHopStrategyGet(TSHttpTxn txnp); /** Returns either null pointer or null terminated pointer to name. - DO NOT FREE. + DO NOT FREE. This value may be a nullptr due to: - parent proxying not enabled - no parent selection strategy (using parent.config) - @param txnp HTTP transaction whose next hop strategy to get. + @param pointer to the NextHopStrategy. */ -char const *TSHttpNextHopStrategyNameGet(void const *strategy); +char const *TSNextHopStrategyNameGet(TSStrategy strategy); /** Retrieves a pointer to the named strategy in the strategy table. - Returns nullptr if no strategy is set. - This uses the current transaction's state machine to get - access to UrlRewrite's NextHopStrategyFactory. + This can only be called during TSRemapNewInstance. + DO NOT FREE. + + Returns nullptr if no strategy found. + This uses the currently being loaded RemapConfig NextHopStrategyFactory. - @param txnp HTTP transaction which holds the strategy table. @param name of the strategy to look up. */ -void const *TSHttpTxnNextHopNamedStrategyGet(TSHttpTxn txnp, const char *name); +TSStrategy TSRemapNextHopStrategyFind(const char *name); + +/** + Retrieves a pointer to remap rule strategy pointer. + This can only be called during TSRemapNewInstance. + DO NOT FREE. + + Returns nullptr if no strategy assigned. + + */ +TSStrategy TSRemapNextHopStrategyGet(); + +/** + Sets the remap rule's next hop strategy. + This can only be called during TSRemapNewInstance. + DO NOT FREE. + + This strategy must be present in the loading NextHopStrategyFactory. + + @param handle to the strategy to set. + + */ +void TSRemapNextHopStrategySet(TSStrategy strategy); /** Sets the parent proxy name and port. The string hostname is copied diff --git a/plugins/header_rewrite/conditions.cc b/plugins/header_rewrite/conditions.cc index 11357033e2b..1a1090461d5 100644 --- a/plugins/header_rewrite/conditions.cc +++ b/plugins/header_rewrite/conditions.cc @@ -1539,12 +1539,13 @@ ConditionNextHop::append_value(std::string &s, const Resources &res) s.append(std::to_string(port)); } break; case NEXT_HOP_STRATEGY: { - char const *const name = TSHttpNextHopStrategyNameGet(res.state.txnp); - if (nullptr != name) { + TSStrategy const strategy = TSHttpTxnNextHopStrategyGet(res.state.txnp); + if (nullptr != strategy) { + char const *const name = TSNextHopStrategyNameGet(strategy); Dbg(pi_dbg_ctl, "Appending '%s' to evaluation value", name); s.append(name); } else { - Dbg(pi_dbg_ctl, "NextHopStrategyName is empty"); + Dbg(pi_dbg_ctl, "NextHopStrategy is empty"); } } break; default: diff --git a/plugins/header_rewrite/operators.cc b/plugins/header_rewrite/operators.cc index c8c4f66b953..c67ea30d3ee 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -1639,45 +1639,48 @@ void OperatorSetNextHopStrategy::initialize(Parser &p) { Operator::initialize(p); + _stratname = p.get_arg(); - _value.set_value(p.get_arg(), this); - Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::initialie: %s", _value.get_value().c_str()); + if (_stratname.empty() || "null" == _stratname) { + Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy() 'clear'"); + } else { + _strategy = TSRemapNextHopStrategyFind(_stratname.c_str()); + if (nullptr == _strategy) { + TSError("[%s] Failed to get strategy '%s'", PLUGIN_NAME, _stratname.c_str()); + _apply = false; + } else { + Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy() '%s'", _stratname.c_str()); + } + } } void OperatorSetNextHopStrategy::initialize_hooks() { - add_allowed_hook(TS_HTTP_READ_REQUEST_HDR_HOOK); add_allowed_hook(TS_REMAP_PSEUDO_HOOK); } bool OperatorSetNextHopStrategy::exec(const Resources &res) const { - if (!res.state.txnp) { - TSError("[%s] OperatorSetNextHopStrategy() failed. Transaction is null", PLUGIN_NAME); + if (!_apply) { + Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::exec: do nothing"); + return true; } - auto const txnp = res.state.txnp; - - std::string value; - _value.append_value(value, res); - - // Setting an empty strategy clears it for either parent.config or remap to - if ("null" == value || value.empty()) { - Dbg(pi_dbg_ctl, "Clearing strategy"); - TSHttpTxnNextHopStrategySet(txnp, nullptr); - return true; + if (!txnp) { + TSError("[%s] OperatorSetNextHopStrategy() failed. Transaction is null", PLUGIN_NAME); + return false; } - void const *const stratptr = TSHttpTxnNextHopNamedStrategyGet(txnp, value.c_str()); - if (nullptr == stratptr) { - TSWarning("[%s] Failed to get strategy '%s'", PLUGIN_NAME, value.c_str()); + if (nullptr == _strategy) { + Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::exec: Clearing strategy"); } else { - Dbg(pi_dbg_ctl, " Setting strategy '%s'", value.c_str()); - TSHttpTxnNextHopStrategySet(txnp, stratptr); + Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::exec: Setting strategy to '%s'", _stratname.c_str()); } + TSHttpTxnNextHopStrategySet(txnp, _strategy); + return true; } diff --git a/plugins/header_rewrite/operators.h b/plugins/header_rewrite/operators.h index 179bd799a05..6f8c26d36a8 100644 --- a/plugins/header_rewrite/operators.h +++ b/plugins/header_rewrite/operators.h @@ -675,7 +675,9 @@ class OperatorSetNextHopStrategy : public Operator bool exec(const Resources &res) const override; private: - Value _value; + bool _apply = true; + std::string _stratname; + TSStrategy _strategy = nullptr; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/lua/ts_lua_http.cc b/plugins/lua/ts_lua_http.cc index cac64dc44cf..3771ca5e447 100644 --- a/plugins/lua/ts_lua_http.cc +++ b/plugins/lua/ts_lua_http.cc @@ -535,9 +535,9 @@ ts_lua_http_get_next_hop_strategy(lua_State *L) GET_HTTP_CONTEXT(http_ctx, L); - void const *const stratptr = TSHttpTxnNextHopStrategyGet(http_ctx->txnp); + TSStrategy const stratptr = TSHttpTxnNextHopStrategyGet(http_ctx->txnp); if (nullptr != stratptr) { - name = TSHttpNextHopStrategyNameGet(stratptr); + name = TSNextHopStrategyNameGet(stratptr); } if (name == nullptr) { @@ -569,7 +569,7 @@ ts_lua_http_set_next_hop_strategy(lua_State *L) Dbg(dbg_ctl, "Clearning strategy (use parent.config)"); TSHttpTxnNextHopStrategySet(http_ctx->txnp, nullptr); } else { - void const *const stratptr = TSHttpTxnNextHopNamedStrategyGet(http_ctx->txnp, name); + TSStrategy const stratptr = TSHttpTxnNextHopStrategyFind(http_ctx->txnp, name); if (nullptr == stratptr) { TSError("[ts_lua][%s] Failed get next hop strategy name '%s'", __FUNCTION__, name); } else { diff --git a/plugins/regex_remap/regex_remap.cc b/plugins/regex_remap/regex_remap.cc index de38ba23787..5ac14b80588 100644 --- a/plugins/regex_remap/regex_remap.cc +++ b/plugins/regex_remap/regex_remap.cc @@ -227,12 +227,17 @@ class RemapRegex return _lowercase_substitutions; } inline bool - has_strategy() const + has_strategy_option() const { return _has_strategy; } inline std::string const & - strategy() const + strategy_name_option() const + { + return _strategy_name; + } + inline TSStrategy + strategy_option() const { return _strategy; } @@ -273,8 +278,9 @@ class RemapRegex int _connect_timeout = -1; int _dns_timeout = -1; - bool _has_strategy = false; - std::string _strategy = {}; + bool _has_strategy = false; + std::string _strategy_name = {}; + TSStrategy _strategy = nullptr; Override *_first_override = nullptr; int _sub_pos[MAX_SUBS]; @@ -323,8 +329,15 @@ RemapRegex::initialize(const std::string ®, const std::string &sub, const std } else if (opt.compare(start, 23, "lowercase_substitutions") == 0) { _lowercase_substitutions = true; } else if (opt.compare(start, 8, "strategy") == 0) { - _has_strategy = true; - _strategy = opt_val; + _has_strategy = true; + _strategy_name = opt_val; + if (!_strategy_name.empty() && "null" != _strategy_name) { + _strategy = TSRemapNextHopStrategyFind(_strategy_name.c_str()); + if (nullptr == _strategy) { + TSError("[%s] Unable to resolve strategy: '%s'", PLUGIN_NAME, opt_val.c_str()); + _has_strategy = false; // disable the strategy action + } + } } else if (opt_val.size() <= 0) { // All other options have a required value TSError("[%s] Malformed options: %s", PLUGIN_NAME, opt.c_str()); @@ -987,20 +1000,14 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri) Dbg(dbg_ctl, "Setting DNS timeout to %d", re->dns_timeout_option()); TSHttpTxnDNSTimeoutSet(txnp, re->dns_timeout_option()); } - if (re->has_strategy()) { - auto const &strat = re->strategy(); - if (strat.empty() || "null" == strat) { + if (re->has_strategy_option()) { + auto const strat = re->strategy_option(); + if (nullptr == strat) { Dbg(dbg_ctl, "Clearing strategy (use parent.config)"); - TSHttpTxnNextHopStrategySet(txnp, nullptr); } else { - void const *const stratptr = TSHttpTxnNextHopNamedStrategyGet(txnp, strat.c_str()); - if (nullptr == stratptr) { - Dbg(dbg_ctl, "No strategy found with name '%s'", strat.c_str()); - } else { - Dbg(dbg_ctl, "Setting strategy to %s", strat.c_str()); - TSHttpTxnNextHopStrategySet(txnp, stratptr); - } + Dbg(dbg_ctl, "Setting strategy to %s", re->strategy_name_option().c_str()); } + TSHttpTxnNextHopStrategySet(txnp, strat); } bool lowercase_substitutions = false; if (re->lowercase_substitutions_option() == true) { diff --git a/src/api/InkAPI.cc b/src/api/InkAPI.cc index f1869503f02..62fea55094c 100644 --- a/src/api/InkAPI.cc +++ b/src/api/InkAPI.cc @@ -4991,57 +4991,92 @@ TSHttpTxnServerRequestBodySet(TSHttpTxn txnp, char *buf, int64_t buflength) s->internal_msg_buffer_fast_allocator_size = -1; } -void const * +TSStrategy TSHttpTxnNextHopStrategyGet(TSHttpTxn txnp) { sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); auto sm = reinterpret_cast(txnp); - return static_cast(sm->t_state.next_hop_strategy); + return reinterpret_cast(sm->t_state.next_hop_strategy); +} + +TSStrategy +TSHttpTxnNextHopStrategyFind(TSHttpTxn txnp, const char *name) +{ + sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); + sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS); + + auto sm = reinterpret_cast(txnp); + + sdk_assert(sdk_sanity_check_null_ptr((void *)sm->m_remap) == TS_SUCCESS); + sdk_assert(sdk_sanity_check_null_ptr((void *)sm->m_remap->strategyFactory) == TS_SUCCESS); + + // HttpSM has a reference count handle to UrlRewrite which has a + // pointer to NextHopStrategyFactory + NextHopSelectionStrategy *const strategy = sm->m_remap->strategyFactory->strategyInstance(name); + + return reinterpret_cast(strategy); } void -TSHttpTxnNextHopStrategySet(TSHttpTxn txnp, void const *stratptr) +TSHttpTxnNextHopStrategySet(TSHttpTxn txnp, TSStrategy stratptr) { sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); // null strategy falls back to parent.config - // sdk_assert(sdk_sanity_check_null_ptr(strategy) == TS_SUCCESS); - - auto sm = reinterpret_cast(txnp); - auto strategy = reinterpret_cast(stratptr); + // sdk_assert(sdk_sanity_check_null_ptr(stratptr) == TS_SUCCESS); - sm->t_state.next_hop_strategy = const_cast(strategy); + auto sm = reinterpret_cast(txnp); + sm->t_state.next_hop_strategy = reinterpret_cast(stratptr); } -char const * -TSHttpNextHopStrategyNameGet(void const *stratptr) +TSStrategy +TSRemapNextHopStrategyFind(const char *name) { - char const *name = nullptr; - if (nullptr != stratptr) { - auto strategy = reinterpret_cast(stratptr); - name = strategy->strategy_name.c_str(); + auto const um = url_mapping::instance; + sdk_assert(sdk_sanity_check_null_ptr((void *)um) == TS_SUCCESS); + + NextHopSelectionStrategy *strategy = nullptr; + + if (nullptr != um->strategyFactory) { + // HttpSM has a reference count handle to UrlRewrite which manages + // the NextHopStrategyFactory pointer. + strategy = um->strategyFactory->strategyInstance(name); } - return name; + return reinterpret_cast(strategy); } -void const * -TSHttpTxnNextHopNamedStrategyGet(TSHttpTxn txnp, const char *name) +void +TSRemapNextHopStrategySet(TSStrategy strategy) { - sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); - sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS); + auto const um = url_mapping::instance; + sdk_assert(sdk_sanity_check_null_ptr((void *)um) == TS_SUCCESS); + // null strategy falls back to parent.config + // sdk_assert(sdk_sanity_check_null_ptr(stratptr) == TS_SUCCESS); - auto sm = reinterpret_cast(txnp); + um->strategy = reinterpret_cast(strategy); +} - sdk_assert(sdk_sanity_check_null_ptr((void *)sm->m_remap) == TS_SUCCESS); - sdk_assert(sdk_sanity_check_null_ptr((void *)sm->m_remap->strategyFactory) == TS_SUCCESS); +TSStrategy +TSRemapNextHopStrategyGet() +{ + auto const um = url_mapping::instance; + sdk_assert(sdk_sanity_check_null_ptr((void *)um) == TS_SUCCESS); + return reinterpret_cast(um->strategy); +} - // HttpSM has a reference count handle to UrlRewrite which has a - // pointer to NextHopStrategyFactory - NextHopSelectionStrategy const *const strat = sm->m_remap->strategyFactory->strategyInstance(name); +char const * +TSNextHopStrategyNameGet(TSStrategy stratptr) +{ + static char const *const nullname = "null"; + char const *name = nullname; + if (nullptr != stratptr) { + auto strategy = reinterpret_cast(stratptr); + name = strategy->strategy_name.c_str(); + } - return static_cast(strat); + return name; } TSReturnCode diff --git a/src/api/InkAPITest.cc b/src/api/InkAPITest.cc index 21d80fc57f3..fcb1f83a684 100644 --- a/src/api/InkAPITest.cc +++ b/src/api/InkAPITest.cc @@ -3511,7 +3511,7 @@ mytest_handler(TSCont contp, TSEvent event, void *data) // Set the strategy pointer here // this is an invalid pointer but the contents don't matter for this test. - TSHttpTxnNextHopStrategySet(static_cast(data), (void *)0x01); + TSHttpTxnNextHopStrategySet(static_cast(data), (TSStrategy)0x01); checkHttpTxnClientReqGet(test, data); diff --git a/src/proxy/http/remap/RemapConfig.cc b/src/proxy/http/remap/RemapConfig.cc index 73d74b8bf42..be8efa02f19 100644 --- a/src/proxy/http/remap/RemapConfig.cc +++ b/src/proxy/http/remap/RemapConfig.cc @@ -90,7 +90,6 @@ clear_xstr_array(char *v[], size_t vsize) } BUILD_TABLE_INFO::BUILD_TABLE_INFO() - { memset(this->paramv, 0, sizeof(this->paramv)); memset(this->argv, 0, sizeof(this->argv)); @@ -1430,6 +1429,9 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) } } + // Set up for ts API for strategies + new_mapping->strategyFactory = bti->rewrite->strategyFactory; + // Check "remap" plugin options and load .so object if ((bti->remap_optflg & REMAP_OPTFLG_PLUGIN) != 0 && (maptype == mapping_type::FORWARD_MAP || maptype == mapping_type::FORWARD_MAP_REFERER || @@ -1438,6 +1440,9 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) int plugin_found_at = 0; int jump_to_argc = 0; + // Set up for ts API for strategies + url_mapping::instance = new_mapping; + // this loads the first plugin if (!remap_load_plugin(bti->argv, bti->argc, new_mapping, errStrBuf, sizeof(errStrBuf), 0, &plugin_found_at, bti->rewrite)) { @@ -1445,6 +1450,7 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) errStr = errStrBuf; goto MAP_ERROR; } + // this loads any subsequent plugins (if present) while (plugin_found_at) { jump_to_argc += plugin_found_at; @@ -1455,6 +1461,8 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) goto MAP_ERROR; } } + + url_mapping::instance = nullptr; } } @@ -1476,6 +1484,8 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) snprintf(errBuf, sizeof(errBuf), "%s failed to add remap rule at %s line %d: %s", modulePrefix, path, cln + 1, errStr); Error("%s", errBuf); + url_mapping::instance = nullptr; + delete reg_map; delete new_mapping; return false;