Skip to content
Closed
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
1 change: 1 addition & 0 deletions cmd/traffic_ctl/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ traffic_ctl_SOURCES = \
alarm.cc \
config.cc \
metric.cc \
plugin.cc \
server.cc \
storage.cc \
traffic_ctl.cc
Expand Down
52 changes: 52 additions & 0 deletions cmd/traffic_ctl/plugin.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/** @file

Plugin related sub commands.

@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.
*/

#include "traffic_ctl.h"

static int
plugin_msg(unsigned argc, const char **argv)
{
if (!CtrlProcessArguments(argc, argv, NULL, 0) || n_file_arguments != 2) {
return CtrlCommandUsage("plugin msg TAG DATA");
}

TSMgmtError error;

error = TSLifecycleMessage(file_arguments[0], file_arguments[1], strlen(file_arguments[1]) + 1);
if (error != TS_ERR_OKAY) {
CtrlMgmtError(error, "message '%s' not sent", file_arguments[0]);
return CTRL_EX_ERROR;
}

return CTRL_EX_OK;
}

int
subcommand_plugin(unsigned argc, const char **argv)
{
const subcommand commands[] = {
{plugin_msg, "msg", "Send message to plugins - a TAG and the message DATA"},
};

return CtrlGenericSubcommand("plugin", commands, countof(commands), argc, argv);
}
1 change: 1 addition & 0 deletions cmd/traffic_ctl/traffic_ctl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ main(int argc, const char **argv)
{subcommand_metric, "metric", "Manipulate performance metrics"},
{subcommand_server, "server", "Stop, restart and examine the server"},
{subcommand_storage, "storage", "Manipulate cache storage"},
{subcommand_plugin, "plugin", "Interact with plugins"},
};

BaseLogFile *base_log_file = new BaseLogFile("stderr");
Expand Down
1 change: 1 addition & 0 deletions cmd/traffic_ctl/traffic_ctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ int subcommand_config(unsigned argc, const char **argv);
int subcommand_metric(unsigned argc, const char **argv);
int subcommand_server(unsigned argc, const char **argv);
int subcommand_storage(unsigned argc, const char **argv);
int subcommand_plugin(unsigned argc, const char **argv);

// Exit status codes, following BSD's sysexits(3)
#define CTRL_EX_OK 0
Expand Down
11 changes: 11 additions & 0 deletions doc/appendices/command-line/traffic_ctl.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ of subcommands that control different aspects of Traffic Server:
Stop, restart and examine the server
:program:`traffic_ctl storage`
Manipulate cache storage
:program:`traffic_ctl plugin`
Interact with plugins.

Options
=======
Expand Down Expand Up @@ -254,6 +256,15 @@ traffic_ctl storage
that storage. This does not persist across restarts of the
:program:`traffic_server` process.

traffic_ctl plugin
-------------------
.. program:: traffic_ctl plugin
.. option:: msg TAG DATA

Send a message to plugins. All plugins that have hooked the :c:member:`TS_LIFECYCLE_MSG_HOOK`
will receive a callback for that hook. The :arg:`TAG` and :arg:`DATA` will be available to the
plugin hook processing.

Examples
========

Expand Down
9 changes: 9 additions & 0 deletions doc/developer-guide/api/functions/TSLifecycleHookAdd.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ is always called before another unless specifically mentioned.
Invoked with the event :c:data:`TS_EVENT_LIFECYCLE_CACHE_READY` and ``NULL``
data.

.. c:var:: TS_LIFECYCLE_MSG_HOOK

Called when triggered by an external process, such as :program:`traffic_ctl`.

Invoked with the event :c:data:`TS_EVENT_LIFECYCLE_MSG`. The data is an instance of the
:c:type:`TSPluginMsg`. This contains a *tag* which is a null terminated string and a data payload.
The payload cannot be assumed to be null terminated and is created by the external agent.


Ordering
========

Expand Down
2 changes: 2 additions & 0 deletions doc/developer-guide/api/types/TSLifecycleHookID.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Enumeration Members
.. c:member:: TSLifecycleHookID TS_LIFECYCLE_SERVER_SSL_CTX_INITIALIZED_HOOK

.. c:member:: TSLifecycleHookID TS_LIFECYCLE_CLIENT_SSL_CTX_INITIALIZED_HOOK

.. c:member:: TSLifecycleHookID MSG_HOOK

.. c:member:: TSLifecycleHookID TS_LIFECYCLE_LAST_HOOK

Expand Down
12 changes: 9 additions & 3 deletions example/lifecycle-plugin/lifecycle-plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@

