Files
scylladb/exceptions/exceptions.cc
Nadav Har'El f84094320d exceptions: de-inline exception constructors
The header file "exceptions/exceptions.hh" and the exception types in it
is used by virtually every source file in Scylla, so excessive includes
and templated code generation in this header could slow down the build
considerably.

Before this patch, all of the exceptions' constructors were inline in
exceptions.hh, so source file using one of these exceptions will need
to recompile the code, which is fairly heavy, using the fmt templates
for various types. According to ClangBuildAnalyzer, 323 source files
needed to materialize prepare_message<db::consistency_level,int&,int&>,
taking 0.3 seconds each.

So this patch moves the exception constructors from the header file
exceptions.hh to the source file exceptions.cc. The header file no longer
uses fmt.

Unfortunately, the actual build-time savings from this patch is tiny -
around 0.1%... It turns out that most of the prepare_message<>
compilation time comes from fmt compilation time, and since virtually
all source files use fmt for other header reasons (intentionally or
through other headers), no compilation time can be saved. Nevertheless,
I hope that as we proceed with more cleanups like this and eliminate
more unnecessary code-generation-in-headers, we'll start seeing build
time drop.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2022-02-28 14:47:41 +02:00

105 lines
4.3 KiB
C++

/*
*/
/*
* Copyright (C) 2015-present ScyllaDB
*
* Modified by ScyllaDB
*/
/*
* SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0)
*/
#include <sstream>
#include "exceptions.hh"
#include "log.hh"
namespace exceptions {
truncate_exception::truncate_exception(std::exception_ptr ep)
: request_execution_exception(exceptions::exception_code::TRUNCATE_ERROR, format("Error during truncate: {}", ep))
{}
const std::unordered_map<exception_code, sstring>& exception_map() {
static const std::unordered_map<exception_code, sstring> map {
{exception_code::SERVER_ERROR, "server_error"},
{exception_code::PROTOCOL_ERROR, "protocol_error"},
{exception_code::BAD_CREDENTIALS, "authentication"},
{exception_code::UNAVAILABLE, "unavailable"},
{exception_code::OVERLOADED, "overloaded"},
{exception_code::IS_BOOTSTRAPPING, "is_bootstrapping"},
{exception_code::TRUNCATE_ERROR, "truncate_error"},
{exception_code::WRITE_TIMEOUT, "write_timeout"},
{exception_code::READ_TIMEOUT, "read_timeout"},
{exception_code::READ_FAILURE, "read_failure"},
{exception_code::FUNCTION_FAILURE, "function_failure"},
{exception_code::WRITE_FAILURE, "write_failure"},
{exception_code::CDC_WRITE_FAILURE, "cdc_write_failure"},
{exception_code::SYNTAX_ERROR, "syntax_error"},
{exception_code::UNAUTHORIZED, "unathorized"},
{exception_code::INVALID, "invalid"},
{exception_code::CONFIG_ERROR, "config_error"},
{exception_code::ALREADY_EXISTS, "already_exists"},
{exception_code::UNPREPARED, "unprepared"}
};
return map;
}
template<typename... Args>
static inline sstring prepare_message(const char* fmt, Args&&... args) noexcept {
try {
return format(fmt, std::forward<Args>(args)...);
} catch (...) {
return sstring();
}
}
unavailable_exception::unavailable_exception(db::consistency_level cl, int32_t required, int32_t alive) noexcept
: unavailable_exception(prepare_message("Cannot achieve consistency level for cl {}. Requires {}, alive {}", cl, required, alive),
cl, required, alive)
{}
request_timeout_exception::request_timeout_exception(exception_code code, const sstring& ks, const sstring& cf, db::consistency_level consistency, int32_t received, int32_t block_for) noexcept
: cassandra_exception{code, prepare_message("Operation timed out for {}.{} - received only {} responses from {} CL={}.", ks, cf, received, block_for, consistency)}
, consistency{consistency}
, received{received}
, block_for{block_for}
{ }
request_failure_exception::request_failure_exception(exception_code code, const sstring& ks, const sstring& cf, db::consistency_level consistency_, int32_t received_, int32_t failures_, int32_t block_for_) noexcept
: cassandra_exception{code, prepare_message("Operation failed for {}.{} - received {} responses and {} failures from {} CL={}.", ks, cf, received_, failures_, block_for_, consistency_)}
, consistency{consistency_}
, received{received_}
, failures{failures_}
, block_for{block_for_}
{}
overloaded_exception::overloaded_exception(size_t c) noexcept
: cassandra_exception(exception_code::OVERLOADED, prepare_message("Too many in flight hints: {}", c))
{}
prepared_query_not_found_exception::prepared_query_not_found_exception(bytes id) noexcept
: request_validation_exception{exception_code::UNPREPARED, prepare_message("No prepared statement with ID {} found.", id)}
, id{id}
{ }
already_exists_exception::already_exists_exception(sstring ks_name_, sstring cf_name_)
: already_exists_exception{ks_name_, cf_name_, format("Cannot add already existing table \"{}\" to keyspace \"{}\"", cf_name_, ks_name_)}
{ }
already_exists_exception::already_exists_exception(sstring ks_name_)
: already_exists_exception{ks_name_, "", format("Cannot add existing keyspace \"{}\"", ks_name_)}
{ }
function_execution_exception::function_execution_exception(sstring func_name_, sstring detail, sstring ks_name_, std::vector<sstring> args_) noexcept
: cassandra_exception{exception_code::FUNCTION_FAILURE,
format("execution of {} failed: {}", func_name_, detail)}
, ks_name(std::move(ks_name_))
, func_name(std::move(func_name_))
, args(std::move(args_))
{ }
}