Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions doc/developer-guide/api/functions/TSHttpArgs.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@
.. include:: ../../../common.defs
.. default-domain:: c


TSHttpArgs
**********

Synopsis
========

.. note::

This set of API is obsoleted as of ATS v9.0.0, and will be removed with ATS v10.0.0!
For details of the new APIs, see :ref:`tsuserargs`.


.. code-block:: cpp

#include <ts/ts.h>
Expand All @@ -35,8 +42,8 @@ Synopsis
.. function:: TSReturnCode TSHttpSsnArgIndexLookup(int arg_idx, const char ** name, const char ** description)
.. function:: void TSHttpTxnArgSet(TSHttpTxn txnp, int arg_idx, void * arg)
.. function:: void * TSHttpTxnArgGet(TSHttpTxn txnp, int arg_idx)
.. function:: void TSHttpSsnArgSet(TSHttpTxn txnp, int arg_idx, void * arg)
.. function:: void * TSHttpSsnArgGet(TSHttpTxn txnp, int arg_idx)
.. function:: void TSHttpSsnArgSet(TSHttpSsn ssnp, int arg_idx, void * arg)
.. function:: void * TSHttpSsnArgGet(TSHttpSsn ssnp, int arg_idx)

Description
===========
Expand Down
4 changes: 4 additions & 0 deletions doc/developer-guide/api/functions/TSTypes.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ more widely. Those are described on this page.

.. type:: TSThreadFunc

.. type:: TSUserArgType

An enum for the supported types of user arguments.

.. type:: TSUuidVersion

A version value for at :type:`TSUuid`.
Expand Down
112 changes: 112 additions & 0 deletions doc/developer-guide/api/functions/TSUserArgs.en.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
.. 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:: c

.. _tsuserargs:

TSUserArgs
**********

Synopsis
========

.. code-block:: cpp

#include <ts/ts.h>

typedef enum {
TS_USER_ARGS_TXN, ///< Transaction based.
TS_USER_ARGS_SSN, ///< Session based
TS_USER_ARGS_VCONN, ///< VConnection based
TS_USER_ARGS_GLB, ///< Global based
TS_USER_ARGS_COUNT ///< Fake enum, # of valid entries.
} TSUserArgType;

.. function:: TSReturnCode TSUserArgIndexReserve(TSUserArgType type, const char *name, const char *description, int *arg_idx)
.. function:: TSReturnCode TSUserArgIndexNameLookup(TSUserArgType type, const char *name, int *arg_idx, const char **description)
.. function:: TSReturnCode TSUserArgIndexLookup(TSUserArgType type, int arg_idx, const char **name, const char **description)
.. function:: void TSUserArgSet(void *data, int arg_idx, void *arg)
.. function:: void *TSUserArgGet(void *data, int arg_idx)

Description
===========

|TS| sessions, transactions, virtual connections and globally provide a fixed array of void pointers
that can be used by plugins to store information. This can be used to avoid creating a per session or
transaction continuations to hold data, or to communicate between plugins as the values in the array
are visible to any plugin which can access the session or transaction. The array values are opaque
to |TS| and it will not dereference nor release them. Plugins are responsible for cleaning up any
resources pointed to by the values or, if the values are simply values, there is no need for the plugin
to remove them after the session or transaction has completed.

To avoid collisions between plugins a plugin should first *reserve* an index in the array. A
plugin can reserve a slot of a particular type by calling :func:`TSUserArgIndexReserve`. The arguments are:

:arg:`type`
The type for which the plugin intend to reserve a slot. See :code:`TSUserArgType` above.

:arg:`name`
An identifying name for the plugin that reserved the index. Required.

:arg:`description`
An optional description of the use of the arg. This can be :code:`nullptr`.

:arg:`arg_idx`
A pointer to an :code:`int`. If an index is successfully reserved, the :code:`int` pointed at by this is
set to the reserved index. It is not modified if the call is unsuccessful.

