There are three handler that need to be patched all at once with the server itself being marked with set_content_streaming For two simple handler just get the content string with read_entire_stream_contiguous helper. This is what httpd server did anyway. The "start_restore" handler used the contiguous contents to parse json from using rjson utility. This handler is patched to use read_entire_stream() that returns a vector of temporary buffers. The rjson parser has a helper to pars from that vector, so the change is also optimization. Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
107 lines
4.0 KiB
C++
107 lines
4.0 KiB
C++
/*
|
|
* Copyright (C) 2020-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
|
|
*/
|
|
|
|
#include "api/api-doc/error_injection.json.hh"
|
|
#include "api/api_init.hh"
|
|
#include <seastar/http/exception.hh>
|
|
#include "utils/error_injection.hh"
|
|
#include "utils/rjson.hh"
|
|
#include <seastar/core/future-util.hh>
|
|
#include <seastar/util/short_streams.hh>
|
|
|
|
namespace api {
|
|
using namespace seastar::httpd;
|
|
|
|
namespace hf = httpd::error_injection_json;
|
|
|
|
void set_error_injection(http_context& ctx, routes& r) {
|
|
|
|
hf::enable_injection.set(r, [](std::unique_ptr<request> req) -> future<json::json_return_type> {
|
|
sstring injection = req->get_path_param("injection");
|
|
bool one_shot = req->get_query_param("one_shot") == "True";
|
|
auto params = co_await util::read_entire_stream_contiguous(*req->content_stream);
|
|
|
|
const size_t max_params_size = 1024 * 1024;
|
|
if (params.size() > max_params_size) {
|
|
// This is a hard limit, because we don't want to allocate
|
|
// too much memory or block the thread for too long.
|
|
throw httpd::bad_param_exception(format("Injection parameters are too long, max length is {}", max_params_size));
|
|
}
|
|
|
|
try {
|
|
auto parameters = params.empty()
|
|
? utils::error_injection_parameters{}
|
|
: rjson::parse_to_map<utils::error_injection_parameters>(params);
|
|
|
|
auto& errinj = utils::get_local_injector();
|
|
co_await errinj.enable_on_all(injection, one_shot, std::move(parameters));
|
|
} catch (const rjson::error& e) {
|
|
throw httpd::bad_param_exception(format("Failed to parse injections parameters: {}", e.what()));
|
|
}
|
|
co_return json::json_void();
|
|
});
|
|
|
|
hf::get_enabled_injections_on_all.set(r, [](std::unique_ptr<request> req) {
|
|
auto& errinj = utils::get_local_injector();
|
|
auto ret = errinj.enabled_injections_on_all();
|
|
return make_ready_future<json::json_return_type>(ret);
|
|
});
|
|
|
|
hf::disable_injection.set(r, [](std::unique_ptr<request> req) {
|
|
sstring injection = req->get_path_param("injection");
|
|
|
|
auto& errinj = utils::get_local_injector();
|
|
return errinj.disable_on_all(injection).then([] {
|
|
return make_ready_future<json::json_return_type>(json::json_void());
|
|
});
|
|
});
|
|
|
|
hf::read_injection.set(r, [](std::unique_ptr<request> req) -> future<json::json_return_type> {
|
|
const sstring injection = req->get_path_param("injection");
|
|
|
|
std::vector<error_injection_json::error_injection_info> error_injection_infos(smp::count, error_injection_json::error_injection_info{});
|
|
|
|
co_await smp::invoke_on_all([&] {
|
|
auto& info = error_injection_infos[this_shard_id()];
|
|
auto& errinj = utils::get_local_injector();
|
|
const auto enabled = errinj.is_enabled(injection);
|
|
info.enabled = enabled;
|
|
if (!enabled) {
|
|
return;
|
|
}
|
|
std::vector<error_injection_json::mapper> parameters;
|
|
for (const auto& p : errinj.get_injection_parameters(injection)) {
|
|
error_injection_json::mapper param;
|
|
param.key = p.first;
|
|
param.value = p.second;
|
|
parameters.push_back(std::move(param));
|
|
}
|
|
info.parameters = std::move(parameters);
|
|
});
|
|
|
|
co_return json::json_return_type(error_injection_infos);
|
|
});
|
|
|
|
hf::disable_on_all.set(r, [](std::unique_ptr<request> req) {
|
|
auto& errinj = utils::get_local_injector();
|
|
return errinj.disable_on_all().then([] {
|
|
return make_ready_future<json::json_return_type>(json::json_void());
|
|
});
|
|
});
|
|
|
|
hf::message_injection.set(r, [](std::unique_ptr<request> req) {
|
|
sstring injection = req->get_path_param("injection");
|
|
auto& errinj = utils::get_local_injector();
|
|
return errinj.receive_message_on_all(injection).then([] {
|
|
return make_ready_future<json::json_return_type>(json::json_void());
|
|
});
|
|
});
|
|
}
|
|
|
|
} // namespace api
|