#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
#include <ts/ts.h>

int
CallbackHandler(TSCont this, TSEvent id, void *no_data)
CallbackHandler(TSCont this, TSEvent id, void *data)
{
(void)this;
(void)no_data;
(void)this; // make compiler shut up about unused variable.
switch (id) {
case TS_EVENT_LIFECYCLE_PORTS_INITIALIZED:
TSDebug("lifecycle-plugin", "Proxy ports initialized");
Expand All @@ -44,6 +44,11 @@ CallbackHandler(TSCont this, TSEvent id, void *no_data)
case TS_EVENT_LIFECYCLE_CACHE_READY:
TSDebug("lifecycle-plugin", "Cache ready");
break;
case TS_EVENT_LIFECYCLE_MSG: {
TSPluginMsg *msg = (TSPluginMsg *)data;
TSDebug("lifecycle-plugin", "Message to '%s' - %" PRIu64 " bytes of data", msg->tag, msg->data_size);
break;
}
default:
TSDebug("lifecycle-plugin", "Unexpected event %d", id);
break;
Expand Down Expand Up @@ -105,6 +110,7 @@ TSPluginInit(int argc, const char *argv[])
TSLifecycleHookAdd(TS_LIFECYCLE_PORTS_INITIALIZED_HOOK, cb);
TSLifecycleHookAdd(TS_LIFECYCLE_PORTS_READY_HOOK, cb);
TSLifecycleHookAdd(TS_LIFECYCLE_CACHE_READY_HOOK, cb);
TSLifecycleHookAdd(TS_LIFECYCLE_MSG_HOOK, cb);

TSDebug("lifecycle-plugin", "online");

Expand Down
14 changes: 14 additions & 0 deletions lib/ts/apidefs.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ typedef struct {
char *support_email;
} TSPluginRegistrationInfo;

typedef struct {
char const* tag; ///< Message tag (null terminated).
void const* data; ///< Message data (payload)
size_t data_size; ///< Amount of message data.
} TSPluginMsg;

/**
This set of enums are possible values returned by
TSHttpHdrParseReq() and TSHttpHdrParseResp().
Expand Down Expand Up @@ -319,6 +325,12 @@ typedef enum {

Event: TS_EVENT_LIFECYCLE_CACHE_READY

TS_LIFECYCLE_MSG_HOOK

Called in response to an external agent. The data is a pointer to an instance of TSPluginMsg.

Event: TS_EVENT_LIFECYCLE_MSG

TS_LIFECYCLE_SERVER_SSL_CTX_INITIALIZED_HOOK

called every time after a server SSL_CTX has finished the initialization.
Expand Down Expand Up @@ -346,6 +358,7 @@ typedef enum {
TS_LIFECYCLE_CACHE_READY_HOOK,
TS_LIFECYCLE_SERVER_SSL_CTX_INITIALIZED_HOOK,
TS_LIFECYCLE_CLIENT_SSL_CTX_INITIALIZED_HOOK,
TS_LIFECYCLE_MSG_HOOK,
TS_LIFECYCLE_LAST_HOOK
} TSLifecycleHookID;

Expand Down Expand Up @@ -440,6 +453,7 @@ typedef enum {
TS_EVENT_LIFECYCLE_SERVER_SSL_CTX_INITIALIZED = 60021,
TS_EVENT_LIFECYCLE_CLIENT_SSL_CTX_INITIALIZED = 60022,
TS_EVENT_VCONN_PRE_ACCEPT = 60023,
TS_EVENT_LIFECYCLE_MSG = 60024,
TS_EVENT_MGMT_UPDATE = 60100,

/* EVENTS 60200 - 60202 for internal use */
Expand Down
1 change: 1 addition & 0 deletions mgmt/BaseManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
// so it's easier to do this than to try to encode an opcode and yet another
// case statement.
#define MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE 10011
#define MGMT_EVENT_LIFECYCLE_MESSAGE 10012

/***********************************************************************
*
Expand Down
3 changes: 3 additions & 0 deletions mgmt/ProcessManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ ProcessManager::handleMgmtMsgFromLM(MgmtMessageHdr *mh)
case MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE:
signalMgmtEntity(MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE, data_raw, mh->data_len);
break;
case MGMT_EVENT_LIFECYCLE_MESSAGE:
signalMgmtEntity(MGMT_EVENT_LIFECYCLE_MESSAGE, data_raw, mh->data_len);
break;
default:
mgmt_elog(stderr, 0, "[ProcessManager::pollLMConnection] unknown type %d\n", mh->msg_id);
break;
Expand Down
12 changes: 12 additions & 0 deletions mgmt/api/CoreAPI.cc
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,18 @@ StorageDeviceCmdOffline(const char *dev)
lmgmt->signalEvent(MGMT_EVENT_STORAGE_DEVICE_CMD_OFFLINE, dev);
return TS_ERR_OKAY;
}
/*-------------------------------------------------------------------------
* Lifecycle Message
*-------------------------------------------------------------------------
* Signal plugins.
*/
TSMgmtError
LifecycleMessage(char const *tag, void const *data, size_t data_size)
{
ink_release_assert(!"Not expected to reach here");
lmgmt->signalEvent(MGMT_EVENT_LIFECYCLE_MESSAGE, tag);
return TS_ERR_OKAY;
}
/**************************************************************************
* RECORD OPERATIONS
*************************************************************************/
Expand Down
9 changes: 5 additions & 4 deletions mgmt/api/CoreAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ TSProxyStateT ProxyStateGet();
TSMgmtError ProxyStateSet(TSProxyStateT state, TSCacheClearT clear);
TSMgmtError ServerBacktrace(unsigned options, char **trace);

TSMgmtError Reconfigure(); // TS reread config files
TSMgmtError Restart(unsigned options); // restart TM
TSMgmtError Bounce(unsigned options); // restart traffic_server
TSMgmtError StorageDeviceCmdOffline(const char *dev); // Storage device operation.
TSMgmtError Reconfigure(); // TS reread config files
TSMgmtError Restart(unsigned options); // restart TM
TSMgmtError Bounce(unsigned options); // restart traffic_server
TSMgmtError StorageDeviceCmdOffline(const char *dev); // Storage device operation.
TSMgmtError LifecycleMessage(char const *tag, void const *data, size_t data_size); // Lifecycle alert to plugins.
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess clang-format ate this? Can you move these comments above the line they refer to?

Copy link
Contributor

Choose a reason for hiding this comment

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

What's wrong with this as it is now? Don't fight clang-format, embrace the suck.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I see. The diff view in github made it look like the comments are on different lines. Sure, leave it as is :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Hahaha. Yes, I saw this as well and spent some time trying to fix my clang format before I realized I was reading the diff wrong. I couldn't figure out where this was coming from since the source file didn't have the split lines...


/***************************************************************************
* Record Operations
Expand Down
17 changes: 17 additions & 0 deletions mgmt/api/CoreAPIRemote.cc
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,23 @@ StorageDeviceCmdOffline(char const *dev)
return (ret == TS_ERR_OKAY) ? parse_generic_response(STORAGE_DEVICE_CMD_OFFLINE, main_socket_fd) : ret;
}

/*-------------------------------------------------------------------------
* LIfecycle Alert
*-------------------------------------------------------------------------
* Send alert to plugins
*/
TSMgmtError
LifecycleMessage(char const *tag, void const *data, size_t data_size)
{
TSMgmtError ret;
MgmtMarshallInt optype = LIFECYCLE_MESSAGE;
MgmtMarshallString mtag = const_cast<MgmtMarshallString>(tag);
MgmtMarshallData mdata = {const_cast<void *>(data), data_size};

ret = MGMTAPI_SEND_MESSAGE(main_socket_fd, LIFECYCLE_MESSAGE, &optype, &mtag, &mdata);
return (ret == TS_ERR_OKAY) ? parse_generic_response(LIFECYCLE_MESSAGE, main_socket_fd) : ret;
}

/***************************************************************************
* Record Operations
***************************************************************************/
Expand Down
1 change: 1 addition & 0 deletions mgmt/api/EventControlMain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ static const event_message_handler handlers[] = {
NULL, // STATS_RESET_CLUSTER
NULL, // STORAGE_DEVICE_CMD_OFFLINE
NULL, // RECORD_MATCH_GET
NULL, // LIFECYCLE_MESSAGE
};

static TSMgmtError
Expand Down
6 changes: 6 additions & 0 deletions mgmt/api/INKMgmtAPI.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1778,6 +1778,12 @@ TSStorageDeviceCmdOffline(char const *dev)
return StorageDeviceCmdOffline(dev);
}

tsapi TSMgmtError
TSLifecycleMessage(char const *tag, void const *data, size_t data_size)
{
return LifecycleMessage(tag, data, data_size);
}

/*--- diags output operations ---------------------------------------------*/
tsapi void
TSDiags(TSDiagsT mode, const char *fmt, ...)
Expand Down
3 changes: 3 additions & 0 deletions mgmt/api/NetworkMessage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static const struct NetCmdOperation requests[] = {
/* API_PING */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}},
/* SERVER_BACKTRACE */ {2, {MGMT_MARSHALL_INT, MGMT_MARSHALL_INT}},
/* RECORD_DESCRIBE_CONFIG */ {3, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT}},
/* LIFECYCLE_MESSAGE */ {3, {MGMT_MARSHALL_INT, MGMT_MARSHALL_STRING, MGMT_MARSHALL_DATA}},
};

