Skip to content
Open
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
18 changes: 18 additions & 0 deletions doc/appendices/command-line/traffic_ctl.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ of subcommands that control different aspects of Traffic Server:

:program:`traffic_ctl config`
Manipulate and display configuration records
:program:`traffic_ctl cache`
Invalidate cached objects
:program:`traffic_ctl metric`
Manipulate performance and status metrics
:program:`traffic_ctl server`
Expand Down Expand Up @@ -1137,6 +1139,22 @@ traffic_ctl server
$ traffic_ctl server debug disable
■ TS Runtime debug set to »OFF(0)«

.. _traffic-control-command-cache:

traffic_ctl cache
-----------------

.. program:: traffic_ctl cache
.. option:: clear

:ref:`admin_cache_clear`

Invalidate cached HTTP objects in the global cache-generation namespace without restarting |TS|. This advances
:ts:cv:`proxy.config.http.cache.generation`, causing subsequent cache lookups to use a new key namespace. Remap rules that
override this configuration have independent namespaces and are not affected. The invalidated data remains on cache storage until
it is overwritten through normal cache operation. The configuration change applies to the running process and is not persisted to
:file:`records.yaml`.

.. _traffic-control-command-storage:

traffic_ctl storage
Expand Down
57 changes: 57 additions & 0 deletions doc/developer-guide/jsonrpc/jsonrpc-api.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,8 @@ Example with stats meta:
JSONRPC API
===========

* `admin_cache_clear`_

* `admin_lookup_records`_


Expand Down Expand Up @@ -471,6 +473,61 @@ JSONRPC API

* `get_connection_tracker_info`_


Cache
=====

.. _admin_cache_clear:

admin_cache_clear
-----------------

|method|

Description
~~~~~~~~~~~

Invalidate cached HTTP objects in the global cache-generation namespace without restarting |TS|. The method advances
:ts:cv:`proxy.config.http.cache.generation`, causing subsequent cache lookups to use a new key namespace. Remap rules that override
this configuration have independent namespaces and are not affected. The invalidated data remains on cache storage until it is
overwritten through normal cache operation. The configuration change applies to the running process and is not persisted to
:file:`records.yaml`.

Parameters
~~~~~~~~~~

* ``params``: Omitted

Result
~~~~~~

The response will contain the default `success_response` or an error. :ref:`jsonrpc-node-errors`.

Examples
~~~~~~~~

Request:

.. code-block:: json
:linenos:

{
"id": "9db0608c-b696-46f4-b865-1b5dc8a80d38",
"jsonrpc": "2.0",
"method": "admin_cache_clear"
}

Response:

.. code-block:: json
:linenos:

{
"jsonrpc": "2.0",
"result": "success",
"id": "9db0608c-b696-46f4-b865-1b5dc8a80d38"
}

.. _jsonapi-management-records:


