You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by dm...@apache.org on 2024/03/12 09:29:46 UTC
(trafficserver) branch master updated: libsowc - remove legacy Errata. (#10986)
This is an automated email from the ASF dual-hosted git repository.
dmeden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new ab95203602 libsowc - remove legacy Errata. (#10986)
ab95203602 is described below
commit ab952036020bb2ba15a69caaec362719f209e16b
Author: Damian Meden <dm...@apache.org>
AuthorDate: Tue Mar 12 10:29:39 2024 +0100
libsowc - remove legacy Errata. (#10986)
libsowc - remove legacy Errata.
---------
Co-authored-by: Alan M. Carroll <am...@apache.org>
---
include/iocore/net/YamlSNIConfig.h | 5 +-
include/mgmt/config/FileManager.h | 22 +-
include/mgmt/rpc/handlers/common/ErrorUtils.h | 22 +-
include/mgmt/rpc/handlers/common/RecordsUtils.h | 3 +-
include/mgmt/rpc/handlers/config/Configuration.h | 4 +-
include/mgmt/rpc/handlers/plugins/Plugins.h | 2 +-
include/mgmt/rpc/handlers/records/Records.h | 16 +-
include/mgmt/rpc/handlers/server/Server.h | 4 +-
include/mgmt/rpc/handlers/storage/Storage.h | 4 +-
include/mgmt/rpc/jsonrpc/Context.h | 8 +-
include/mgmt/rpc/jsonrpc/Defs.h | 11 +-
include/mgmt/rpc/jsonrpc/JsonRPCManager.h | 9 +-
include/mgmt/rpc/jsonrpc/json/YAMLCodec.h | 14 +-
include/mgmt/rpc/server/CommBase.h | 2 +-
include/mgmt/rpc/server/IPCSocketServer.h | 4 +-
include/tscore/Errata.h | 1047 --------------------
include/tsutil/ts_errata.h | 82 +-
lib/swoc/include/swoc/Errata.h | 1 +
src/api/InkAPI.cc | 4 +-
src/iocore/net/SSLSNIConfig.cc | 4 +-
src/iocore/net/YamlSNIConfig.cc | 14 +-
src/iocore/net/unit_tests/test_YamlSNIConfig.cc | 10 +-
src/mgmt/config/AddConfigFilesHere.cc | 1 -
src/mgmt/config/FileManager.cc | 45 +-
src/mgmt/rpc/CMakeLists.txt | 14 +-
src/mgmt/rpc/handlers/common/ErrorUtils.cc | 69 ++
src/mgmt/rpc/handlers/config/Configuration.cc | 22 +-
src/mgmt/rpc/handlers/plugins/Plugins.cc | 4 +-
src/mgmt/rpc/handlers/records/Records.cc | 10 +-
src/mgmt/rpc/handlers/server/Server.cc | 14 +-
src/mgmt/rpc/handlers/storage/Storage.cc | 16 +-
src/mgmt/rpc/jsonrpc/Context.cc | 4 +-
src/mgmt/rpc/jsonrpc/JsonRPCManager.cc | 45 +-
.../rpc/jsonrpc/unit_tests/test_basic_protocol.cc | 46 +-
src/mgmt/rpc/server/IPCSocketServer.cc | 16 +-
src/mgmt/rpc/server/unit_tests/test_rpcserver.cc | 6 +-
src/proxy/CMakeLists.txt | 2 +-
src/proxy/HostStatus.cc | 18 +-
src/proxy/http/HttpConfig.cc | 2 +
src/traffic_cache_tool/CacheTool.cc | 1 +
src/tscore/CMakeLists.txt | 2 -
src/tscore/Errata.cc | 269 -----
src/tscore/unit_tests/test_Errata.cc | 60 --
src/tsutil/CMakeLists.txt | 2 +
src/tsutil/ts_errata.cc | 34 +
.../jsonrpc/plugins/jsonrpc_plugin_handler_test.cc | 2 +-
46 files changed, 417 insertions(+), 1579 deletions(-)
diff --git a/include/iocore/net/YamlSNIConfig.h b/include/iocore/net/YamlSNIConfig.h
index 6ac8d76119..aa5ec2008d 100644
--- a/include/iocore/net/YamlSNIConfig.h
+++ b/include/iocore/net/YamlSNIConfig.h
@@ -32,8 +32,7 @@
#include "iocore/net/SSLTypes.h"
#include "tsutil/ts_ip.h"
-
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
#define TSDECL(id) constexpr char TS_##id[] = #id
TSDECL(fqdn);
@@ -129,7 +128,7 @@ struct YamlSNIConfig {
void populate_sni_actions(action_vector_t &actions);
};
- ts::Errata loader(const std::string &cfgFilename);
+ swoc::Errata loader(const std::string &cfgFilename);
std::vector<YamlSNIConfig::Item> items;
};
diff --git a/include/mgmt/config/FileManager.h b/include/mgmt/config/FileManager.h
index 60792e7142..28262acf51 100644
--- a/include/mgmt/config/FileManager.h
+++ b/include/mgmt/config/FileManager.h
@@ -23,19 +23,19 @@
#pragma once
-#include "tscore/ink_mutex.h"
-#include "tscore/List.h"
-
-#include "tscore/Errata.h"
-
-#include "mgmt/rpc/jsonrpc/JsonRPC.h"
-
#include <unordered_map>
#include <string_view>
#include <forward_list>
#include <mutex>
#include <functional>
+#include "tsutil/ts_errata.h"
+
+#include "tscore/ink_mutex.h"
+#include "tscore/List.h"
+
+#include <mgmt/rpc/jsonrpc/JsonRPC.h>
+
class ConfigUpdateCbTable;
class FileManager
@@ -121,7 +121,7 @@ public:
time_t fileLastModified = 0;
};
- using CallbackType = std::function<ts::Errata(std::string const &, std::string const &)>;
+ using CallbackType = std::function<swoc::Errata(std::string const &, std::string const &)>;
~FileManager();
FileManager(const FileManager &obj) = delete;
@@ -139,8 +139,8 @@ public:
_configCallbacks.push_front(std::move(f));
}
- ts::Errata fileChanged(std::string const &fileName, std::string const &configName);
- ts::Errata rereadConfig();
+ swoc::Errata fileChanged(std::string const &fileName, std::string const &configName);
+ swoc::Errata rereadConfig();
bool isConfigStale();
void configFileChild(const char *parent, const char *child);
@@ -169,7 +169,7 @@ private:
void addFileHelper(const char *fileName, const char *configName, bool root_access_needed, bool isRequired,
ConfigManager *parentConfig);
/// JSONRPC endpoint
- ts::Rv<YAML::Node> get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms);
+ swoc::Rv<YAML::Node> get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms);
};
void initializeRegistry(); // implemented in AddConfigFilesHere.cc
diff --git a/include/mgmt/rpc/handlers/common/ErrorUtils.h b/include/mgmt/rpc/handlers/common/ErrorUtils.h
index 1cf1f4b881..8d7d750c0a 100644
--- a/include/mgmt/rpc/handlers/common/ErrorUtils.h
+++ b/include/mgmt/rpc/handlers/common/ErrorUtils.h
@@ -26,7 +26,8 @@
#include <system_error>
#include <string_view>
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
+#include "tsutil/ts_bw_format.h"
namespace rpc::handlers::errors
{
@@ -38,7 +39,7 @@ namespace rpc::handlers::errors
// With this we try to avoid error codes collision. You can also use same error Code for all your
// errors.
enum Codes : unsigned int {
- CONFIGURATION = 1,
+ CONFIGURATION = 999, // go past @c errno
METRIC = 1000,
RECORD = 2000,
SERVER = 3000,
@@ -48,19 +49,24 @@ enum Codes : unsigned int {
GENERIC = 30000
};
-static constexpr int ERRATA_DEFAULT_ID{1};
+std::error_code make_error_code(rpc::handlers::errors::Codes e);
template <typename... Args>
-static inline ts::Errata
+static inline swoc::Errata
make_errata(int code, std::string_view fmt, Args &&...args)
{
- std::string text;
- return ts::Errata{}.push(ERRATA_DEFAULT_ID, code, swoc::bwprint(text, fmt, std::forward<Args>(args)...));
+ return swoc::Errata(std::error_code(code, std::generic_category()), fmt, std::forward<Args>(args)...);
}
-static inline ts::Errata
+static inline swoc::Errata
make_errata(int code, std::string_view text)
{
- return ts::Errata{}.push(ERRATA_DEFAULT_ID, code, text);
+ return swoc::Errata(std::error_code(code, std::generic_category()), std::string(text));
}
} // namespace rpc::handlers::errors
+namespace std
+{
+template <> struct is_error_code_enum<rpc::handlers::errors::Codes> : true_type {
+};
+
+} // namespace std
diff --git a/include/mgmt/rpc/handlers/common/RecordsUtils.h b/include/mgmt/rpc/handlers/common/RecordsUtils.h
index a8b047a614..22be1e9416 100644
--- a/include/mgmt/rpc/handlers/common/RecordsUtils.h
+++ b/include/mgmt/rpc/handlers/common/RecordsUtils.h
@@ -22,13 +22,14 @@
#include <tuple>
+#include "tsutil/ts_errata.h"
+
#include "mgmt/rpc/handlers/common/convert.h"
#include "mgmt/rpc/handlers/common/ErrorUtils.h"
#include "records/RecCore.h"
#include "../../../../../src/records/P_RecCore.h"
#include "tscore/Diags.h"
-#include "tscore/Errata.h"
#include <yaml-cpp/yaml.h>
diff --git a/include/mgmt/rpc/handlers/config/Configuration.h b/include/mgmt/rpc/handlers/config/Configuration.h
index a79fc6d483..e6f00b5aea 100644
--- a/include/mgmt/rpc/handlers/config/Configuration.h
+++ b/include/mgmt/rpc/handlers/config/Configuration.h
@@ -24,7 +24,7 @@
namespace rpc::handlers::config
{
-ts::Rv<YAML::Node> set_config_records(std::string_view const &id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> reload_config(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> set_config_records(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> reload_config(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::config
diff --git a/include/mgmt/rpc/handlers/plugins/Plugins.h b/include/mgmt/rpc/handlers/plugins/Plugins.h
index 4f9e079e8a..250b90d4e6 100644
--- a/include/mgmt/rpc/handlers/plugins/Plugins.h
+++ b/include/mgmt/rpc/handlers/plugins/Plugins.h
@@ -24,5 +24,5 @@
namespace rpc::handlers::plugins
{
-ts::Rv<YAML::Node> plugin_send_basic_msg(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> plugin_send_basic_msg(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::plugins
diff --git a/include/mgmt/rpc/handlers/records/Records.h b/include/mgmt/rpc/handlers/records/Records.h
index 40fd9696b4..a1d86cab7f 100644
--- a/include/mgmt/rpc/handlers/records/Records.h
+++ b/include/mgmt/rpc/handlers/records/Records.h
@@ -22,7 +22,7 @@
#include <string_view>
#include <yaml-cpp/yaml.h>
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
namespace rpc::handlers::records
{
@@ -34,27 +34,27 @@ namespace rpc::handlers::records
/// lead the search.
/// @param id JSONRPC client's id.
/// @param params lookup_records query structure.
-/// @return ts::Rv<YAML::Node> A node or an error. If ok, the node will hold the @c "recordList" sequence with the findings. In case
-/// of any missed search, ie: when paseed types didn't match the found record(s), the particular error will be added to the @c
+/// @return swoc::Rv<YAML::Node> A node or an error. If ok, the node will hold the @c "recordList" sequence with the findings. In
+/// case of any missed search, ie: when paseed types didn't match the found record(s), the particular error will be added to the @c
/// "errorList" field.
///
-ts::Rv<YAML::Node> lookup_records(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> lookup_records(std::string_view const &id, YAML::Node const ¶ms);
///
/// @brief A RPC function handler that clear all the metrics.
///
/// @param id JSONRPC client's id.
/// @param params Nothing, this will be ignored.
-/// @return ts::Rv<YAML::Node> An empty YAML::Node or the proper Errata with the tracked error.
+/// @return swoc::Rv<YAML::Node> An empty YAML::Node or the proper Errata with the tracked error.
///
-ts::Rv<YAML::Node> clear_all_metrics_records(std::string_view const &id, YAML::Node const &);
+swoc::Rv<YAML::Node> clear_all_metrics_records(std::string_view const &id, YAML::Node const &);
///
/// @brief A RPC function handler that clear a specific set of metrics.
/// The @c "errorList" field will only be set if there is any error cleaning a specific metric.
/// @param id JSONRPC client's id.
/// @param params A list of records to update. @see RequestRecordElement
-/// @return ts::Rv<YAML::Node> A YAML::Node or the proper Errata with the tracked error.
+/// @return swoc::Rv<YAML::Node> A YAML::Node or the proper Errata with the tracked error.
///
-ts::Rv<YAML::Node> clear_metrics_records(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> clear_metrics_records(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::records
diff --git a/include/mgmt/rpc/handlers/server/Server.h b/include/mgmt/rpc/handlers/server/Server.h
index 6b6bd26bc5..b66b535ca1 100644
--- a/include/mgmt/rpc/handlers/server/Server.h
+++ b/include/mgmt/rpc/handlers/server/Server.h
@@ -24,7 +24,7 @@
namespace rpc::handlers::server
{
-ts::Rv<YAML::Node> server_start_drain(std::string_view const &id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> server_stop_drain(std::string_view const &id, YAML::Node const &);
+swoc::Rv<YAML::Node> server_start_drain(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> server_stop_drain(std::string_view const &id, YAML::Node const &);
void server_shutdown(YAML::Node const &);
} // namespace rpc::handlers::server
diff --git a/include/mgmt/rpc/handlers/storage/Storage.h b/include/mgmt/rpc/handlers/storage/Storage.h
index 47738e565f..d07282b5a4 100644
--- a/include/mgmt/rpc/handlers/storage/Storage.h
+++ b/include/mgmt/rpc/handlers/storage/Storage.h
@@ -24,6 +24,6 @@
namespace rpc::handlers::storage
{
-ts::Rv<YAML::Node> set_storage_offline(std::string_view const &id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> get_storage_status(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> set_storage_offline(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> get_storage_status(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::storage
diff --git a/include/mgmt/rpc/jsonrpc/Context.h b/include/mgmt/rpc/jsonrpc/Context.h
index 920d1fbd3c..54d6086fde 100644
--- a/include/mgmt/rpc/jsonrpc/Context.h
+++ b/include/mgmt/rpc/jsonrpc/Context.h
@@ -23,7 +23,7 @@
#include <functional>
#include <string_view>
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
#include "ts/apidefs.h"
#include "mgmt/rpc/handlers/common/ErrorUtils.h"
@@ -40,15 +40,15 @@ constexpr bool NON_RESTRICTED_API{false};
///
class Context
{
- using checker_cb = std::function<void(TSRPCHandlerOptions const &, ts::Errata &)>;
+ using checker_cb = std::function<void(TSRPCHandlerOptions const &, swoc::Errata &)>;
/// @brief Internal class to hold the permission checker part.
struct Auth {
/// Checks for permissions. This function checks for every registered permission checker.
///
/// @param options Registered handler options.
- /// @return ts::Errata The errata will be filled by each of the registered checkers, if there was any issue validating the
+ /// @return swoc::Errata The errata will be filled by each of the registered checkers, if there was any issue validating the
/// call, then the errata reflects that.
- ts::Errata is_blocked(TSRPCHandlerOptions const &options) const;
+ swoc::Errata is_blocked(TSRPCHandlerOptions const &options) const;
/// Add permission checkers.
template <typename F>
diff --git a/include/mgmt/rpc/jsonrpc/Defs.h b/include/mgmt/rpc/jsonrpc/Defs.h
index 22bcf021f1..00cf2a3e0f 100644
--- a/include/mgmt/rpc/jsonrpc/Defs.h
+++ b/include/mgmt/rpc/jsonrpc/Defs.h
@@ -23,6 +23,8 @@
#include <string>
#include <optional>
+#include "tsutil/ts_errata.h"
+
#include <yaml-cpp/yaml.h>
#include "mgmt/rpc/jsonrpc/error/RPCError.h"
@@ -40,17 +42,16 @@ const std::string JSONRPC_VERSION{"2.0"};
class RPCHandlerResponse
{
public:
- YAML::Node result; //!< The response from the registered handler.
- ts::Errata errata; //!< The error response from the registered handler.
+ YAML::Node result; //!< The response from the registered handler.
+ swoc::Errata errata; //!< The error response from the registered handler.
};
struct RPCResponseInfo {
RPCResponseInfo(std::string const &id_) : id{id_} {} // Convenient
RPCResponseInfo() = default;
-
struct Error {
- std::error_code ec;
- ts::Errata data;
+ std::error_code ec; // protocol error track.
+ swoc::Errata data; // internal error detail.
};
std::string id; //!< incoming request id (only used for method calls, empty means it's a notification as requests with empty id
diff --git a/include/mgmt/rpc/jsonrpc/JsonRPCManager.h b/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
index 56b2d71e80..9506493465 100644
--- a/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
+++ b/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
@@ -28,7 +28,6 @@
#include <variant>
#include <mutex>
-#include "tscore/Errata.h"
#include "tscore/Diags.h"
#include "ts/apidefs.h"
@@ -66,7 +65,7 @@ private:
public:
// Possible RPC method signatures.
- using MethodHandlerSignature = std::function<ts::Rv<YAML::Node>(std::string_view const &, const YAML::Node &)>;
+ using MethodHandlerSignature = std::function<swoc::Rv<YAML::Node>(std::string_view const &, const YAML::Node &)>;
using PluginMethodHandlerSignature = std::function<void(std::string_view const &, const YAML::Node &)>;
using NotificationHandlerSignature = std::function<void(const YAML::Node &)>;
@@ -216,8 +215,8 @@ private:
bool remove_handler(std::string_view name);
// JSONRPC API - here for now.
- ts::Rv<YAML::Node> show_registered_handlers(std::string_view const &, const YAML::Node &);
- ts::Rv<YAML::Node> get_service_descriptor(std::string_view const &, const YAML::Node &);
+ swoc::Rv<YAML::Node> show_registered_handlers(std::string_view const &, const YAML::Node &);
+ swoc::Rv<YAML::Node> get_service_descriptor(std::string_view const &, const YAML::Node &);
// Supported handler endpoint types.
using Method = FunctionWrapper<MethodHandlerSignature>;
@@ -248,7 +247,7 @@ private:
explicit operator bool() const;
bool operator!() const;
/// Invoke the actual handler callback.
- ts::Rv<YAML::Node> invoke(specs::RPCRequestInfo const &request) const;
+ swoc::Rv<YAML::Node> invoke(specs::RPCRequestInfo const &request) const;
/// Check if the handler was registered as method.
bool is_method() const;
diff --git a/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h b/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
index a8b3d3972a..ce8eb5a7e4 100644
--- a/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
+++ b/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
@@ -115,7 +115,7 @@ class yamlcpp_json_decoder
return {request, error::RPCErrorCode::PARSE_ERROR};
}
// TODO We may want to extend the error handling and inform the user if there is more than one invalid field in the request,
- // so far we notify only the first one, we can use the data field to add more errors in it. ts::Errata
+ // so far we notify only the first one, we can use the data field to add more errors in it. swoc::Errata
return {request, {/*ok*/}};
}
@@ -182,19 +182,19 @@ class yamlcpp_json_encoder
/// @param json output parameter. YAML::Emitter.
///
static void
- encode_error(std::error_code error, ts::Errata const &errata, YAML::Emitter &json)
+ encode_error(std::error_code error, swoc::Errata const &errata, YAML::Emitter &json)
{
json << YAML::Key << "error";
json << YAML::BeginMap;
json << YAML::Key << "code" << YAML::Value << error.value();
json << YAML::Key << "message" << YAML::Value << error.message();
- if (!errata.isOK()) {
+ if (!errata.is_ok()) {
json << YAML::Key << "data";
json << YAML::BeginSeq;
for (auto const &err : errata) {
json << YAML::BeginMap;
- json << YAML::Key << "code" << YAML::Value << err.getCode();
- json << YAML::Key << "message" << YAML::Value << err.text();
+ json << YAML::Key << "code" << YAML::Value << errata.code().value();
+ json << YAML::Key << "message" << YAML::Value << std::string{err.text().data(), err.text().size()};
json << YAML::EndMap;
}
json << YAML::EndSeq;
@@ -204,7 +204,7 @@ class yamlcpp_json_encoder
/// Convenience functions to call encode_error.
static void
- encode_error(ts::Errata const &errata, YAML::Emitter &json)
+ encode_error(swoc::Errata const &errata, YAML::Emitter &json)
{
encode_error({error::RPCErrorCode::ExecutionError}, errata, json);
}
@@ -229,7 +229,7 @@ class yamlcpp_json_encoder
}
// Registered handler error: They have set the error on the response from the registered handler. This uses ExecutionError as
// top error.
- else if (!resp.callResult.errata.isOK()) {
+ else if (!resp.callResult.errata.is_ok()) {
encode_error(resp.callResult.errata, json);
}
// A valid response: The registered handler have set the proper result and no error was flagged.
diff --git a/include/mgmt/rpc/server/CommBase.h b/include/mgmt/rpc/server/CommBase.h
index 30767d82aa..23bbb36503 100644
--- a/include/mgmt/rpc/server/CommBase.h
+++ b/include/mgmt/rpc/server/CommBase.h
@@ -21,7 +21,7 @@
#include <system_error>
-#include <tscore/Errata.h>
+#include <tsutil/ts_errata.h>
#include "mgmt/rpc/config/JsonRPCConfig.h"
diff --git a/include/mgmt/rpc/server/IPCSocketServer.h b/include/mgmt/rpc/server/IPCSocketServer.h
index 7c3ccfba30..854e571dc9 100644
--- a/include/mgmt/rpc/server/IPCSocketServer.h
+++ b/include/mgmt/rpc/server/IPCSocketServer.h
@@ -29,6 +29,8 @@
#include "swoc/MemSpan.h"
#include "swoc/BufferWriter.h"
+#include "tsutil/ts_bw_format.h"
+#include "tsutil/ts_errata.h"
#include "tscore/Layout.h"
#include "mgmt/rpc/server/CommBase.h"
@@ -134,7 +136,7 @@ private:
void bind(std::error_code &ec);
void listen(std::error_code &ec);
void close();
- void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const;
+ void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, swoc::Errata &errata) const;
std::atomic_bool _running;
diff --git a/include/tscore/Errata.h b/include/tscore/Errata.h
deleted file mode 100644
index 3db677d429..0000000000
--- a/include/tscore/Errata.h
+++ /dev/null
@@ -1,1047 +0,0 @@
-/** @file
- Stacking error message handling.
-
- The problem addressed by this library is the ability to pass back
- detailed error messages from failures. It is hard to get good
- diagnostics because the specific failures and general context are
- located in very different stack frames. This library allows local
- functions to pass back local messages which can be easily
- augmented as the error travels up the stack frame.
-
- This could be done with exceptions but
- - That is more effort to implementation
- - Generally more expensive.
-
- Each message on a stack contains text and a numeric identifier.
- The identifier value zero is reserved for messages that are not
- errors so that information can be passed back even in the success
- case.
-
- The implementation takes the position that success is fast and
- failure is expensive. Therefore it is optimized for the success
- path, imposing very little overhead. On the other hand, if an
- error occurs and is handled, that is generally so expensive that
- optimizations are pointless (although, of course, one should not
- be gratuitiously expensive).
-
- The library also provides the @c Rv ("return value") template to
- make returning values and status easier. This template allows a
- function to return a value and status pair with minimal changes.
- The pair acts like the value type in most situations, while
- providing access to the status.
-
- Each instance of an erratum is a wrapper class that emulates value
- semantics (copy on write). This means passing even large message
- stacks is inexpensive, involving only a pointer copy and reference
- counter increment and decrement. A success value is represented by
- an internal @c NULL so it is even cheaper to copy.
-
- To further ease use, the library has the ability to define @a
- sinks. A sink is a function that acts on an erratum when it
- becomes unreferenced. The indended use is to send the messages to
- an output log. This makes reporting errors to a log from even
- deeply nested functions easy while preserving the ability of the
- top level logic to control such logging.
-
- @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 <memory>
-#include <string>
-#include <iosfwd>
-#include <sstream>
-#include <deque>
-#include <system_error>
-#include "tscore/NumericType.h"
-#include "tscore/IntrusivePtr.h"
-
-namespace ts
-{
-/** Class to hold a stack of error messages (the "errata").
- This is a smart handle class, which wraps the actual data
- and can therefore be treated a value type with cheap copy
- semantics. Default construction is very cheap.
- */
-class Errata
-{
-protected:
- /// Implementation class.
- struct Data;
- /// Handle for implementation class instance.
- using ImpPtr = IntrusivePtr<Data>;
-
-public:
- using self = Errata; /// Self reference type.
-
- /// Message ID.
- using Id = NumericType<unsigned int, struct MsgIdTag>;
-
- /* Tag / level / code severity.
- This is intended for clients to use to provide additional
- classification of a message. A severity code, as for syslog,
- is a common use.
-
- */
- using Code = NumericType<unsigned int, struct CodeTag>;
- struct Message;
-
- using Container = std::deque<Message>; ///< Storage type for messages.
- // We iterate backwards to look like a stack.
- // using iterator = Container::reverse_iterator; ///< Message iteration.
- /// Message const iteration.
- // using const_iterator = Container::const_reverse_iterator;
- /// Reverse message iteration.
- // using reverse_iterator = Container::iterator;
- /// Reverse constant message iteration.
- // using const_reverse_iterator = Container::const_iterator;
-
- /// Default constructor - empty errata, very fast.
- Errata();
- /// Copy constructor, very fast.
- Errata(self const &that ///< Object to copy
- );
- /// Construct from string.
- /// Message Id and Code are default.
- explicit Errata(std::string const &text ///< Finalized message text.
- );
- /// Construct with @a id and @a text.
- /// Code is default.
- Errata(Id id, ///< Message id.
- std::string const &text ///< Message text.
- );
- /// Construct with @a id, @a code, and @a text.
- Errata(Id id, ///< Message text.
- Code code, ///< Message code.
- std::string const &text ///< Message text.
- );
- /** Construct from a message instance.
- This is equivalent to default constructing an @c errata and then
- invoking @c push with an argument of @a msg.
- */
- Errata(Message const &msg ///< Message to push
- );
-
- /// Constructor with @a id and @a std::error_code
- Errata(std::error_code const &ec ///< Standard error code.
- );
- /// Move constructor.
- Errata(self &&that);
- /// Move constructor from @c Message.
- Errata(Message &&msg);
-
- /// destructor
- ~Errata();
-
- /// Self assignment.
- /// @return A reference to this object.
- self &operator=(const self &that ///< Source instance.
- );
-
- /// Move assignment.
- self &operator=(self &&that);
-
- /** Assign message.
- All other messages are discarded.
- @return A reference to this object.
- */
- self &operator=(Message const &msg ///< Source message.
- );
-
- /** Push @a text as a message.
- The message is constructed from just the @a text.
- It becomes the top message.
- @return A reference to this object.
- */
- self &push(std::string const &text);
- /** Push @a text as a message with message @a id.
- The message is constructed from @a text and @a id.
- It becomes the top message.
- @return A reference to this object.
- */
- self &push(Id id, std::string const &text);
- /** Push @a text as a message with message @a id and @a code.
- The message is constructed from @a text and @a id.
- It becomes the top message.
- @return A reference to this object.
- */
- self &push(Id id, Code code, std::string const &text);
- /** Push a message.
- @a msg becomes the top message.
- @return A reference to this object.
- */
- self &push(Message const &msg);
- self &push(Message &&msg);
-
- /** Push a constructed @c Message.
- The @c Message is set to have the @a id and @a code. The other arguments are converted
- to strings and concatenated to form the message text.
- @return A reference to this object.
- */
- template <typename... Args> self &push(Id id, Code code, Args const &...args);
-
- /** Push a nested status.
- @a err becomes the top item.
- @return A reference to this object.
- */
- self &push(self const &err);
-
- /** Access top message.
- @return If the errata is empty, a default constructed message
- otherwise the most recent message.
- */
- Message const &top() const;
-
- /** Move messages from @a that to @c this errata.
- Messages from @a that are put on the top of the
- stack in @c this and removed from @a that.
- */
- self &pull(self &that);
-
- /// Remove last message.
- void pop();
-
- /// Remove all messages.
- void clear();
-
- /** Inhibit logging.
- @note This only affects @c this as a top level @c errata.
- It has no effect on this @c this being logged as a nested
- @c errata.
- */
- self &doNotLog();
-
- friend std::ostream &operator<<(std::ostream &, self const &);
-
- /// Default glue value (a newline) for text rendering.
- static std::string const DEFAULT_GLUE;
-
- /** Test status.
-
- Equivalent to @c success but more convenient for use in
- control statements.
-
- @return @c true if no messages or last message has a zero
- message ID, @c false otherwise.
- */
- operator bool() const;
-
- /** Test errata for no failure condition.
-
- Equivalent to @c operator @c bool but easier to invoke.
-
- @return @c true if no messages or last message has a zero
- message ID, @c false otherwise.
- */
- bool isOK() const;
-
- /// Number of messages in the errata.
- size_t size() const;
-
- /* Forward declares.
- We have to make our own iterators as the least bad option. The problem
- is that we have recursive structures so declaration order is difficult.
- We can't use the container iterators here because the element type is
- not yet defined. If we define the element type here, it can't contain
- an Errata and we have to do funky things to get around that. So we
- have our own iterators, which are just shadowing sublclasses of the
- container iterators.
- */
- class iterator;
- class const_iterator;
-
- /// Reference to top item on the stack.
- iterator begin();
- /// Reference to top item on the stack.
- const_iterator begin() const;
- //! Reference one past bottom item on the stack.
- iterator end();
- //! Reference one past bottom item on the stack.
- const_iterator end() const;
-
- // Logging support.
-
- /** Base class for erratum sink.
- When an errata is abandoned, this will be called on it to perform
- any client specific logging. It is passed around by handle so that
- it doesn't have to support copy semantics (and is not destructed
- until application shutdown). Clients can subclass this class in order
- to preserve arbitrary data for the sink or retain a handle to the
- sink for runtime modifications.
- */
- class Sink : public IntrusivePtrCounter
- {
- public:
- using self = Sink; ///< Self reference type.
- using Handle = IntrusivePtr<self>; ///< Handle type.
-
- /// Handle an abandoned errata.
- virtual void operator()(Errata const &) const = 0;
- /// Force virtual destructor.
- virtual ~Sink() {}
- };
-
- //! Register a sink for discarded erratum.
- static void registerSink(Sink::Handle const &s);
-
- /// Register a function as a sink.
- using SinkHandlerFunction = void (*)(Errata const &);
-
- // Wrapper class to support registering functions as sinks.
- struct SinkFunctionWrapper : public Sink {
- /// Constructor.
- SinkFunctionWrapper(SinkHandlerFunction f) : m_f(f) {}
- /// Operator to invoke the function.
- void
- operator()(Errata const &e) const override
- {
- m_f(e);
- }
- SinkHandlerFunction m_f; ///< Client supplied handler.
- };
-
- /// Register a sink function for abandoned erratum.
- static void
- registerSink(SinkHandlerFunction f)
- {
- registerSink(Sink::Handle(new SinkFunctionWrapper(f)));
- }
-
- /** Simple formatted output.
-
- Each message is written to a line. All lines are indented with
- whitespace @a offset characters. Lines are indented an
- additional @a indent. This value is increased by @a shift for
- each level of nesting of an @c Errata. if @a lead is not @c
- NULL the indentation is overwritten by @a lead if @a indent is
- non-zero. It acts as a "continuation" marker for nested
- @c Errata.
-
- */
- std::ostream &write(std::ostream &out, ///< Output stream.
- int offset, ///< Lead white space for every line.
- int indent, ///< Additional indentation per line for messages.
- int shift, ///< Additional @a indent for nested @c Errata.
- char const *lead ///< Leading text for nested @c Errata.
- ) const;
- /// Simple formatted output to fixed sized buffer.
- /// @return Number of characters written to @a buffer.
- size_t write(char *buffer, ///< Output buffer.
- size_t n, ///< Buffer size.
- int offset, ///< Lead white space for every line.
- int indent, ///< Additional indentation per line for messages.
- int shift, ///< Additional @a indent for nested @c Errata.
- char const *lead ///< Leading text for nested @c Errata.
- ) const;
-
-protected:
- /// Construct from implementation pointer.
- /// Used internally by nested classes.
- Errata(ImpPtr const &ptr);
- /// Implementation instance.
- ImpPtr m_data;
-
- /// Return the implementation instance, allocating and unsharing as needed.
- Data *pre_write();
- /// Force and return an implementation instance.
- /// Does not follow copy on write.
- Data const *instance();
-
- /// Used for returns when no data is present.
- static Message const NIL_MESSAGE;
-
- friend struct Data;
- friend class Item;
-};
-
-extern std::ostream &operator<<(std::ostream &os, Errata const &stat);
-
-/// Storage for a single message.
-struct Errata::Message {
- using self = Message; ///< Self reference type.
-
- /// Default constructor.
- /// The message has Id = 0, default code, and empty text.
- Message() = default;
-
- /// Construct from text.
- /// Id is zero and Code is default.
- Message(std::string const &text ///< Finalized message text.
- );
-
- /// Construct with @a id and @a text.
- /// Code is default.
- Message(Id id, ///< ID of message in table.
- std::string const &text ///< Final text for message.
- );
-
- /// Construct with @a id, @a code, and @a text.
- Message(Id id, ///< Message Id.
- Code code, ///< Message Code.
- std::string const &text ///< Final text for message.
- );
-
- /// Construct with an @a id, @a code, and a @a message.
- /// The message contents are created by converting the variable arguments
- /// to strings using the stream operator and concatenated in order.
- template <typename... Args>
- Message(Id id, ///< Message Id.
- Code code, ///< Message Code.
- Args const &...text);
-
- /// Reset to the message to default state.
- self &clear();
-
- /// Set the message Id.
- self &set(Id id ///< New message Id.
- );
-
- /// Set the code.
- self &set(Code code ///< New code for message.
- );
-
- /// Set the text.
- self &set(std::string const &text ///< New message text.
- );
-
- /// Set the text.
- self &set(char const *text ///< New message text.
- );
-
- /// Set the errata.
- self &set(Errata const &err ///< Errata to store.
- );
-
- /// Get the text of the message.
- std::string const &text() const;
-
- /// Get the code.
- Code getCode() const;
- /// Get the nested status.
- /// @return A status object, which is not @c NULL if there is a
- /// nested status stored in this item.
- Errata getErrata() const;
-
- /** The default message code.
-
- This value is used as the Code value for constructing and
- clearing messages. It can be changed to control the value
- used for empty messages.
- */
- static Code Default_Code;
-
- /// Type for overriding success message test.
- using SuccessTest = bool (*)(Message const &m);
-
- /** Success message test.
-
- When a message is tested for being "successful", this
- function is called. It may be overridden by a client.
- The initial value is @c DEFAULT_SUCCESS_TEST.
-
- @note This is only called when there are Messages in the
- Errata. An empty Errata (@c NULL or empty stack) is always
- a success. Only the @c top Message is checked.
-
- @return @c true if the message indicates success,
- @c false otherwise.
- */
- static SuccessTest Success_Test;
-
- /// Indicate success if the message code is zero.
- /// @note Used as the default success test.
- static bool isCodeZero(Message const &m);
-
- static SuccessTest const DEFAULT_SUCCESS_TEST;
-
- template <typename... Args> static std::string stringify(Args const &...items);
-
- Id m_id = 0; ///< Message ID.
- Code m_code = Default_Code; ///< Message code.
- std::string m_text; ///< Final text.
- Errata m_errata; ///< Nested errata.
-};
-
-/** This is the implementation class for Errata.
-
- It holds the actual messages and is treated as a passive data
- object with nice constructors.
-
- We implement reference counting semantics by hand for two
- reasons. One is that we need to do some specialized things, but
- mainly because the client can't see this class so we can't
-*/
-struct Errata::Data : public IntrusivePtrCounter {
- using self = Data; ///< Self reference type.
-
- //! Default constructor.
- Data();
-
- /// Destructor, to do logging.
- ~Data();
-
- //! Number of messages.
- size_t size() const;
-
- /// Get the top message on the stack.
- Message const &top() const;
-
- /// Put a message on top of the stack.
- void push(Message const &msg);
- void push(Message &&msg);
-
- /// Log this when it is deleted.
- mutable bool m_log_on_delete = true;
-
- //! The message stack.
- Container m_items;
-};
-
-/// Forward iterator for @c Messages in an @c Errata.
-class Errata::iterator : public Errata::Container::reverse_iterator
-{
-public:
- using self = iterator; ///< Self reference type.
- using super = Errata::Container::reverse_iterator; ///< Parent type.
- iterator(); ///< Default constructor.
- /// Copy constructor.
- iterator(self const &that ///< Source instance.
- );
- /// Construct from super class.
- iterator(super const &that ///< Source instance.
- );
- /// Assignment.
- self &operator=(self const &that);
- /// Assignment from super class.
- self &operator=(super const &that);
- /// Prefix increment.
- self &operator++();
- /// Prefix decrement.
- self &operator--();
-};
-
-/// Forward constant iterator for @c Messages in an @c Errata.
-class Errata::const_iterator : public Errata::Container::const_reverse_iterator
-{
-public:
- using self = const_iterator; ///< Self reference type.
- using super = Errata::Container::const_reverse_iterator; ///< Parent type.
- const_iterator(); ///< Default constructor.
- /// Copy constructor.
- const_iterator(self const &that ///< Source instance.
- );
- const_iterator(super const &that ///< Source instance.
- );
- /// Assignment.
- self &operator=(self const &that);
- /// Assignment from super class.
- self &operator=(super const &that);
- /// Prefix increment.
- self &operator++();
- /// Prefix decrement.
- self &operator--();
-};
-
-/** Helper class for @c Rv.
- This class enables us to move the implementation of non-templated methods
- and members out of the header file for a cleaner API.
- */
-struct RvBase {
- Errata _errata; ///< The status from the function.
-
- /** Default constructor. */
- RvBase();
-
- /** Construct with specific status.
- */
- RvBase(Errata const &s ///< Status to copy
- );
-
- /** Construct with specific status.
- */
- RvBase(Errata &&s ///< Status to move
- );
-
- //! Test the return value for success.
- bool isOK() const;
-
- /** Clear any stacked errors.
- This is useful during shutdown, to silence irrelevant errors caused
- by the shutdown process.
- */
- void clear();
-
- /// Inhibit logging of the errata.
- void doNotLog();
-};
-
-/** Return type for returning a value and status (errata). In
- general, a method wants to return both a result and a status so
- that errors are logged properly. This structure is used to do that
- in way that is more usable than just @c std::pair. - Simpler and
- shorter typography - Force use of @c errata rather than having to
- remember it (and the order) each time - Enable assignment directly
- to @a R for ease of use and compatibility so clients can upgrade
- asynchronously.
- */
-template <typename R> struct Rv : public RvBase {
- using self = Rv; ///< Standard self reference type.
- using super = RvBase; ///< Standard super class reference type.
- using Result = R; ///< Type of result value.
-
- Result _result; ///< The actual result of the function.
-
- /** Default constructor.
- The default constructor for @a R is used.
- The status is initialized to SUCCESS.
- */
- Rv();
-
- /** Standard (success) constructor.
-
- This copies the result and sets the status to SUCCESS.
-
- @note Not @c explicit so that clients can return just a result
- and have it be marked as SUCCESS.
- */
- Rv(Result const &r ///< The function result
- );
-
- /** Construct from a result and a pre-existing status object.
-
- @internal No constructor from just an Errata to avoid
- potential ambiguity with constructing from result type.
- */
- Rv(Result const &r, ///< The function result
- Errata const &s ///< A pre-existing status object
- );
-
- Rv(Errata &&errata);
- /** User conversion to the result type.
-
- This makes it easy to use the function normally or to pass the
- result only to other functions without having to extract it by
- hand.
- */
- operator Result const &() const;
-
- /** Assignment from result type.
-
- This allows the result to be assigned to a pre-declared return
- value structure. The return value is a reference to the
- internal result so that this operator can be chained in other
- assignments to instances of result type. This is most commonly
- used when the result is computed in to a local variable to be
- both returned and stored in a member.
-
- @code
- Rv<int> zret;
- int value;
- // ... complex computations, result in value
- this->m_value = zret = value;
- // ...
- return zret;
- @endcode
-
- @return A reference to the copy of @a r stored in this object.
- */
- Result &
- operator=(Result const &r ///< Result to assign
- )
- {
- _result = r;
- return _result;
- }
-
- /** Add the status from another instance to this one.
- @return A reference to @c this object.
- */
- template <typename U>
- self &push(Rv<U> const &that ///< Source of status messages
- );
-
- /** Set the result.
-
- This differs from assignment of the function result in that the
- return value is a reference to the @c Rv, not the internal
- result. This makes it useful for assigning a result local
- variable and then returning.
-
- @code
- Rv<int> zret;
- int value;
- // ... complex computation, result in value
- return zret.set(value);
- @endcode
- */
- self &set(Result const &r ///< Result to store
- );
-
- /** Return the result.
- @return A reference to the result value in this object.
- */
- Result &result();
-
- /** Return the result.
- @return A reference to the result value in this object.
- */
- Result const &result() const;
-
- /** Return the status.
- @return A reference to the @c errata in this object.
- */
- Errata &errata();
-
- /** Return the status.
- @return A reference to the @c errata in this object.
- */
- Errata const &errata() const;
-
- /// Directly set the errata
- self &operator=(Errata const &status ///< Errata to assign.
- );
-
- /// Push a message on to the status.
- self &push(Errata::Message const &msg);
-};
-
-/** Combine a function result and status in to an @c Rv.
- This is useful for clients that want to declare the status object
- and result independently.
- */
-template <typename R>
-Rv<R>
-MakeRv(R const &r, ///< The function result
- Errata const &s ///< The pre-existing status object
-)
-{
- return Rv<R>(r, s);
-}
-/* ----------------------------------------------------------------------- */
-/* ----------------------------------------------------------------------- */
-// Inline methods.
-inline Errata::Message::Message(std::string const &text) : m_text(text) {}
-inline Errata::Message::Message(Id id, std::string const &text) : m_id(id), m_text(text) {}
-inline Errata::Message::Message(Id id, Code code, std::string const &text) : m_id(id), m_code(code), m_text(text) {}
-template <typename... Args>
-Errata::Message::Message(Id id, Code code, Args const &...text) : m_id(id), m_code(code), m_text(stringify(text...))
-{
-}
-
-inline Errata::Message &
-Errata::Message::clear()
-{
- m_id = 0;
- m_code = Default_Code;
- m_text.erase();
- m_errata.clear();
- return *this;
-}
-
-inline std::string const &
-Errata::Message::text() const
-{
- return m_text;
-}
-inline Errata::Code
-Errata::Message::getCode() const
-{
- return m_code;
-}
-inline Errata
-Errata::Message::getErrata() const
-{
- return m_errata;
-}
-
-inline Errata::Message &
-Errata::Message::set(Id id)
-{
- m_id = id;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(Code code)
-{
- m_code = code;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(std::string const &text)
-{
- m_text = text;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(char const *text)
-{
- m_text = text;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(Errata const &err)
-{
- m_errata = err;
- m_errata.doNotLog();
- return *this;
-}
-
-template <typename... Args>
-std::string
-Errata::Message::stringify(Args const &...items)
-{
- std::ostringstream s;
- (void)(int[]){0, ((s << items), 0)...};
- return s.str();
-}
-
-inline Errata::Errata() {}
-inline Errata::Errata(Id id, Code code, std::string const &text)
-{
- this->push(Message(id, code, text));
-}
-inline Errata::Errata(Message const &msg)
-{
- this->push(msg);
-}
-inline Errata::Errata(Message &&msg)
-{
- this->push(std::move(msg));
-}
-inline Errata::Errata(std::error_code const &ec)
-{
- auto cond = ec.category().default_error_condition(ec.value());
- this->push(cond.value(), // we use the classification from the error_condition.
- ec.value(), ec.message());
-}
-
-inline Errata::operator bool() const
-{
- return this->isOK();
-}
-
-inline size_t
-Errata::size() const
-{
- return m_data ? m_data->m_items.size() : 0;
-}
-
-inline bool
-Errata::isOK() const
-{
- return nullptr == m_data || 0 == m_data->size() || Message::Success_Test(this->top());
-}
-
-inline Errata &
-Errata::push(std::string const &text)
-{
- this->push(Message(text));
- return *this;
-}
-
-inline Errata &
-Errata::push(Id id, std::string const &text)
-{
- this->push(Message(id, text));
- return *this;
-}
-
-inline Errata &
-Errata::push(Id id, Code code, std::string const &text)
-{
- this->push(Message(id, code, text));
- return *this;
-}
-
-template <typename... Args>
-auto
-Errata::push(Id id, Code code, Args const &...args) -> self &
-{
- this->push(Message(id, code, args...));
- return *this;
-}
-
-inline Errata &
-Errata::push(Errata const &err)
-{
- for (auto const &e : err) {
- this->push(e.m_id, e.m_code, e.m_text);
- // e.m_errata??
- }
- return *this;
-}
-
-inline Errata::Message const &
-Errata::top() const
-{
- return m_data ? m_data->top() : NIL_MESSAGE;
-}
-inline Errata &
-Errata::doNotLog()
-{
- this->instance()->m_log_on_delete = false;
- return *this;
-}
-
-inline Errata::Data::Data() {}
-inline size_t
-Errata::Data::size() const
-{
- return m_items.size();
-}
-
-inline Errata::iterator::iterator() {}
-inline Errata::iterator::iterator(self const &that) : super(that) {}
-inline Errata::iterator::iterator(super const &that) : super(that) {}
-inline Errata::iterator &
-Errata::iterator::operator=(self const &that)
-{
- this->super::operator=(that);
- return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator=(super const &that)
-{
- this->super::operator=(that);
- return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator++()
-{
- this->super::operator++();
- return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator--()
-{
- this->super::operator--();
- return *this;
-}
-
-inline Errata::const_iterator::const_iterator() {}
-inline Errata::const_iterator::const_iterator(self const &that) : super(that) {}
-inline Errata::const_iterator::const_iterator(super const &that) : super(that) {}
-inline Errata::const_iterator &
-Errata::const_iterator::operator=(self const &that)
-{
- super::operator=(that);
- return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator=(super const &that)
-{
- super::operator=(that);
- return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator++()
-{
- this->super::operator++();
- return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator--()
-{
- this->super::operator--();
- return *this;
-}
-
-inline RvBase::RvBase() {}
-inline RvBase::RvBase(Errata const &errata) : _errata(errata) {}
-inline RvBase::RvBase(Errata &&errata) : _errata(std::move(errata)) {}
-inline bool
-RvBase::isOK() const
-{
- return _errata;
-}
-inline void
-RvBase::clear()
-{
- _errata.clear();
-}
-inline void
-RvBase::doNotLog()
-{
- _errata.doNotLog();
-}
-
-template <typename T> Rv<T>::Rv() : _result() {}
-template <typename T> Rv<T>::Rv(Result const &r) : _result(r) {}
-template <typename T> Rv<T>::Rv(Result const &r, Errata const &errata) : super(errata), _result(r) {}
-template <typename T> Rv<T>::Rv(Errata &&errata) : super(std::move(errata)) {}
-template <typename T> Rv<T>::operator Result const &() const
-{
- return _result;
-}
-template <typename T>
-T const &
-Rv<T>::result() const
-{
- return _result;
-}
-template <typename T>
-T &
-Rv<T>::result()
-{
- return _result;
-}
-template <typename T>
-Errata const &
-Rv<T>::errata() const
-{
- return _errata;
-}
-template <typename T>
-Errata &
-Rv<T>::errata()
-{
- return _errata;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::set(Result const &r)
-{
- _result = r;
- return *this;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::operator=(Errata const &errata)
-{
- _errata = errata;
- return *this;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::push(Errata::Message const &msg)
-{
- _errata.push(msg);
- return *this;
-}
-template <typename T>
-template <typename U>
-Rv<T> &
-Rv<T>::push(Rv<U> const &that)
-{
- _errata.push(that.errata());
- return *this;
-}
-/* ----------------------------------------------------------------------- */
-/* ----------------------------------------------------------------------- */
-} // namespace ts
diff --git a/include/tsutil/ts_errata.h b/include/tsutil/ts_errata.h
index 427983bbbb..313d5ab54d 100644
--- a/include/tsutil/ts_errata.h
+++ b/include/tsutil/ts_errata.h
@@ -22,6 +22,7 @@ limitations under the License.
#pragma once
#include <utility>
+#include <unordered_map>
#include "tsutil/ts_diag_levels.h"
#include "swoc/TextView.h"
@@ -44,27 +45,20 @@ diags_level_of(swoc::Errata::Severity s)
return static_cast<DiagsLevel>(static_cast<int>(s));
}
-inline std::error_code
-ec_for()
-{
- return std::error_code(errno, std::system_category());
-}
-inline std::error_code
-ec_for(int e)
-{
- return std::error_code(e, std::system_category());
-}
-
// This is treated as an array so must numerically match with @c DiagsLevel
static constexpr std::array<swoc::TextView, 9> Severity_Names{
{"Diag", "Debug", "Status", "Note", "Warn", "Error", "Fatal", "Alert", "Emergency"}
};
+namespace ts
+{
+
inline std::error_code
make_errno_code()
{
return {errno, std::system_category()};
}
+
inline std::error_code
make_errno_code(int err)
{
@@ -77,3 +71,69 @@ bw_log(DiagsLevel lvl, swoc::TextView fmt, Args &&...args)
{
swoc::bwprint_v(ts::bw_dbg, fmt, std::forward_as_tuple(args...));
}
+
+class err_category : public std::error_category
+{
+ using self_type = err_category;
+
+public:
+ /// @return Name of the category.
+ char const *name() const noexcept override;
+
+ /** Convert code to condition.
+ *
+ * @param code Numeric error code.
+ * @return The correspodning condition.
+ */
+ std::error_condition default_error_condition(int code) const noexcept override;
+
+ /** Is numeric error code equivalent to condition.
+ *
+ * @param code Numeric error code.
+ * @param condition Condition object.
+ * @return @a true if the arguments are equivalent.
+ */
+ bool equivalent(int code, std::error_condition const &condition) const noexcept override;
+
+ /** Is error code enumeration value equivalent to error code object.
+ *
+ * @param ec Condition object.
+ * @param code Numeric error code.
+ * @return @a true if the arguments are equivalent.
+ */
+ bool equivalent(std::error_code const &ec, int code) const noexcept override;
+
+ /// @return Text for @c code.
+ std::string message(int code) const override;
+
+protected:
+ using table_type = std::unordered_map<int, std::string>;
+ /// Mapping from numeric error code to message string.
+ static table_type const _table;
+};
+
+inline char const *
+ts::err_category::name() const noexcept
+{
+ return "trafficserver";
+}
+
+inline std::error_condition
+err_category::default_error_condition(int code) const noexcept
+{
+ return {code, *this};
+}
+
+inline bool
+err_category::equivalent(const std::error_code &ec, int code) const noexcept
+{
+ return ec.value() == code;
+}
+
+inline bool
+err_category::equivalent(int code, const std::error_condition &condition) const noexcept
+{
+ return code == condition.value();
+}
+
+} // namespace ts
diff --git a/lib/swoc/include/swoc/Errata.h b/lib/swoc/include/swoc/Errata.h
index 6ee0be5c25..fff9e17db1 100644
--- a/lib/swoc/include/swoc/Errata.h
+++ b/lib/swoc/include/swoc/Errata.h
@@ -1544,4 +1544,5 @@ get(swoc::Rv<R> const &rv) {
throw std::domain_error("Errata index value out of bounds");
}
/// @endcond
+
}} // namespace swoc::SWOC_VERSION_NS
diff --git a/src/api/InkAPI.cc b/src/api/InkAPI.cc
index 91cba8252f..a69938cfd6 100644
--- a/src/api/InkAPI.cc
+++ b/src/api/InkAPI.cc
@@ -117,7 +117,7 @@ namespace rpc
{
extern std::mutex g_rpcHandlingMutex;
extern std::condition_variable g_rpcHandlingCompletion;
-extern ts::Rv<YAML::Node> g_rpcHandlerResponseData;
+extern swoc::Rv<YAML::Node> g_rpcHandlerResponseData;
extern bool g_rpcHandlerProcessingCompleted;
} // namespace rpc
@@ -8853,7 +8853,7 @@ TSRPCHandlerError(int ec, const char *descr, size_t descr_len)
{
Debug("rpc.api", ">> Handler seems to be done with an error");
std::lock_guard<std::mutex> lock(rpc::g_rpcHandlingMutex);
- ::rpc::g_rpcHandlerResponseData = ts::Errata{}.push(1, ec, std::string{descr, descr_len});
+ ::rpc::g_rpcHandlerResponseData = swoc::Errata(ts::make_errno_code(ec), "{}", swoc::TextView{descr, descr_len});
::rpc::g_rpcHandlerProcessingCompleted = true;
::rpc::g_rpcHandlingCompletion.notify_one();
Debug("rpc.api", ">> error flagged.");
diff --git a/src/iocore/net/SSLSNIConfig.cc b/src/iocore/net/SSLSNIConfig.cc
index 357abd9f16..5a0cd99e93 100644
--- a/src/iocore/net/SSLSNIConfig.cc
+++ b/src/iocore/net/SSLSNIConfig.cc
@@ -306,8 +306,8 @@ SNIConfigParams::initialize(std::string const &sni_filename)
}
YamlSNIConfig yaml_sni_tmp;
- ts::Errata zret = yaml_sni_tmp.loader(sni_filename);
- if (!zret.isOK()) {
+ auto zret = yaml_sni_tmp.loader(sni_filename);
+ if (!zret.is_ok()) {
std::stringstream errMsg;
errMsg << zret;
if (TSSystemState::is_initializing()) {
diff --git a/src/iocore/net/YamlSNIConfig.cc b/src/iocore/net/YamlSNIConfig.cc
index e7c6919453..26d12b6e3a 100644
--- a/src/iocore/net/YamlSNIConfig.cc
+++ b/src/iocore/net/YamlSNIConfig.cc
@@ -38,6 +38,7 @@
#include "swoc/TextView.h"
#include "swoc/bwf_base.h"
+#include "iocore/net/YamlSNIConfig.h"
#include "SNIActionPerformer.h"
#include "P_SSLConfig.h"
#include "P_SSLNetVConnection.h"
@@ -47,7 +48,6 @@
#include "swoc/bwf_fwd.h"
#include "tscore/Diags.h"
#include "tscore/EnumDescriptor.h"
-#include "tscore/Errata.h"
#include "tscore/ink_assert.h"
#include "records/RecCore.h"
@@ -76,32 +76,32 @@ load_tunnel_alpn(std::vector<int> &dst, const YAML::Node &node)
} // namespace
-ts::Errata
+swoc::Errata
YamlSNIConfig::loader(const std::string &cfgFilename)
{
try {
YAML::Node config = YAML::LoadFile(cfgFilename);
if (config.IsNull()) {
- return ts::Errata();
+ return {};
}
if (!config["sni"]) {
- return ts::Errata::Message(1, 1, "expected a toplevel 'sni' node");
+ return swoc::Errata("expected a toplevel 'sni' node");
}
config = config["sni"];
if (!config.IsSequence()) {
- return ts::Errata::Message(1, 1, "expected sequence");
+ return swoc::Errata("expected sequence");
}
for (auto it = config.begin(); it != config.end(); ++it) {
items.push_back(it->as<YamlSNIConfig::Item>());
}
} catch (std::exception &ex) {
- return ts::Errata::Message(1, 1, ex.what());
+ return swoc::Errata("exception - {}", ex.what());
}
- return ts::Errata();
+ return swoc::Errata();
}
void
diff --git a/src/iocore/net/unit_tests/test_YamlSNIConfig.cc b/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
index 58932567d2..9c809d9840 100644
--- a/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
+++ b/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
@@ -48,13 +48,13 @@ check_port_range(const YamlSNIConfig::Item &item, in_port_t min_expected, in_por
TEST_CASE("YamlSNIConfig sets port ranges appropriately")
{
YamlSNIConfig conf{};
- ts::Errata zret{conf.loader(_XSTR(LIBINKNET_UNIT_TEST_DIR) "/sni_conf_test.yaml")};
- if (!zret.isOK()) {
+ swoc::Errata zret{conf.loader(_XSTR(LIBINKNET_UNIT_TEST_DIR) "/sni_conf_test.yaml")};
+ if (!zret.is_ok()) {
std::stringstream errorstream;
errorstream << zret;
FAIL(errorstream.str());
}
- REQUIRE(zret.isOK());
+ REQUIRE(zret.is_ok());
REQUIRE(conf.items.size() == 7);
SECTION("If no ports were specified, port range should contain all ports.")
@@ -113,11 +113,11 @@ TEST_CASE("YamlConfig handles bad ports appropriately.")
std::string filepath;
swoc::bwprint(filepath, "{}/sni_conf_test_bad_port_{}.yaml", _XSTR(LIBINKNET_UNIT_TEST_DIR), port_str);
- ts::Errata zret{conf.loader(filepath)};
+ swoc::Errata zret{conf.loader(filepath)};
std::stringstream errorstream;
errorstream << zret;
std::string expected;
- swoc::bwprint(expected, "1 [1]: yaml-cpp: error at line 20, column 5: bad port range: {}\n", port_str);
+ swoc::bwprint(expected, "Error: exception - yaml-cpp: error at line 20, column 5: bad port range: {}\n", port_str);
CHECK(errorstream.str() == expected);
}
diff --git a/src/mgmt/config/AddConfigFilesHere.cc b/src/mgmt/config/AddConfigFilesHere.cc
index 9e3fa3ef2d..e589a1bd90 100644
--- a/src/mgmt/config/AddConfigFilesHere.cc
+++ b/src/mgmt/config/AddConfigFilesHere.cc
@@ -26,7 +26,6 @@
#include "../../records/P_RecCore.h"
#include "tscore/Diags.h"
#include "mgmt/config/FileManager.h"
-#include "tscore/Errata.h"
static constexpr bool REQUIRED{true};
static constexpr bool NOT_REQUIRED{false};
diff --git a/src/mgmt/config/FileManager.cc b/src/mgmt/config/FileManager.cc
index 3df746258c..8d9644b06e 100644
--- a/src/mgmt/config/FileManager.cc
+++ b/src/mgmt/config/FileManager.cc
@@ -45,18 +45,17 @@
static constexpr auto logTag{"filemanager"};
namespace
{
-ts::Errata
+swoc::Errata
handle_file_reload(std::string const &fileName, std::string const &configName)
{
Debug(logTag, "handling reload %s - %s", fileName.c_str(), configName.c_str());
- ts::Errata ret;
+ swoc::Errata ret;
// TODO: make sure records holds the name after change, if not we should change it.
if (fileName == ts::filename::RECORDS) {
if (auto zret = RecReadYamlConfigFile(); zret) {
RecConfigWarnIfUnregistered();
} else {
- std::string str;
- ret.push(1, swoc::bwprint(str, "Error reading {}. {}", fileName));
+ ret.note("Error reading {}", fileName).note(zret);
}
} else {
RecT rec_type;
@@ -64,8 +63,7 @@ handle_file_reload(std::string const &fileName, std::string const &configName)
if (RecGetRecordType(data, &rec_type) == REC_ERR_OKAY && rec_type == RECT_CONFIG) {
RecSetSyncRequired(data);
} else {
- std::string str;
- ret.push(1, swoc::bwprint(str, "Unknown file change {}.", configName));
+ ret.note("Unknown file change {}.", configName);
}
}
@@ -90,7 +88,7 @@ FileManager::FileManager()
// Register the files registry jsonrpc endpoint
rpc::add_method_handler("filemanager.get_files_registry",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
return get_files_registry_rpc_endpoint(id, req);
},
&rpc::core_ats_rpc_service_provider_handle, {{rpc::NON_RESTRICTED_API}});
@@ -163,17 +161,20 @@ FileManager::getConfigObj(const char *fileName, ConfigManager **rbPtr)
return found;
}
-ts::Errata
+swoc::Errata
FileManager::fileChanged(std::string const &fileName, std::string const &configName)
{
Debug("filemanager", "file changed %s", fileName.c_str());
- ts::Errata ret;
+ swoc::Errata ret;
std::lock_guard<std::mutex> guard(_callbacksMutex);
for (auto const &call : _configCallbacks) {
if (auto const &r = call(fileName, configName); !r) {
Debug("filemanager", "something back from callback %s", fileName.c_str());
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Errors while reloading configurations.");
+ }
+ ret.note(r);
}
}
@@ -206,10 +207,10 @@ FileManager::invokeConfigPluginCallbacks()
// although it is tempting, DO NOT CALL FROM SIGNAL HANDLERS
// This function is not Async-Signal Safe. It
// is thread safe
-ts::Errata
+swoc::Errata
FileManager::rereadConfig()
{
- ts::Errata ret;
+ swoc::Errata ret;
ConfigManager *rb;
std::vector<ConfigManager *> changedFiles;
@@ -225,7 +226,8 @@ FileManager::rereadConfig()
auto const &r = fileChanged(rb->getFileName(), rb->getConfigName());
if (!r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ ret.note("Errors while reloading configurations.");
+ ret.note(r);
}
changedFiles.push_back(rb);
@@ -265,7 +267,10 @@ FileManager::rereadConfig()
for (size_t i = 0; i < n; i++) {
if (std::find(changedFiles.begin(), changedFiles.end(), parentFileNeedChange[i]) == changedFiles.end()) {
if (auto const &r = fileChanged(parentFileNeedChange[i]->getFileName(), parentFileNeedChange[i]->getConfigName()); !r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Error while handling parent file name changed.");
+ }
+ ret.note(r);
}
}
}
@@ -277,13 +282,19 @@ FileManager::rereadConfig()
if (found && enabled) {
if (auto const &r = fileChanged("proxy.config.body_factory.template_sets_dir", "proxy.config.body_factory.template_sets_dir");
!r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Error while loading body factory templates");
+ }
+ ret.note(r);
}
}
if (auto const &r = fileChanged("proxy.config.ssl.server.ticket_key.filename", "proxy.config.ssl.server.ticket_key.filename");
!r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Error while loading ticket keys");
+ }
+ ret.note(r);
}
return ret;
@@ -325,7 +336,7 @@ FileManager::configFileChild(const char *parent, const char *child)
}
auto
-FileManager::get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms) -> ts::Rv<YAML::Node>
+FileManager::get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms) -> swoc::Rv<YAML::Node>
{
// If any error, the rpc manager will catch it and respond with it.
YAML::Node configs{YAML::NodeType::Sequence};
diff --git a/src/mgmt/rpc/CMakeLists.txt b/src/mgmt/rpc/CMakeLists.txt
index f9d5674405..36446217b7 100644
--- a/src/mgmt/rpc/CMakeLists.txt
+++ b/src/mgmt/rpc/CMakeLists.txt
@@ -38,8 +38,14 @@ add_library(ts::jsonrpc_server ALIAS jsonrpc_server)
target_link_libraries(jsonrpc_server PUBLIC ts::jsonrpc_protocol)
add_library(
- rpcpublichandlers STATIC handlers/common/RecordsUtils.cc handlers/config/Configuration.cc handlers/records/Records.cc
- handlers/storage/Storage.cc handlers/server/Server.cc handlers/plugins/Plugins.cc
+ rpcpublichandlers STATIC
+ handlers/common/ErrorUtils.cc
+ handlers/common/RecordsUtils.cc
+ handlers/config/Configuration.cc
+ handlers/records/Records.cc
+ handlers/storage/Storage.cc
+ handlers/server/Server.cc
+ handlers/plugins/Plugins.cc
)
add_library(ts::rpcpublichandlers ALIAS rpcpublichandlers)
@@ -51,7 +57,9 @@ target_link_libraries(
if(BUILD_TESTING)
add_executable(test_jsonrpc jsonrpc/unit_tests/unit_test_main.cc jsonrpc/unit_tests/test_basic_protocol.cc)
- target_link_libraries(test_jsonrpc ts::tsutil catch2::catch2 ts::jsonrpc_protocol libswoc::libswoc)
+ target_link_libraries(
+ test_jsonrpc ts::tsutil catch2::catch2 ts::rpcpublichandlers ts::jsonrpc_protocol libswoc::libswoc
+ )
add_test(NAME test_jsonrpc COMMAND test_jsonrpc)
add_executable(
diff --git a/src/mgmt/rpc/handlers/common/ErrorUtils.cc b/src/mgmt/rpc/handlers/common/ErrorUtils.cc
new file mode 100644
index 0000000000..2b9bcad7d9
--- /dev/null
+++ b/src/mgmt/rpc/handlers/common/ErrorUtils.cc
@@ -0,0 +1,69 @@
+/**
+ @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/common/ErrorUtils.h"
+
+#include <system_error>
+#include <string>
+
+namespace
+{ // anonymous namespace
+
+struct RPCHandlerLogicErrorCategory : std::error_category {
+ const char *name() const noexcept override;
+ std::string message(int ev) const override;
+};
+
+const char *
+RPCHandlerLogicErrorCategory::name() const noexcept
+{
+ return "rpc_handler_logic_error";
+}
+std::string
+RPCHandlerLogicErrorCategory::message(int ev) const
+{
+ switch (static_cast<rpc::handlers::errors::Codes>(ev)) {
+ case rpc::handlers::errors::Codes::CONFIGURATION:
+ return {"Configuration handling error."};
+ case rpc::handlers::errors::Codes::METRIC:
+ return {"Metric handling error."};
+ case rpc::handlers::errors::Codes::RECORD:
+ return {"Record handling error."};
+ case rpc::handlers::errors::Codes::SERVER:
+ return {"Server handling error."};
+ case rpc::handlers::errors::Codes::STORAGE:
+ return {"Storage handling error."};
+ case rpc::handlers::errors::Codes::PLUGIN:
+ return {"Plugin handling error."};
+ default:
+ return "Generic handling error: " + std::to_string(ev);
+ }
+}
+
+const RPCHandlerLogicErrorCategory rpcHandlerLogicErrorCategory{};
+} // anonymous namespace
+
+namespace rpc::handlers::errors
+{
+std::error_code
+make_error_code(rpc::handlers::errors::Codes e)
+{
+ return {static_cast<int>(e), rpcHandlerLogicErrorCategory};
+}
+} // namespace rpc::handlers::errors
diff --git a/src/mgmt/rpc/handlers/config/Configuration.cc b/src/mgmt/rpc/handlers/config/Configuration.cc
index 773532553d..9a0a0b80e0 100644
--- a/src/mgmt/rpc/handlers/config/Configuration.cc
+++ b/src/mgmt/rpc/handlers/config/Configuration.cc
@@ -102,10 +102,10 @@ namespace
}
} // namespace
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
set_config_records(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
// we need the type and the update type for now.
using LookupContext = std::tuple<RecDataT, RecCheckT, const char *, RecUpdateT>;
@@ -115,7 +115,7 @@ set_config_records(std::string_view const &id, YAML::Node const ¶ms)
try {
info = kv.as<SetRecordCmdInfo>();
} catch (YAML::Exception const &ex) {
- resp.errata().push({err::RecordError::RECORD_NOT_FOUND});
+ resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::RECORD_NOT_FOUND});
continue;
}
@@ -139,7 +139,7 @@ set_config_records(std::string_view const &id, YAML::Node const ¶ms)
// make sure if exist. If not, we stop it and do not keep forward.
if (ret != REC_ERR_OKAY) {
- resp.errata().push({err::RecordError::RECORD_NOT_FOUND});
+ resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::RECORD_NOT_FOUND});
continue;
}
@@ -148,7 +148,9 @@ set_config_records(std::string_view const &id, YAML::Node const ¶ms)
// run the check only if we have something to check against it.
if (pattern != nullptr && utils::recordValidityCheck(info.value.c_str(), checkType, pattern) == false) {
- resp.errata().push({err::RecordError::VALIDITY_CHECK_ERROR});
+ resp.errata()
+ .assign(std::error_code{errors::Codes::RECORD})
+ .note("{}", std::error_code{err::RecordError::VALIDITY_CHECK_ERROR});
continue;
}
@@ -173,7 +175,7 @@ set_config_records(std::string_view const &id, YAML::Node const ¶ms)
updatedRecord[utils::RECORD_UPDATE_TYPE_KEY] = std::to_string(updateType);
resp.result().push_back(updatedRecord);
} else {
- resp.errata().push({err::RecordError::GENERAL_ERROR});
+ resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::GENERAL_ERROR});
continue;
}
}
@@ -181,17 +183,17 @@ set_config_records(std::string_view const &id, YAML::Node const ¶ms)
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
reload_config(std::string_view const &id, YAML::Node const ¶ms)
{
ts::Metrics &metrics = ts::Metrics::instance();
static auto reconf_time = metrics.lookup("proxy.process.proxy.reconfigure_time");
static auto reconf_req = metrics.lookup("proxy.process.proxy.reconfigure_required");
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
Debug("RPC", "invoke plugin callbacks");
// if there is any error, report it back.
- if (auto err = FileManager::instance().rereadConfig(); err.size()) {
- resp = err;
+ if (auto err = FileManager::instance().rereadConfig(); !err.empty()) {
+ resp.note(err);
}
// If any callback was register(TSMgmtUpdateRegister) for config notifications, then it will be eventually notify.
FileManager::instance().invokeConfigPluginCallbacks();
diff --git a/src/mgmt/rpc/handlers/plugins/Plugins.cc b/src/mgmt/rpc/handlers/plugins/Plugins.cc
index b5e130ac3a..9cd4eb565e 100644
--- a/src/mgmt/rpc/handlers/plugins/Plugins.cc
+++ b/src/mgmt/rpc/handlers/plugins/Plugins.cc
@@ -56,7 +56,7 @@ namespace rpc::handlers::plugins
{
namespace err = rpc::handlers::errors;
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
plugin_send_basic_msg(std::string_view const &id, YAML::Node const ¶ms)
{
// The rpc could be ready before plugins are initialized.
@@ -65,7 +65,7 @@ plugin_send_basic_msg(std::string_view const &id, YAML::Node const ¶ms)
return err::make_errata(err::Codes::PLUGIN, "Plugin is not yet ready to handle any messages.");
}
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
try {
// keep the data.
PluginMsgInfo info = params.as<PluginMsgInfo>();
diff --git a/src/mgmt/rpc/handlers/records/Records.cc b/src/mgmt/rpc/handlers/records/Records.cc
index a1f3f809f9..de49f8aae5 100644
--- a/src/mgmt/rpc/handlers/records/Records.cc
+++ b/src/mgmt/rpc/handlers/records/Records.cc
@@ -204,7 +204,7 @@ namespace rpc::handlers::records
{
namespace err = rpc::handlers::errors;
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
lookup_records(std::string_view const &id, YAML::Node const ¶ms)
{
// TODO: we may want to deal with our own object instead of a node here.
@@ -247,19 +247,19 @@ lookup_records(std::string_view const &id, YAML::Node const ¶ms)
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
clear_all_metrics_records(std::string_view const &id, YAML::Node const ¶ms)
{
using namespace rpc::handlers::records::utils;
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
if (RecResetStatRecord(RECT_NULL, true) != REC_ERR_OKAY) {
- return ts::Errata{rpc::handlers::errors::RecordError::RECORD_WRITE_ERROR};
+ return swoc::Errata{std::error_code{errors::Codes::METRIC}, "Failed to clear stats"};
}
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
clear_metrics_records(std::string_view const &id, YAML::Node const ¶ms)
{
using namespace rpc::handlers::records::utils;
diff --git a/src/mgmt/rpc/handlers/server/Server.cc b/src/mgmt/rpc/handlers/server/Server.cc
index e6639cc6dd..8e74ed3098 100644
--- a/src/mgmt/rpc/handlers/server/Server.cc
+++ b/src/mgmt/rpc/handlers/server/Server.cc
@@ -79,10 +79,10 @@ set_server_drain(bool drain)
metrics[drain_id].store(TSSystemState::is_draining() ? 1 : 0);
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_start_drain(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
try {
if (!params.IsNull()) {
DrainInfo di = params.as<DrainInfo>();
@@ -93,23 +93,23 @@ server_start_drain(std::string_view const &id, YAML::Node const ¶ms)
if (!is_server_draining()) {
set_server_drain(true);
} else {
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Server already draining."));
+ resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Server already draining.");
}
} catch (std::exception const &ex) {
Debug("rpc.handler.server", "Got an error DrainInfo decoding: %s", ex.what());
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Error found during server drain: {}", ex.what()));
+ resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Error found during server drain: {}", ex.what());
}
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_stop_drain(std::string_view const &id, [[maybe_unused]] YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
if (is_server_draining()) {
set_server_drain(false);
} else {
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Server is not draining."));
+ resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Server is not draining.");
}
return resp;
diff --git a/src/mgmt/rpc/handlers/storage/Storage.cc b/src/mgmt/rpc/handlers/storage/Storage.cc
index 10619caab6..0a66c7f500 100644
--- a/src/mgmt/rpc/handlers/storage/Storage.cc
+++ b/src/mgmt/rpc/handlers/storage/Storage.cc
@@ -57,10 +57,10 @@ namespace rpc::handlers::storage
{
namespace err = rpc::handlers::errors;
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
set_storage_offline(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
for (auto &&it : params) {
std::string device = it.as<std::string>();
@@ -75,16 +75,18 @@ set_storage_offline(std::string_view const &id, YAML::Node const ¶ms)
n["has_online_storage_left"] = ret ? "true" : "false";
resp.result().push_back(std::move(n));
} else {
- resp.errata().push(err::make_errata(err::Codes::STORAGE, "Passed device:'{}' does not match any defined storage", device));
+ resp.errata()
+ .assign(std::error_code{errors::Codes::STORAGE})
+ .note("Passed device: '{}' does not match any defined storage", device);
}
}
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
get_storage_status(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
for (auto &&it : params) {
std::string device = it.as<std::string>();
@@ -93,7 +95,9 @@ get_storage_status(std::string_view const &id, YAML::Node const ¶ms)
if (d) {
resp.result().push_back(*d);
} else {
- resp.errata().push(err::make_errata(err::Codes::STORAGE, "Passed device:'{}' does not match any defined storage", device));
+ resp.errata()
+ .assign(std::error_code{errors::Codes::STORAGE})
+ .note("Passed device: '{}' does not match any defined storage", device);
}
}
return resp;
diff --git a/src/mgmt/rpc/jsonrpc/Context.cc b/src/mgmt/rpc/jsonrpc/Context.cc
index 4c7d790691..f4f19682f4 100644
--- a/src/mgmt/rpc/jsonrpc/Context.cc
+++ b/src/mgmt/rpc/jsonrpc/Context.cc
@@ -22,10 +22,10 @@
namespace rpc
{
// --- Call Context impl
-ts::Errata
+swoc::Errata
Context::Auth::is_blocked(TSRPCHandlerOptions const &options) const
{
- ts::Errata out;
+ swoc::Errata out;
// check every registered callback and see if they have something to say. Then report back to the manager
for (auto &&check : _checkers) {
check(options, out);
diff --git a/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc b/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
index b05e35279c..dbe695934b 100644
--- a/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
+++ b/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
@@ -27,6 +27,7 @@
#include <condition_variable>
#include <swoc/swoc_meta.h>
+
#include "mgmt/rpc/jsonrpc/json/YAMLCodec.h"
namespace
@@ -57,15 +58,16 @@ RPCRegistryInfo core_ats_rpc_service_provider_handle = {
// plugin rpc handling variables.
std::mutex g_rpcHandlingMutex;
std::condition_variable g_rpcHandlingCompletion;
-ts::Rv<YAML::Node> g_rpcHandlerResponseData;
+swoc::Rv<YAML::Node> g_rpcHandlerResponseData;
bool g_rpcHandlerProcessingCompleted{false};
// --- Helpers
-std::pair<ts::Errata, error::RPCErrorCode>
+swoc::Errata
check_for_blockers(Context const &ctx, TSRPCHandlerOptions const &options)
{
- if (auto err = ctx.get_auth().is_blocked(options); !err.isOK()) {
- return {err, error::RPCErrorCode::Unauthorized};
+ if (auto err = ctx.get_auth().is_blocked(options); !err.is_ok()) {
+ return std::move(err.note(swoc::Errata(std::error_code(unsigned(error::RPCErrorCode::Unauthorized), std::generic_category()),
+ ERRATA_ERROR, swoc::Errata::AUTO)));
}
return {};
}
@@ -80,7 +82,7 @@ JsonRPCManager::Dispatcher::register_service_descriptor_handler()
{
if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
"show_registered_handlers",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
return show_registered_handlers(id, req);
},
&core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
@@ -89,7 +91,9 @@ JsonRPCManager::Dispatcher::register_service_descriptor_handler()
if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
"get_service_descriptor",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> { return get_service_descriptor(id, req); },
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
+ return get_service_descriptor(id, req);
+ },
&core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
Warning("Handler already registered.");
}
@@ -108,10 +112,10 @@ JsonRPCManager::Dispatcher::dispatch(Context const &ctx, specs::RPCRequestInfo c
}
// We have got a valid handler, we will now check if the context holds any restriction for this handler to be called.
- if (auto &&[errata, ec] = check_for_blockers(ctx, handler.get_options()); !errata.isOK()) {
+ if (auto errata = check_for_blockers(ctx, handler.get_options()); !errata.is_ok()) {
specs::RPCResponseInfo resp{request.id};
resp.error.ec = ec;
- resp.error.data = errata;
+ resp.error.data = std::move(errata);
return resp;
}
@@ -152,13 +156,13 @@ JsonRPCManager::Dispatcher::invoke_method_handler(JsonRPCManager::Dispatcher::In
specs::RPCResponseInfo response{request.id};
try {
- auto const &rv = handler.invoke(request);
+ auto rv = handler.invoke(request);
- if (rv.isOK()) {
+ if (rv.is_ok()) {
response.callResult.result = rv.result();
} else {
// if we have some errors to log, then include it.
- response.callResult.errata = rv.errata();
+ response.callResult.errata = std::move(rv.errata());
}
} catch (std::exception const &e) {
Debug(logTag, "Oops, something happened during the callback invocation: %s", e.what());
@@ -238,6 +242,7 @@ JsonRPCManager::handle_call(Context const &ctx, std::string const &request)
} else {
// If the request was marked as an error(decode error), we still need to send the error back, so we save it.
specs::RPCResponseInfo resp{req.id};
+ // resp.error.assign(swoc::Errata(decode_error));
resp.error.ec = decode_error;
response.add_message(std::move(resp));
}
@@ -250,20 +255,22 @@ JsonRPCManager::handle_call(Context const &ctx, std::string const &request)
resp = Encoder::encode(response);
Debug(logTagMsg, "<-- JSONRPC Response\n '%s'", (*resp).c_str());
}
+
return resp;
} catch (std::exception const &ex) {
ec = error::RPCErrorCode::INTERNAL_ERROR;
}
+
specs::RPCResponseInfo resp;
resp.error.ec = ec;
return {Encoder::encode(resp)};
}
// ---------------------------- InternalHandler ---------------------------------
-inline ts::Rv<YAML::Node>
+inline swoc::Rv<YAML::Node>
JsonRPCManager::Dispatcher::InternalHandler::invoke(specs::RPCRequestInfo const &request) const
{
- ts::Rv<YAML::Node> ret;
+ swoc::Rv<YAML::Node> ret;
std::visit(swoc::meta::vary{[](std::monostate) -> void { /* no op */ },
[&request](Notification const &handler) -> void {
// Notification handler call. Ignore response, there is no completion cv check in here basically
@@ -284,11 +291,11 @@ JsonRPCManager::Dispatcher::InternalHandler::invoke(specs::RPCRequestInfo const
std::unique_lock<std::mutex> lock(g_rpcHandlingMutex);
g_rpcHandlingCompletion.wait(lock, []() { return g_rpcHandlerProcessingCompleted; });
g_rpcHandlerProcessingCompleted = false;
- // seems to be done, set the response. As the response data is a ts::Rv this will handle both,
+ // seems to be done, set the response. As the response data is a swoc::Rv this will handle both,
// error and non error cases.
- ret = g_rpcHandlerResponseData;
+ ret = std::move(g_rpcHandlerResponseData);
// clean up the shared data.
- g_rpcHandlerResponseData.clear();
+ // g_rpcHandlerResponseData.clear(); // moved so no cleanup?
lock.unlock();
}},
this->_func);
@@ -310,10 +317,10 @@ JsonRPCManager::Dispatcher::InternalHandler::is_method() const
return false;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
JsonRPCManager::Dispatcher::show_registered_handlers(std::string_view const &, const YAML::Node &)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
std::lock_guard<std::mutex> lock(_mutex);
for (auto const &[name, handler] : _handlers) {
std::string const &key = handler.is_method() ? RPC_SERVICE_METHODS_KEY : RPC_SERVICE_NOTIFICATIONS_KEY;
@@ -324,7 +331,7 @@ JsonRPCManager::Dispatcher::show_registered_handlers(std::string_view const &, c
// -----------------------------------------------------------------------------
// This jsonrpc handler can provides a service descriptor for the RPC
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
JsonRPCManager::Dispatcher::get_service_descriptor(std::string_view const &, const YAML::Node &)
{
YAML::Node rpcService;
diff --git a/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc b/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
index 117c597f20..68e1146751 100644
--- a/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
+++ b/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
@@ -28,8 +28,6 @@
namespace
{
-const int ErratId{1};
-
// Not using the singleton logic.
struct JsonRpcUnitTest : rpc::JsonRPCManager {
JsonRpcUnitTest() : JsonRPCManager() {}
@@ -60,16 +58,20 @@ struct JsonRpcUnitTest : rpc::JsonRPCManager {
};
enum class TestErrors { ERR1 = 9999, ERR2 };
-inline ts::Rv<YAML::Node>
+static const std::error_code ERR1{ts::make_errno_code(9999)};
+static const std::error_code ERR2{ts::make_errno_code(10000)};
+static std::string_view err{"Just an error message to add more meaning to the failure"};
+
+inline swoc::Rv<YAML::Node>
test_callback_ok_or_error(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
// play with the req.id if needed.
if (YAML::Node n = params["return_error"]) {
auto yesOrNo = n.as<std::string>();
if (yesOrNo == "yes") {
- resp.errata().push(ErratId, static_cast<int>(TestErrors::ERR1), "Just an error message to add more meaning to the failure");
+ resp.errata().assign(ERR1).note(err);
} else {
resp.result()["ran"] = "ok";
}
@@ -334,12 +336,12 @@ TEST_CASE("Basic test with member functions(add, remove)", "[basic][member_funct
{
return rpc.add_method_handler(
"member_function",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> { return test(id, req); });
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> { return test(id, req); });
}
- ts::Rv<YAML::Node>
+ swoc::Rv<YAML::Node>
test(std::string_view const &id, const YAML::Node &req)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
resp.result() = "grand!";
return resp;
}
@@ -379,10 +381,10 @@ TEST_CASE("Test Dispatcher rpc method", "[dispatcher]")
R"({"jsonrpc": "2.0", "result": {"methods": ["get_service_descriptor", "show_registered_handlers"]}, "id": "AbC"})");
}
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
subtract(std::string_view const &id, YAML::Node const &numbers)
{
- ts::Rv<YAML::Node> res;
+ swoc::Rv<YAML::Node> res;
if (numbers.Type() == YAML::NodeType::Sequence) {
auto it = numbers.begin();
@@ -402,10 +404,10 @@ subtract(std::string_view const &id, YAML::Node const &numbers)
return res;
}
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
sum(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> res;
+ swoc::Rv<YAML::Node> res;
int total{0};
for (auto n : params) {
total += n.as<int>();
@@ -414,10 +416,10 @@ sum(std::string_view const &id, YAML::Node const ¶ms)
return res;
}
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
get_data(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> res;
+ swoc::Rv<YAML::Node> res;
res.result().push_back("hello");
res.result().push_back("5");
return res;
@@ -555,10 +557,10 @@ TEST_CASE("Handle un-handle handler's error", "[throw]")
JsonRpcUnitTest rpc;
SECTION("Basic exception thrown")
{
- REQUIRE(
- rpc.add_method_handler("oops_i_did_it_again", [](std::string_view const &id, const YAML::Node ¶ms) -> ts::Rv<YAML::Node> {
- throw std::runtime_error("Oops, I did it again");
- }));
+ REQUIRE(rpc.add_method_handler("oops_i_did_it_again",
+ [](std::string_view const &id, const YAML::Node ¶ms) -> swoc::Rv<YAML::Node> {
+ throw std::runtime_error("Oops, I did it again");
+ }));
const auto resp = rpc.handle_call(R"({"jsonrpc": "2.0", "method": "oops_i_did_it_again", "id": "1"})");
std::string_view expected = R"({"jsonrpc": "2.0", "error": {"code": 9, "message": "Error during execution"}, "id": "1"})";
REQUIRE(*resp == expected);
@@ -570,10 +572,10 @@ TEST_CASE("Call registered method with no ID", "[no-id]")
JsonRpcUnitTest rpc;
SECTION("Basic test, no id on method call")
{
- REQUIRE(
- rpc.add_method_handler("call_me_with_no_id", [](std::string_view const &id, const YAML::Node ¶ms) -> ts::Rv<YAML::Node> {
- throw std::runtime_error("Oops, I did it again");
- }));
+ REQUIRE(rpc.add_method_handler("call_me_with_no_id",
+ [](std::string_view const &id, const YAML::Node ¶ms) -> swoc::Rv<YAML::Node> {
+ throw std::runtime_error("Oops, I did it again");
+ }));
const auto resp = rpc.handle_call(R"({"jsonrpc": "2.0", "method": "call_me_with_no_id"})");
std::string_view expected = R"({"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}})";
REQUIRE(*resp == expected);
diff --git a/src/mgmt/rpc/server/IPCSocketServer.cc b/src/mgmt/rpc/server/IPCSocketServer.cc
index 3b6e3b568f..f476bb0183 100644
--- a/src/mgmt/rpc/server/IPCSocketServer.cc
+++ b/src/mgmt/rpc/server/IPCSocketServer.cc
@@ -226,7 +226,7 @@ IPCSocketServer::run()
rpc::Context ctx;
// we want to make sure the peer's credentials are ok.
ctx.get_auth().add_checker(
- [&](TSRPCHandlerOptions const &opt, ts::Errata &errata) -> void { return late_check_peer_credentials(fd, opt, errata); });
+ [&](TSRPCHandlerOptions const &opt, swoc::Errata &errata) -> void { late_check_peer_credentials(fd, opt, errata); });
if (auto response = rpc::JsonRPCManager::instance().handle_call(ctx, json); response) {
// seems a valid response.
@@ -446,19 +446,23 @@ IPCSocketServer::Config::Config()
}
void
-IPCSocketServer::late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const
+IPCSocketServer::late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, swoc::Errata &errata) const
{
swoc::LocalBufferWriter<256> w;
// For privileged calls, ensure we have caller credentials and that the caller is privileged.
+ auto ecode = [](UnauthorizedErrorCode c) -> std::error_code {
+ return std::error_code(static_cast<unsigned>(c), std::generic_category());
+ };
+
if (has_peereid() && options.auth.restricted) {
uid_t euid = -1;
gid_t egid = -1;
if (get_peereid(peedFd, &euid, &egid) == -1) {
- errata.push(1, static_cast<int>(UnauthorizedErrorCode::PEER_CREDENTIALS_ERROR),
- w.print("Error getting peer credentials: {}\0", swoc::bwf::Errno{}).data());
+ errata.assign(ecode(UnauthorizedErrorCode::PEER_CREDENTIALS_ERROR))
+ .note("Error getting peer credentials: {}", swoc::bwf::Errno{});
} else if (euid != 0 && euid != geteuid()) {
- errata.push(1, static_cast<int>(UnauthorizedErrorCode::PERMISSION_DENIED),
- w.print("Denied privileged API access for uid={} gid={}\0", euid, egid).data());
+ errata.assign(ecode(UnauthorizedErrorCode::PERMISSION_DENIED))
+ .note("Denied privileged API access for uid={} gid={}", euid, egid);
}
}
}
diff --git a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
index c08183e34a..c28abd21bc 100644
--- a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
+++ b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
@@ -45,7 +45,7 @@
#include "tscore/Layout.h"
#include "iocore/utils/diags.i"
-#define DEFINE_JSONRPC_PROTO_FUNCTION(fn) ts::Rv<YAML::Node> fn(std::string_view const &id, const YAML::Node ¶ms)
+#define DEFINE_JSONRPC_PROTO_FUNCTION(fn) swoc::Rv<YAML::Node> fn(std::string_view const &id, const YAML::Node ¶ms)
namespace fs = swoc::file;
@@ -127,7 +127,7 @@ RPCServerTestListener::~RPCServerTestListener() {}
DEFINE_JSONRPC_PROTO_FUNCTION(some_foo) // id, params
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
int dur{1};
try {
dur = params["duration"].as<int>();
@@ -309,7 +309,7 @@ random_string(std::string::size_type length)
DEFINE_JSONRPC_PROTO_FUNCTION(do_nothing) // id, params, resp
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
resp.result()["size"] = params["msg"].as<std::string>().size();
return resp;
}
diff --git a/src/proxy/CMakeLists.txt b/src/proxy/CMakeLists.txt
index 508ba7c1d8..6b25c6683d 100644
--- a/src/proxy/CMakeLists.txt
+++ b/src/proxy/CMakeLists.txt
@@ -47,7 +47,7 @@ endif()
target_link_libraries(
proxy
PUBLIC ts::inkcache ts::inkevent ts::tsutil ts::tscore
- PRIVATE ts::jsonrpc_protocol ts::inkutils ts::tsapibackend
+ PRIVATE ts::rpcpublichandlers ts::jsonrpc_protocol ts::inkutils ts::tsapibackend
)
add_subdirectory(hdrs)
diff --git a/src/proxy/HostStatus.cc b/src/proxy/HostStatus.cc
index 121770fbe9..9e8e7fb540 100644
--- a/src/proxy/HostStatus.cc
+++ b/src/proxy/HostStatus.cc
@@ -44,8 +44,8 @@ struct HostCmdInfo {
} // namespace
-ts::Rv<YAML::Node> server_get_status(std::string_view const id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> server_set_status(std::string_view const id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> server_get_status(std::string_view const id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> server_set_status(std::string_view const id, YAML::Node const ¶ms);
HostStatRec::HostStatRec()
: status(TS_HOST_STATUS_UP),
@@ -419,11 +419,11 @@ template <> struct convert<HostCmdInfo> {
} // namespace YAML
// JSON-RPC method to retrieve host status information.
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_get_status(std::string_view id, YAML::Node const ¶ms)
{
namespace err = rpc::handlers::errors;
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
YAML::Node statusList{YAML::NodeType::Sequence}, errorList{YAML::NodeType::Sequence};
try {
@@ -470,12 +470,12 @@ server_get_status(std::string_view id, YAML::Node const ¶ms)
}
// JSON-RPC method to mark up or down a host.
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_set_status(std::string_view id, YAML::Node const ¶ms)
{
Debug("host_statuses", "id=%s", id.data());
namespace err = rpc::handlers::errors;
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
try {
if (!params.IsNull()) {
@@ -489,7 +489,7 @@ server_set_status(std::string_view id, YAML::Node const ¶ms)
hs.setHostStatus(name.c_str(), cmdInfo.type, cmdInfo.time, cmdInfo.reasonType);
}
} else {
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Invalid input parameters, null"));
+ resp.errata().assign(std::error_code{rpc::handlers::errors::Codes::SERVER}).note("Invalid input parameters, null");
}
// schedule a write to the persistent store.
@@ -497,7 +497,9 @@ server_set_status(std::string_view id, YAML::Node const ¶ms)
eventProcessor.schedule_imm(new HostStatusSync, ET_TASK);
} catch (std::exception const &ex) {
Debug("host_statuses", "Got an error HostCmdInfo decoding: %s", ex.what());
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Error found during host status set: {}", ex.what()));
+ resp.errata()
+ .assign(std::error_code{rpc::handlers::errors::Codes::SERVER})
+ .note("Error found during host status set: {}", ex.what());
}
return resp;
}
diff --git a/src/proxy/http/HttpConfig.cc b/src/proxy/http/HttpConfig.cc
index aadc77e8a9..1cfde695b2 100644
--- a/src/proxy/http/HttpConfig.cc
+++ b/src/proxy/http/HttpConfig.cc
@@ -22,6 +22,8 @@
limitations under the License.
*/
+#include <deque>
+
#include "tscore/ink_config.h"
#include "tscore/Filenames.h"
#include "tscore/Tokenizer.h"
diff --git a/src/traffic_cache_tool/CacheTool.cc b/src/traffic_cache_tool/CacheTool.cc
index 6b187e2cd5..8d1b07652f 100644
--- a/src/traffic_cache_tool/CacheTool.cc
+++ b/src/traffic_cache_tool/CacheTool.cc
@@ -47,6 +47,7 @@
using swoc::MemSpan;
using swoc::Errata;
+using ts::make_errno_code;
using ts::Bytes;
using ts::Megabytes;
diff --git a/src/tscore/CMakeLists.txt b/src/tscore/CMakeLists.txt
index 68ed20e878..b7722e99a4 100644
--- a/src/tscore/CMakeLists.txt
+++ b/src/tscore/CMakeLists.txt
@@ -39,7 +39,6 @@ add_library(
CryptoHash.cc
Diags.cc
Encoding.cc
- Errata.cc
EventNotify.cc
Extendible.cc
FrequencyCounter.cc
@@ -145,7 +144,6 @@ if(BUILD_TESTING)
unit_tests/test_AcidPtr.cc
unit_tests/test_ArgParser.cc
unit_tests/test_CryptoHash.cc
- unit_tests/test_Errata.cc
unit_tests/test_Extendible.cc
unit_tests/test_Encoding.cc
unit_tests/test_FrequencyCounter.cc
diff --git a/src/tscore/Errata.cc b/src/tscore/Errata.cc
deleted file mode 100644
index ded3bf5e80..0000000000
--- a/src/tscore/Errata.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/** @file
- Errata implementation.
-
- @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 "tscore/Errata.h"
-
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-#include <algorithm>
-#include <memory.h>
-
-namespace ts
-{
-/** List of sinks for abandoned erratum.
- */
-namespace
-{
- std::deque<Errata::Sink::Handle> Sink_List;
-}
-
-std::string const Errata::DEFAULT_GLUE("\n");
-Errata::Message const Errata::NIL_MESSAGE;
-Errata::Code Errata::Message::Default_Code = 0;
-Errata::Message::SuccessTest const Errata::Message::DEFAULT_SUCCESS_TEST = &Errata::Message::isCodeZero;
-Errata::Message::SuccessTest Errata::Message::Success_Test = Errata::Message::DEFAULT_SUCCESS_TEST;
-
-bool
-Errata::Message::isCodeZero(Message const &msg)
-{
- return msg.m_code == 0;
-}
-
-void
-Errata::Data::push(Message const &msg)
-{
- m_items.push_back(msg);
-}
-
-void
-Errata::Data::push(Message &&msg)
-{
- m_items.push_back(std::move(msg));
-}
-
-Errata::Message const &
-Errata::Data::top() const
-{
- return m_items.size() ? m_items.back() : NIL_MESSAGE;
-}
-
-inline Errata::Errata(ImpPtr const &ptr) : m_data(ptr) {}
-
-Errata::Data::~Data()
-{
- if (m_log_on_delete) {
- Errata tmp(ImpPtr(this)); // because client API requires a wrapper.
- for (auto &f : Sink_List) {
- (*f)(tmp);
- }
- tmp.m_data.release(); // don't delete this again.
- }
-}
-
-Errata::Errata(self const &that) : m_data(that.m_data) {}
-
-Errata::Errata(self &&that) : m_data(that.m_data) {}
-
-Errata::Errata(std::string const &text)
-{
- this->push(text);
-}
-
-Errata::Errata(Id id, std::string const &text)
-{
- this->push(id, text);
-}
-
-Errata::~Errata() {}
-
-/* This forces the errata to have a data object that only it references.
- If we're sharing the data, clone. If there's no data, allocate.
- This is used just before a write operation to have copy on write semantics.
- */
-Errata::Data *
-Errata::pre_write()
-{
- if (m_data) {
- if (m_data.use_count() > 1) {
- m_data.reset(new Data(*m_data)); // clone current data
- }
- } else { // create new data
- m_data.reset(new Data);
- }
- return m_data.get();
-}
-
-// Just create an instance if needed.
-Errata::Data const *
-Errata::instance()
-{
- if (!m_data) {
- m_data.reset(new Data);
- }
- return m_data.get();
-}
-
-Errata &
-Errata::push(Message const &msg)
-{
- this->pre_write()->push(msg);
- return *this;
-}
-
-Errata &
-Errata::push(Message &&msg)
-{
- this->pre_write()->push(std::move(msg));
- return *this;
-}
-
-Errata &
-Errata::operator=(self const &that)
-{
- m_data = that.m_data;
- return *this;
-}
-
-Errata &
-Errata::operator=(Message const &msg)
-{
- // Avoid copy on write in the case where we discard.
- if (!m_data || m_data.use_count() > 1) {
- this->clear();
- this->push(msg);
- } else {
- m_data->m_items.clear();
- m_data->push(msg);
- }
- return *this;
-}
-
-Errata &
-Errata::operator=(self &&that)
-{
- m_data = that.m_data;
- return *this;
-}
-
-Errata &
-Errata::pull(self &that)
-{
- if (that.m_data) {
- this->pre_write();
- m_data->m_items.insert(m_data->m_items.end(), that.m_data->m_items.begin(), that.m_data->m_items.end());
- that.m_data->m_items.clear();
- }
- return *this;
-}
-
-void
-Errata::pop()
-{
- if (m_data && m_data->size()) {
- this->pre_write()->m_items.pop_front();
- }
- return;
-}
-
-void
-Errata::clear()
-{
- m_data.reset(nullptr);
-}
-
-/* We want to allow iteration on empty / nil containers because that's very
- convenient for clients. We need only return the same value for begin()
- and end() and everything works as expected.
-
- However we need to be a bit more clever for VC 8. It checks for
- iterator compatibility, i.e. that the iterators are not
- invalidated and that they are for the same container. It appears
- that default iterators are not compatible with anything. So we
- use static container for the nil data case.
- */
-static Errata::Container NIL_CONTAINER;
-
-Errata::iterator
-Errata::begin()
-{
- return m_data ? m_data->m_items.rbegin() : NIL_CONTAINER.rbegin();
-}
-
-Errata::const_iterator
-Errata::begin() const
-{
- return m_data ? static_cast<Data const &>(*m_data).m_items.rbegin() : static_cast<Container const &>(NIL_CONTAINER).rbegin();
-}
-
-Errata::iterator
-Errata::end()
-{
- return m_data ? m_data->m_items.rend() : NIL_CONTAINER.rend();
-}
-
-Errata::const_iterator
-Errata::end() const
-{
- return m_data ? static_cast<Data const &>(*m_data).m_items.rend() : static_cast<Container const &>(NIL_CONTAINER).rend();
-}
-
-void
-Errata::registerSink(Sink::Handle const &s)
-{
- Sink_List.push_back(s);
-}
-
-std::ostream &
-Errata::write(std::ostream &out, int offset, int indent, int shift, char const *lead) const
-{
- for (auto m : *this) {
- if ((offset + indent) > 0) {
- out << std::setw(indent + offset) << std::setfill(' ') << ((indent > 0 && lead) ? lead : " ");
- }
-
- out << m.m_id << " [" << m.m_code << "]: " << m.m_text << std::endl;
- if (m.getErrata().size()) {
- m.getErrata().write(out, offset, indent + shift, shift, lead);
- }
- }
- return out;
-}
-
-size_t
-Errata::write(char *buff, size_t n, int offset, int indent, int shift, char const *lead) const
-{
- std::ostringstream out;
- std::string text;
- this->write(out, offset, indent, shift, lead);
- text = out.str();
- memcpy(buff, text.data(), std::min(n, text.size()));
- return text.size();
-}
-
-std::ostream &
-operator<<(std::ostream &os, Errata const &err)
-{
- return err.write(os, 0, 0, 2, "> ");
-}
-
-} // namespace ts
diff --git a/src/tscore/unit_tests/test_Errata.cc b/src/tscore/unit_tests/test_Errata.cc
deleted file mode 100644
index f19273a782..0000000000
--- a/src/tscore/unit_tests/test_Errata.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- @file Test for Errata
-
- @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 "catch.hpp"
-
-#include "tscore/Errata.h"
-
-TEST_CASE("Basic Errata with text only", "[errata]")
-{
- ts::Errata err;
- std::string text{"Some error text"};
- err.push(text);
- REQUIRE(err.isOK()); // as code is 0 by default.
- REQUIRE(err.top().text() == text);
-}
-
-TEST_CASE("Basic Errata test with id and text", "[errata]")
-{
- ts::Errata err;
- int id{1};
- std::string text{"Some error text"};
-
- err.push(id, text);
-
- REQUIRE(err.isOK()); // as code is 0 by default.
- REQUIRE(err.top().text() == text);
-}
-
-TEST_CASE("Basic Errata test with id,code and text", "[errata]")
-{
- ts::Errata err;
- int id{1};
- unsigned int code{2};
- std::string text{"Some error text"};
-
- err.push(id, code, text);
-
- REQUIRE(!err.isOK()); // This should not be ok as code now is 2
- REQUIRE(err.top().getCode() == code);
- REQUIRE(err.top().text() == text);
-}
diff --git a/src/tsutil/CMakeLists.txt b/src/tsutil/CMakeLists.txt
index 0cd0ab8fd4..17f7f19b2d 100644
--- a/src/tsutil/CMakeLists.txt
+++ b/src/tsutil/CMakeLists.txt
@@ -37,6 +37,7 @@ set(TSUTIL_PUBLIC_HEADERS
${PROJECT_SOURCE_DIR}/include/tsutil/ts_meta.h
${PROJECT_SOURCE_DIR}/include/tsutil/ts_time_parser.h
${PROJECT_SOURCE_DIR}/include/tsutil/ts_unit_parser.h
+ ${PROJECT_SOURCE_DIR}/include/tsutil/ts_errata.h
)
add_library(
tsutil
@@ -49,6 +50,7 @@ add_library(
YamlCfg.cc
ts_unit_parser.cc
Regex.cc
+ ts_errata.cc
)
add_library(ts::tsutil ALIAS tsutil)
diff --git a/src/tsutil/ts_errata.cc b/src/tsutil/ts_errata.cc
new file mode 100644
index 0000000000..fc10b11eb8
--- /dev/null
+++ b/src/tsutil/ts_errata.cc
@@ -0,0 +1,34 @@
+/** @file
+
+ Utilities for @c swoc::Errata
+
+ @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 "tsutil/ts_errata.h"
+
+namespace ts
+{
+std::string
+err_category::message(int code) const
+{
+ std::string s;
+ swoc::bwprint(s, "{}", swoc::bwf::Errno(code));
+ return s;
+}
+} // namespace ts
diff --git a/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc b/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
index 41d94bbe53..9bf7fe937f 100644
--- a/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
+++ b/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
@@ -27,9 +27,9 @@
#include <fstream>
#include "swoc/swoc_file.h"
+#include "tsutil/ts_bw_format.h"
#include "yaml-cpp/yaml.h"
-#include "tscore/Errata.h"
#include "tscore/Layout.h"
#include "tsutil/ts_bw_format.h"
#include "mgmt/rpc/jsonrpc/JsonRPC.h"