The functions return :code:`TS_SUCCESS` if an index was reserved,
:code:`TS_ERROR` if not (most likely because all of the indices have already been reserved).
Generally this will be a file or library scope global which is set at plugin initialization. This
function is used in the example remap plugin :ts:git:`example/plugins/c-api/remap/remap.cc`. The index is stored
in the plugin global :code:`arg_index`. Transaction and session plugin argument indices are reserved
independently.

To look up the owner of a reserved index use :func:`TSUserArgIndexNameLookup`, with the appropriate type.
If :arg:`name` is found as an owner, the function returns :code:`TS_SUCCESS` and :arg:`arg_index` is
updated with the index reserved under that name. If :arg:`description` is not :code:`NULL` then
the character pointer to which it points will be updated to point at the description for that
reserved index. This enables communication between plugins where plugin "A" reserves an index under
a well known name and plugin "B" locates the index by looking it up under that name.

The owner of a reserved index can be found with :func:`TSUserArgIndexLookup`. If
:arg:`arg_index` is reserved then the function returns :code:`TS_SUCCESS` and the pointers referred
to by :arg:`name` and :arg:`description` are updated. :arg:`name` must point at a valid character
pointer but :arg:`description` can be :code:`NULL` in which case it is ignored.

Manipulating the array is simple. :func:`TSUserArgSet` sets the array slot at :arg:`arg_idx`, for the
particular type based on the provide data pointer. The values can be retrieved with the value from
:func:`TSUserArgGet`. Values that have not been set are :code:`NULL`. Note that both the setter and the getter are
context sensitive, based on the type (or value) of the data pointer:

============== =======================================================================
data type Semantics
============== =======================================================================
``TSHttpTxn`` The implicit context is for a transaction (``TS_USER_ARGS_TXN``)
``TSHttpSsn`` The implicit context is for a transaction (``TS_USER_ARGS_SSN``)
``TSVConn`` The implicit context is for a transaction (``TS_USER_ARGS_VCONN``)
``nullptr`` The implicit context is global (``TS_USER_ARGS_GLB``)
============== =======================================================================

Note that neither :func:`TSUserArgSet` nor :func:`TSUserArgGet` has any type safety on the :arg:`data`
parameters, being a ``void*`` pointer.


.. note:: Session arguments persist for the entire session, which means potentially across all transactions in that session.

.. note:: Following arg index reservations is conventional, it is not enforced.
8 changes: 6 additions & 2 deletions doc/developer-guide/api/functions/TSVConnArgs.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@
.. include:: ../../../common.defs
.. default-domain:: c

.. _TSVConnArgs:

TSVConnArgs
************

Synopsis
========

.. note::

This set of API is obsoleted as of ATS v9.0.0, and will be removed with ATS v10.0.0!
For details of the new APIs, see :ref:`tsuserargs`.


.. code-block:: cpp

#include <ts/ts.h>
Expand Down
16 changes: 8 additions & 8 deletions doc/developer-guide/design-documents/reloading-plugins.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,17 @@ The continuations created by the plugin will have a context member added to them
reference counting, when continuations are destroyed, and to handle events.


TSHttpArgs
TSUserArgs
----------

|TS| sessions and transactions provide a fixed array of void pointers that can be used by plugins
to store information. To avoid collisions between plugins a plugin should first *reserve* an index in the array.
|TS| sessions, transactions, virtual connections and globally provide a fixed array of void pointers that
can be used by plugins to store information. To avoid collisions between plugins a plugin should first
*reserve* an index in the array.

