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..851bfb100de --- /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 + +TSRemapNextHopStrategySet +************************* + +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 8888e1568ff..7fa78920087 100644 --- a/include/proxy/http/remap/UrlMapping.h +++ b/include/proxy/http/remap/UrlMapping.h @@ -38,6 +38,7 @@ #include "tscore/List.h" class NextHopSelectionStrategy; +class NextHopStrategyFactory; struct CacheHostRecord; /** @@ -115,11 +116,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; + NextHopSelectionStrategy *strategy = nullptr; + NextHopStrategyFactory *strategyFactory = nullptr; std::string remapKey; std::atomic _hitCount = 0; // counter can overflow std::atomic volume_host_rec = nullptr; + // For use with the strategies API to be called during TSRemapNewInstance. + static inline thread_local url_mapping *instance = nullptr; + CacheHostRecord * getVolumeHostRec() const { diff --git a/include/ts/apidefs.h.in b/include/ts/apidefs.h.in index e82eb7f0aea..945f2538610 100644 --- a/include/ts/apidefs.h.in +++ b/include/ts/apidefs.h.in @@ -1155,6 +1155,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 9b62d64fe8c..ec49e7ca42f 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -1625,10 +1625,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(). @@ -1636,7 +1648,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. @@ -1647,32 +1659,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 faf4a19a52a..5642600942c 100644 --- a/plugins/header_rewrite/conditions.cc +++ b/plugins/header_rewrite/conditions.cc @@ -1598,12 +1598,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 9a3238d3af7..a7cf7f2f557 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -1642,45 +1642,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 eee90c35810..96b552cd74a 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 6eca1e8c33a..fa6b4e87702 100644 --- a/plugins/regex_remap/regex_remap.cc +++ b/plugins/regex_remap/regex_remap.cc @@ -223,12 +223,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; } @@ -269,8 +274,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]; @@ -319,8 +325,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 = std::move(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()); @@ -975,20 +988,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 529ff6d2029..980bb15b43b 100644 --- a/src/api/InkAPI.cc +++ b/src/api/InkAPI.cc @@ -4996,57 +4996,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 eac60ccd3fc..69e7ff801ae 100644 --- a/src/api/InkAPITest.cc +++ b/src/api/InkAPITest.cc @@ -3541,7 +3541,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 95d51af39cf..8347658451a 100644 --- a/src/proxy/http/remap/RemapConfig.cc +++ b/src/proxy/http/remap/RemapConfig.cc @@ -94,7 +94,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)); @@ -1504,6 +1503,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 || @@ -1512,6 +1514,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)) { @@ -1519,6 +1524,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; @@ -1529,6 +1535,8 @@ remap_parse_config_bti(const char *path, BUILD_TABLE_INFO *bti) goto MAP_ERROR; } } + + url_mapping::instance = nullptr; } } @@ -1550,6 +1558,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;