Expand Down
31 changes: 31 additions & 0 deletions include/mgmt/rpc/handlers/cache/Cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/** @file

Cache JSON-RPC handlers.

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

#pragma once

#include "mgmt/rpc/jsonrpc/JsonRPCManager.h"

namespace rpc::handlers::cache
{
swoc::Rv<YAML::Node> clear_cache(std::string_view const &id, YAML::Node const &params);
} // namespace rpc::handlers::cache
1 change: 1 addition & 0 deletions src/mgmt/rpc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ target_link_libraries(jsonrpc_server PUBLIC ts::jsonrpc_protocol)

add_library(
rpcpublichandlers STATIC
handlers/cache/Cache.cc
handlers/common/ErrorUtils.cc
handlers/common/RecordsUtils.cc
handlers/config/Configuration.cc
Expand Down
69 changes: 69 additions & 0 deletions src/mgmt/rpc/handlers/cache/Cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/** @file

Cache JSON-RPC handlers.

@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 "mgmt/rpc/handlers/cache/Cache.h"
#include "mgmt/rpc/handlers/common/ErrorUtils.h"

#include "records/RecCore.h"

#include <limits>
#include <mutex>

namespace
{
constexpr char CACHE_GENERATION_RECORD[] = "proxy.config.http.cache.generation";
std::mutex generation_mutex;
} // namespace

namespace rpc::handlers::cache
{
swoc::Rv<YAML::Node>
clear_cache(std::string_view const & /* id ATS_UNUSED */, YAML::Node const & /* params ATS_UNUSED */)
{
namespace err = rpc::handlers::errors;

swoc::Rv<YAML::Node> resp;
std::lock_guard lock{generation_mutex};
auto generation = RecGetRecordInt(CACHE_GENERATION_RECORD);

if (!generation) {
resp.errata()
.assign(std::error_code{err::Codes::CONFIGURATION})
.note("Could not read cache generation record '{}'.", CACHE_GENERATION_RECORD);
return resp;
}

RecInt next_generation = 0;
if (*generation >= 0 && *generation < std::numeric_limits<RecInt>::max()) {
next_generation = *generation + 1;
}

if (RecSetRecordInt(CACHE_GENERATION_RECORD, next_generation, REC_SOURCE_DEFAULT) != REC_ERR_OKAY) {
resp.errata()
.assign(std::error_code{err::Codes::CONFIGURATION})
.note("Could not advance cache generation record '{}'.", CACHE_GENERATION_RECORD);
}

return resp;
}
} // namespace rpc::handlers::cache
20 changes: 20 additions & 0 deletions src/traffic_ctl/CtrlCommands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,26 @@ ConfigCommand::config_show_file_registry()
_printer->write_output(invoke_rpc(ConfigShowFileRegistryRequest{}));
}
//------------------------------------------------------------------------------------------------------------------------------------
CacheCommand::CacheCommand(ts::Arguments *args) : CtrlCommand(args)
{
auto printOpts = parse_print_opts(args);

if (get_parsed_arguments()->get(CLEAR_STR)) {
_printer = std::make_unique<GenericPrinter>(printOpts);
_invoked_func = [&]() { clear(); };
}
}