// Responses always begin with a TSMgmtError code, followed by additional fields.
Expand Down Expand Up @@ -108,6 +109,7 @@ static const struct NetCmdOperation responses[] = {
MGMT_MARSHALL_INT /* order */, MGMT_MARSHALL_INT /* access */, MGMT_MARSHALL_INT /* update */,
MGMT_MARSHALL_INT /* updatetype */, MGMT_MARSHALL_INT /* checktype */,
MGMT_MARSHALL_INT /* source */, MGMT_MARSHALL_STRING /* checkexpr */}},
/* LIFECYCLE_MESSAGE */ {1, {MGMT_MARSHALL_INT}},
};

#define GETCMD(ops, optype, cmd) \
Expand Down Expand Up @@ -231,6 +233,7 @@ send_mgmt_error(int fd, OpType optype, TSMgmtError error)
return send_mgmt_response(fd, optype, &ecode, &strval);

case FILE_READ:
case LIFECYCLE_MESSAGE:
ink_release_assert(responses[optype].nfields == 3);
return send_mgmt_response(fd, optype, &ecode, &intval, &dataval);

Expand Down
1 change: 1 addition & 0 deletions mgmt/api/NetworkMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ typedef enum {
API_PING,
SERVER_BACKTRACE,
RECORD_DESCRIBE_CONFIG,
LIFECYCLE_MESSAGE,
UNDEFINED_OP /* This must be last */
} OpType;