Since :c:func:`TSHttpTxnArgIndexReserve` and :c:func:`TSHttpSsnArgIndexReserve` are meant to be called during plugin
initialization we could end up "leaking" indices during plugin reload.
Hence it is necessary to make sure only one index is allocated per "plugin identifying name", current
:c:func:`TSHttpTxnArgIndexNameLookup` and :c:func:`TSHttpTxnArgIndexNameLookup` implementation assumes 1-1
index-to-name relationship as well.
Since :c:func:`TSUserArgIndexReserve` is meant to be called during plugin initialization we could end up
"leaking" indices during plugin reload. Hence it is necessary to make sure only one index is allocated per
"plugin identifying name", current :c:func:`TSUserArgIndexNameLookup` and
:c:func:`TSUserArgIndexLookup` implementation assumes 1-1 index-to-name relationship as well.


PluginFactory
Expand Down
6 changes: 3 additions & 3 deletions example/plugins/c-api/remap/remap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,9 @@ TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri)
}

// How to store plugin private arguments inside Traffic Server request processing block.
if (TSHttpTxnArgIndexReserve("remap_example", "Example remap plugin", &arg_index) == TS_SUCCESS) {
if (TSUserArgIndexReserve(TS_USER_ARGS_TXN, "remap_example", "Example remap plugin", &arg_index) == TS_SUCCESS) {
TSDebug(PLUGIN_NAME, "Save processing counter %" PRIu64 " inside request processing block\n", _processing_counter);
TSHttpTxnArgSet(rh, arg_index, (void *)_processing_counter); // save counter
TSUserArgSet(rh, arg_index, (void *)_processing_counter); // save counter
}
// How to cancel request processing and return error message to the client
// We will do it every other request
Expand Down Expand Up @@ -321,7 +321,7 @@ TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri)
void
TSRemapOSResponse(void *ih ATS_UNUSED, TSHttpTxn rh, int os_response_type)
{
void *data = TSHttpTxnArgGet(rh, arg_index); // read counter (we store it in TSRemapDoRemap function call)
void *data = TSUserArgGet(rh, arg_index); // read counter (we store it in TSRemapDoRemap function call)
int request_id = data ? static_cast<int *>(data)[0] : -1;

TSDebug(PLUGIN_NAME, "Read processing counter %d from request processing block\n", request_id);
Expand Down
8 changes: 4 additions & 4 deletions example/plugins/c-api/vconn_args/vconn_args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ vconn_arg_handler(TSCont contp, TSEvent event, void *edata)
case TS_EVENT_VCONN_START: {
// Testing set argument
int idx = 0;
while (TSVConnArgIndexReserve(PLUGIN_NAME, "test", &idx) == TS_SUCCESS) {
while (TSUserArgIndexReserve(TS_USER_ARGS_VCONN, PLUGIN_NAME, "test", &idx) == TS_SUCCESS) {
char *buf = static_cast<char *>(TSmalloc(64));
snprintf(buf, 64, "Test Arg Idx %d", idx);
TSVConnArgSet(ssl_vc, idx, (void *)buf);
TSUserArgSet(ssl_vc, idx, (void *)buf);
TSDebug(PLUGIN_NAME, "Successfully reserve and set arg #%d", idx);
}
last_arg = idx;
Expand All @@ -52,7 +52,7 @@ vconn_arg_handler(TSCont contp, TSEvent event, void *edata)
while (idx <= last_arg) {
const char *name = nullptr;
const char *desc = nullptr;
if (TSVConnArgIndexLookup(idx, &name, &desc) == TS_SUCCESS) {
if (TSUserArgIndexLookup(TS_USER_ARGS_VCONN, idx, &name, &desc) == TS_SUCCESS) {
TSDebug(PLUGIN_NAME, "Successful lookup for arg #%d: [%s] [%s]", idx, name, desc);
} else {
TSDebug(PLUGIN_NAME, "Failed lookup for arg #%d", idx);
Expand All @@ -65,7 +65,7 @@ vconn_arg_handler(TSCont contp, TSEvent event, void *edata)
// Testing argget and delete
int idx = 0;
while (idx <= last_arg) {
char *buf = static_cast<char *>(TSVConnArgGet(ssl_vc, idx));
char *buf = static_cast<char *>(TSUserArgGet(ssl_vc, idx));
if (buf) {
TSDebug(PLUGIN_NAME, "Successfully retrieve vconn arg #%d: %s", idx, buf);
TSfree(buf);
Expand Down
9 changes: 9 additions & 0 deletions include/ts/apidefs.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,15 @@ typedef enum {
TS_MGMT_SOURCE_ENV ///< Process environment variable.
} TSMgmtSource;

/// The User Arg type, used for Txn/Ssn/VConn user argument slots
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be problematic. Because it's C (and because in C++ it's not an enum class) these names are injected in to
the surrounding (global) scope. It would probably be better to prefix the enumeration names to reduce collisions. E.g.

typedef enum {
   USER_ARG_TXN,
   USER_ARG_SSN,
// ....
} TSUserTypeType;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, an oversight on my part, thanks for spotting. And for consistency, they should be prefixed TS_.

typedef enum {
TS_USER_ARGS_TXN, ///< Transaction based.
TS_USER_ARGS_SSN, ///< Session based
TS_USER_ARGS_VCONN, ///< VConnection based
TS_USER_ARGS_GLB, ///< Global based
TS_USER_ARGS_COUNT ///< Fake enum, # of valid entries.
} TSUserArgType;

typedef struct tsapi_file *TSFile;

typedef struct tsapi_mloc *TSMLoc;
Expand Down
49 changes: 28 additions & 21 deletions include/ts/ts.h
Original file line number Diff line number Diff line change
Expand Up @@ -1548,25 +1548,32 @@ tsapi void TSHttpTxnTransformedRespCache(TSHttpTxn txnp, int on);
tsapi void TSHttpTxnReenable(TSHttpTxn txnp, TSEvent event);
tsapi TSReturnCode TSHttpCacheReenable(TSCacheTxn txnp, const TSEvent event, const void *data, const uint64_t size);

tsapi void TSHttpTxnArgSet(TSHttpTxn txnp, int arg_idx, void *arg);
tsapi void *TSHttpTxnArgGet(TSHttpTxn txnp, int arg_idx);
tsapi void TSHttpSsnArgSet(TSHttpSsn ssnp, int arg_idx, void *arg);
tsapi void *TSHttpSsnArgGet(TSHttpSsn ssnp, int arg_idx);
tsapi void TSVConnArgSet(TSVConn connp, int arg_idx, void *arg);
tsapi void *TSVConnArgGet(TSVConn connp, int arg_idx);

/* The reserve API should only be use in TSAPI plugins, during plugin initialization! */
/* The lookup methods can be used anytime, but are best used during initialization as well,
/* The reserve API should only be use in TSAPI plugins, during plugin initialization!
The lookup methods can be used anytime, but are best used during initialization as well,
or at least "cache" the results for best performance. */
tsapi TSReturnCode TSHttpTxnArgIndexReserve(const char *name, const char *description, int *arg_idx);
tsapi TSReturnCode TSHttpTxnArgIndexNameLookup(const char *name, int *arg_idx, const char **description);
tsapi TSReturnCode TSHttpTxnArgIndexLookup(int arg_idx, const char **name, const char **description);
tsapi TSReturnCode TSHttpSsnArgIndexReserve(const char *name, const char *description, int *arg_idx);
tsapi TSReturnCode TSHttpSsnArgIndexNameLookup(const char *name, int *arg_idx, const char **description);
tsapi TSReturnCode TSHttpSsnArgIndexLookup(int arg_idx, const char **name, const char **description);
tsapi TSReturnCode TSVConnArgIndexReserve(const char *name, const char *description, int *arg_idx);
tsapi TSReturnCode TSVConnArgIndexNameLookup(const char *name, int *arg_idx, const char **description);
tsapi TSReturnCode TSVConnArgIndexLookup(int arg_idx, const char **name, const char **description);
tsapi TSReturnCode TSUserArgIndexReserve(TSUserArgType type, const char *name, const char *description, int *arg_idx);
tsapi TSReturnCode TSUserArgIndexNameLookup(TSUserArgType type, const char *name, int *arg_idx, const char **description);
tsapi TSReturnCode TSUserArgIndexLookup(TSUserArgType type, int arg_idx, const char **name, const char **description);
tsapi void TSUserArgSet(void *data, int arg_idx, void *arg);
tsapi void *TSUserArgGet(void *data, int arg_idx);

/* These are deprecated as of v9.0.0, and will be removed in v10.0.0 */
tsapi TS_DEPRECATED void TSHttpTxnArgSet(TSHttpTxn txnp, int arg_idx, void *arg);
tsapi TS_DEPRECATED void *TSHttpTxnArgGet(TSHttpTxn txnp, int arg_idx);
tsapi TS_DEPRECATED void TSHttpSsnArgSet(TSHttpSsn ssnp, int arg_idx, void *arg);
tsapi TS_DEPRECATED void *TSHttpSsnArgGet(TSHttpSsn ssnp, int arg_idx);
tsapi TS_DEPRECATED void TSVConnArgSet(TSVConn connp, int arg_idx, void *arg);
tsapi TS_DEPRECATED void *TSVConnArgGet(TSVConn connp, int arg_idx);

tsapi TS_DEPRECATED TSReturnCode TSHttpTxnArgIndexReserve(const char *name, const char *description, int *arg_idx);
tsapi TS_DEPRECATED TSReturnCode TSHttpTxnArgIndexNameLookup(const char *name, int *arg_idx, const char **description);
tsapi TS_DEPRECATED TSReturnCode TSHttpTxnArgIndexLookup(int arg_idx, const char **name, const char **description);
tsapi TS_DEPRECATED TSReturnCode TSHttpSsnArgIndexReserve(const char *name, const char *description, int *arg_idx);
tsapi TS_DEPRECATED TSReturnCode TSHttpSsnArgIndexNameLookup(const char *name, int *arg_idx, const char **description);
tsapi TS_DEPRECATED TSReturnCode TSHttpSsnArgIndexLookup(int arg_idx, const char **name, const char **description);
tsapi TS_DEPRECATED TSReturnCode TSVConnArgIndexReserve(const char *name, const char *description, int *arg_idx);
tsapi TS_DEPRECATED TSReturnCode TSVConnArgIndexNameLookup(const char *name, int *arg_idx, const char **description);
tsapi TS_DEPRECATED TSReturnCode TSVConnArgIndexLookup(int arg_idx, const char **name, const char **description);

tsapi void TSHttpTxnStatusSet(TSHttpTxn txnp, TSHttpStatus status);
tsapi TSHttpStatus TSHttpTxnStatusGet(TSHttpTxn txnp);
Expand Down Expand Up @@ -2504,9 +2511,9 @@ tsapi const char *TSHttpSsnClientProtocolStackContains(TSHttpSsn ssnp, char cons
tsapi const char *TSNormalizedProtocolTag(char const *tag);
tsapi const char *TSRegisterProtocolTag(char const *tag);

// If, for the given transaction, the URL has been remapped, this function puts the memory location of the "from" URL object in the
// variable pointed to by urlLocp, and returns TS_SUCCESS. (The URL object will be within memory allocated to the transaction
// object.) Otherwise, the function returns TS_ERROR.
// If, for the given transaction, the URL has been remapped, this function puts the memory location of the "from" URL object in
// the variable pointed to by urlLocp, and returns TS_SUCCESS. (The URL object will be within memory allocated to the
// transaction object.) Otherwise, the function returns TS_ERROR.
//
tsapi TSReturnCode TSRemapFromUrlGet(TSHttpTxn txnp, TSMLoc *urlLocp);

Expand Down
Loading