void
CacheCommand::clear()
{
CacheClearRequest request;

auto response = invoke_rpc(request);

_printer->write_output(response);
}
//------------------------------------------------------------------------------------------------------------------------------------
MetricCommand::MetricCommand(ts::Arguments *args) : RecordCommand(args)
{
BasePrinter::Options printOpts{parse_print_opts(args)};
Expand Down
11 changes: 11 additions & 0 deletions src/traffic_ctl/CtrlCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ class ConfigCommand : public RecordCommand
ConfigCommand(ts::Arguments *args);
};
// -----------------------------------------------------------------------------------------------------------------------------------
class CacheCommand : public CtrlCommand
{
public:
CacheCommand(ts::Arguments *args);

private:
static inline const std::string CLEAR_STR{"clear"};

void clear();
};
// -----------------------------------------------------------------------------------------------------------------------------------
class MetricCommand : public RecordCommand
{
static inline const std::string MONITOR_STR{"monitor"};
Expand Down
8 changes: 8 additions & 0 deletions src/traffic_ctl/jsonrpc/CtrlRPCRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ struct ConfigSetRecordResponse {
std::vector<UpdatedRec> data;
};
//------------------------------------------------------------------------------------------------------------------------------------
struct CacheClearRequest : shared::rpc::ClientRequest {
std::string
get_method() const override
{
return "admin_cache_clear";
}
};
//------------------------------------------------------------------------------------------------------------------------------------
struct HostStatusLookUpResponse {
struct HostStatusInfo {
std::string hostName;
Expand Down
6 changes: 6 additions & 0 deletions src/traffic_ctl/traffic_ctl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ main([[maybe_unused]] int argc, const char **argv)
.add_option("--watch", "-w", "Execute a program periodically. Watch interval(in seconds) can be passed.", "", 1, "-1", "watch");

auto &config_command = parser.add_command("config", "Manipulate configuration records").require_commands();
auto &cache_command = parser.add_command("cache", "Manage the document cache").require_commands();
auto &metric_command = parser.add_command("metric", "Manipulate performance metrics").require_commands();
auto &server_command = parser.add_command("server", "Stop, restart and examine the server").require_commands();
auto &storage_command = parser.add_command("storage", "Manipulate cache storage").require_commands();
Expand Down Expand Up @@ -201,6 +202,10 @@ main([[maybe_unused]] int argc, const char **argv)
config_command.add_command("registry", "Show configuration file registry", Command_Execute)
.add_example_usage("traffic_ctl config registry");

// cache commands
cache_command.add_command("clear", "Advance the global cache generation", "", 0, Command_Execute)
.add_example_usage("traffic_ctl cache clear");

// ssl-multicert subcommand
auto &ssl_multicert_command =
config_command.add_command("ssl-multicert", "Manage ssl_multicert configuration").require_commands();
Expand Down Expand Up @@ -330,6 +335,7 @@ main([[maybe_unused]] int argc, const char **argv)
}

static const std::map<std::string, std::function<std::unique_ptr<CtrlCommand>(ts::Arguments *)>> factories = {
{"cache", [](ts::Arguments *a) { return std::make_unique<CacheCommand>(a); } },
{"metric", [](ts::Arguments *a) { return std::make_unique<MetricCommand>(a); } },
{"server", [](ts::Arguments *a) { return std::make_unique<ServerCommand>(a); } },
{"storage", [](ts::Arguments *a) { return std::make_unique<StorageCommand>(a); } },
Expand Down
5 changes: 5 additions & 0 deletions src/traffic_server/RpcAdminPubHandlers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "mgmt/rpc/jsonrpc/JsonRPC.h"

// Admin API Implementation headers.
#include "mgmt/rpc/handlers/cache/Cache.h"
#include "mgmt/rpc/handlers/config/Configuration.h"
#include "mgmt/rpc/handlers/hostdb/HostDB.h"
#include "mgmt/rpc/handlers/records/Records.h"
Expand All @@ -34,6 +35,10 @@ namespace rpc::admin
void
register_admin_jsonrpc_handlers()
{
// Cache
using namespace rpc::handlers::cache;
rpc::add_method_handler("admin_cache_clear", &clear_cache, &core_ats_rpc_service_provider_handle, {{rpc::RESTRICTED_API}});

// Config
using namespace rpc::handlers::config;
rpc::add_method_handler("admin_config_set_records", &set_config_records, &core_ats_rpc_service_provider_handle,
Expand Down
12 changes: 6 additions & 6 deletions tests/gold_tests/cache/cache-generation-clear.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = "gold/hit_default-1.gold"

# Call traffic_ctrl to set new generation
# Clear the cache through traffic_ctl. The command advances the initial generation from -1 to 0.
tr = Test.AddTestRun()
tr.Processes.Default.Command = f'traffic_ctl --debug config set proxy.config.http.cache.generation 77'
tr.Processes.Default.Command = 'traffic_ctl cache clear'
tr.Processes.Default.ForceUseShell = False
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Env = ts.Env # set the environment for traffic_control to run in
Expand All @@ -80,16 +80,16 @@
ts.Variables.port, objectid),
ts=ts)
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = "gold/miss_default77.gold"
tr.Processes.Default.Streams.All = "gold/miss_default0.gold"

# new generation should should now hit.
# The new generation should now hit.
tr = Test.AddTestRun()
tr.MakeCurlCommand(
'"http://127.0.0.1:{0}/default/cache/10/{1}" -H "x-debug: x-cache,x-cache-key,via,x-cache-generation" --verbose'.format(
ts.Variables.port, objectid),
ts=ts)
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = "gold/hit_default77.gold"
tr.Processes.Default.Streams.All = "gold/hit_default0.gold"

# should still hit.
tr = Test.AddTestRun()
Expand All @@ -98,4 +98,4 @@
ts.Variables.port, objectid),
ts=ts)
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = "gold/hit_default77.gold"
tr.Processes.Default.Streams.All = "gold/hit_default0.gold"
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
< Server: ATS/{}
< X-Cache-Key: http://127.0.0.1/cache/10/{}
< X-Cache: hit-fresh
< X-Cache-Generation: 77
< X-Cache-Generation: 0
{}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
< Server: ATS/{}
< X-Cache-Key: http://127.0.0.1/cache/10/{}
< X-Cache: miss
< X-Cache-Generation: 77
< X-Cache-Generation: 0
{}