Expand Down
27 changes: 26 additions & 1 deletion mgmt/api/TSControlMain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,29 @@ handle_record_describe(int fd, void *req, size_t reqlen)
ats_free(name);
return ret;
}
/**************************************************************************
* handle_lifecycle_message
*
* purpose: handle lifecyle message to plugins
* output: TS_ERR_xx
* note: None
*************************************************************************/
static TSMgmtError
handle_lifecycle_message(int fd, void *req, size_t reqlen)
{
MgmtMarshallInt optype;
MgmtMarshallInt err;
MgmtMarshallString tag;
MgmtMarshallData data;

err = recv_mgmt_request(req, reqlen, LIFECYCLE_MESSAGE, &optype, &tag, &data);
if (err == TS_ERR_OKAY) {
lmgmt->signalEvent(MGMT_EVENT_LIFECYCLE_MESSAGE, static_cast<char *>(req), reqlen);
}

return send_mgmt_response(fd, LIFECYCLE_MESSAGE, &err);
}
/**************************************************************************/

struct control_message_handler {
unsigned flags;
Expand Down Expand Up @@ -1183,7 +1206,9 @@ static const control_message_handler handlers[] = {
/* RECORD_MATCH_GET */ {0, handle_record_match},
/* API_PING */ {0, handle_api_ping},
/* SERVER_BACKTRACE */ {MGMT_API_PRIVILEGED, handle_server_backtrace},
/* RECORD_DESCRIBE_CONFIG */ {0, handle_record_describe}};
/* RECORD_DESCRIBE_CONFIG */ {0, handle_record_describe},
/* LIFECYCLE_MESSAGE */ {MGMT_API_PRIVILEGED, handle_lifecycle_message},
};

// This should use countof(), but we need a constexpr :-/
#define NUM_OP_HANDLERS (sizeof(handlers) / sizeof(handlers[0]))
Expand Down
7 changes: 7 additions & 0 deletions mgmt/api/include/mgmtapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>

/***************************************************************************
* System Specific Items
Expand Down Expand Up @@ -945,6 +946,12 @@ tsapi TSMgmtError TSBounce(unsigned options);
*/
tsapi TSMgmtError TSStorageDeviceCmdOffline(char const *dev);

/* TSLifecycleMessage: Send a lifecycle message to the plugins.
* @arg tag Alert tag string (null-terminated)
* @return Success
*/
tsapi TSMgmtError TSLifecycleMessage(char const *tag, void const *data, size_t data_size);

/*--- diags output operations ---------------------------------------------*/
/* TSDiags: enables users to manipulate run-time diagnostics, and print
* user-formatted notices, warnings and errors
Expand Down
Loading