blob: 97e751a48c600add66bf7b8b2d864fa031eafef1 [file] [log] [blame]
/*
* 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 <fmt/ostream.h>
#include <rocksdb/status.h>
#include "utils/api_utilities.h"
// The macros below no longer use the default snprintf method for log message formatting,
// instead we use fmt::format.
// TODO(wutao1): prevent construction of std::string for each log.
// __FILENAME__ macro comes from the cmake, in which we calculate a filename without path.
#define LOG(level, ...) \
do { \
if (level >= log_start_level) \
global_log( \
__FILENAME__, __FUNCTION__, __LINE__, level, fmt::format(__VA_ARGS__).c_str()); \
} while (false)
#define LOG_DEBUG(...) LOG(LOG_LEVEL_DEBUG, __VA_ARGS__)
#define LOG_INFO(...) LOG(LOG_LEVEL_INFO, __VA_ARGS__)
#define LOG_WARNING(...) LOG(LOG_LEVEL_WARNING, __VA_ARGS__)
#define LOG_ERROR(...) LOG(LOG_LEVEL_ERROR, __VA_ARGS__)
#define LOG_FATAL(...) LOG(LOG_LEVEL_FATAL, __VA_ARGS__)
#define LOG_WARNING_IF(x, ...) \
do { \
if (dsn_unlikely(x)) { \
LOG_WARNING(__VA_ARGS__); \
} \
} while (false)
#define LOG_ERROR_IF(x, ...) \
do { \
if (dsn_unlikely(x)) { \
LOG_ERROR(__VA_ARGS__); \
} \
} while (false)
#define LOG_WARNING_IF_PREFIX(x, ...) \
LOG_WARNING_IF(x, "[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
#define LOG_ERROR_IF_PREFIX(x, ...) \
LOG_ERROR_IF(x, "[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
#define CHECK_EXPRESSION(expression, evaluation, ...) \
do { \
if (dsn_unlikely(!(evaluation))) { \
std::string assertion_info("assertion expression: [" #expression "] "); \
assertion_info += fmt::format(__VA_ARGS__); \
LOG_FATAL(assertion_info); \
} \
} while (false)
#define CHECK(x, ...) CHECK_EXPRESSION(x, x, __VA_ARGS__)
#define CHECK_NOTNULL(p, ...) CHECK((p) != nullptr, __VA_ARGS__)
#define CHECK_NULL(p, ...) CHECK((p) == nullptr, __VA_ARGS__)
// Macros for writing log message prefixed by log_prefix().
#define LOG_DEBUG_PREFIX(...) LOG_DEBUG("[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
#define LOG_INFO_PREFIX(...) LOG_INFO("[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
#define LOG_WARNING_PREFIX(...) LOG_WARNING("[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
#define LOG_ERROR_PREFIX(...) LOG_ERROR("[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
#define LOG_FATAL_PREFIX(...) LOG_FATAL("[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
namespace {
inline const char *null_str_printer(const char *s) { return s == nullptr ? "(null)" : s; }
} // anonymous namespace
// Macros to check expected condition. It will abort the application
// and log a fatal message when the condition is not met.
#define CHECK_STREQ_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION(var1 == var2, \
dsn::utils::equals(_v1, _v2), \
"{} vs {} {}", \
null_str_printer(_v1), \
null_str_printer(_v2), \
fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_STRNE_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION(var1 != var2, \
!dsn::utils::equals(_v1, _v2), \
"{} vs {} {}", \
null_str_printer(_v1), \
null_str_printer(_v2), \
fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_STRCASEEQ_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION(var1 == var2, \
dsn::utils::iequals(_v1, _v2), \
"{} vs {} {}", \
null_str_printer(_v1), \
null_str_printer(_v2), \
fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_STRCASENE_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION(var1 != var2, \
!dsn::utils::iequals(_v1, _v2), \
"{} vs {} {}", \
null_str_printer(_v1), \
null_str_printer(_v2), \
fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_NE_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION( \
var1 != var2, _v1 != _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_EQ_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION( \
var1 == var2, _v1 == _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_GE_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION( \
var1 >= var2, _v1 >= _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_LE_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION( \
var1 <= var2, _v1 <= _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_GT_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION( \
var1 > var2, _v1 > _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_LT_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION( \
var1 < var2, _v1 < _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_STREQ(var1, var2) CHECK_STREQ_MSG(var1, var2, "")
#define CHECK_STRNE(var1, var2) CHECK_STRNE_MSG(var1, var2, "")
#define CHECK_NE(var1, var2) CHECK_NE_MSG(var1, var2, "")
#define CHECK_EQ(var1, var2) CHECK_EQ_MSG(var1, var2, "")
#define CHECK_GE(var1, var2) CHECK_GE_MSG(var1, var2, "")
#define CHECK_LE(var1, var2) CHECK_LE_MSG(var1, var2, "")
#define CHECK_GT(var1, var2) CHECK_GT_MSG(var1, var2, "")
#define CHECK_LT(var1, var2) CHECK_LT_MSG(var1, var2, "")
#define CHECK_TRUE(var) CHECK_EQ(var, true)
#define CHECK_FALSE(var) CHECK_EQ(var, false)
// TODO(yingchun): add CHECK_NULL(ptr), CHECK_OK(err), CHECK(cond)
#define CHECK_EXPRESSION_PREFIX_MSG(expression, evaluation, ...) \
CHECK_EXPRESSION(expression, evaluation, "[{}] {}", log_prefix(), fmt::format(__VA_ARGS__))
#define CHECK_PREFIX_MSG(x, ...) CHECK_EXPRESSION_PREFIX_MSG(x, x, __VA_ARGS__)
#define CHECK_NOTNULL_PREFIX_MSG(p, ...) CHECK_PREFIX_MSG(p != nullptr, __VA_ARGS__)
#define CHECK_NOTNULL_PREFIX(p) CHECK_NOTNULL_PREFIX_MSG(p, "")
#define CHECK_STREQ_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG(var1 == var2, \
dsn::utils::equals(_v1, _v2), \
"{} vs {} {}", \
null_str_printer(_v1), \
null_str_printer(_v2), \
fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_STRNE_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG(var1 != var2, \
!dsn::utils::equals(_v1, _v2), \
"{} vs {} {}", \
null_str_printer(_v1), \
null_str_printer(_v2), \
fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_NE_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG( \
var1 != var2, _v1 != _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_EQ_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG( \
var1 == var2, _v1 == _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_GE_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG( \
var1 >= var2, _v1 >= _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_LE_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG( \
var1 <= var2, _v1 <= _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_GT_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG( \
var1 > var2, _v1 > _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_LT_PREFIX_MSG(var1, var2, ...) \
do { \
const auto &_v1 = (var1); \
const auto &_v2 = (var2); \
CHECK_EXPRESSION_PREFIX_MSG( \
var1 < var2, _v1 < _v2, "{} vs {} {}", _v1, _v2, fmt::format(__VA_ARGS__)); \
} while (false)
#define CHECK_PREFIX(x) CHECK_PREFIX_MSG(x, "")
#define CHECK_NE_PREFIX(var1, var2) CHECK_NE_PREFIX_MSG(var1, var2, "")
#define CHECK_EQ_PREFIX(var1, var2) CHECK_EQ_PREFIX_MSG(var1, var2, "")
#define CHECK_GE_PREFIX(var1, var2) CHECK_GE_PREFIX_MSG(var1, var2, "")
#define CHECK_LE_PREFIX(var1, var2) CHECK_LE_PREFIX_MSG(var1, var2, "")
#define CHECK_GT_PREFIX(var1, var2) CHECK_GT_PREFIX_MSG(var1, var2, "")
#define CHECK_LT_PREFIX(var1, var2) CHECK_LT_PREFIX_MSG(var1, var2, "")
#define CHECK_OK_PREFIX(x) CHECK_EQ_PREFIX_MSG(x, ::dsn::ERR_OK, "")
// Return the given status if condition is not true.
#define LOG_AND_RETURN_NOT_TRUE(level, s, err, ...) \
do { \
if (dsn_unlikely(!(s))) { \
LOG_##level("{}: {}", err, fmt::format(__VA_ARGS__)); \
return err; \
} \
} while (0)
// Return the given status if it is not ERR_OK.
#define LOG_AND_RETURN_NOT_OK(level, s, ...) \
do { \
::dsn::error_code _err = (s); \
LOG_AND_RETURN_NOT_TRUE(level, _err == ::dsn::ERR_OK, _err, __VA_ARGS__); \
} while (0)
// Return the given rocksdb::Status of 'exp' if it is not OK.
#define LOG_AND_RETURN_NOT_RDB_OK(level, exp, ...) \
do { \
const auto &_s = (exp); \
if (dsn_unlikely(!_s.ok())) { \
LOG_##level("{}: {}", _s.ToString(), fmt::format(__VA_ARGS__)); \
return _s; \
} \
} while (0)
// Return the given 'err' code if 'exp' is not OK.
#define LOG_AND_RETURN_CODE_NOT_RDB_OK(level, exp, err, ...) \
do { \
const auto &_s = (exp); \
if (dsn_unlikely(!_s.ok())) { \
LOG_##level("{}: {}", _s.ToString(), fmt::format(__VA_ARGS__)); \
return err; \
} \
} while (0)
#ifndef NDEBUG
#define DCHECK CHECK
#define DCHECK_NOTNULL CHECK_NOTNULL
#define DCHECK_NE_MSG CHECK_NE_MSG
#define DCHECK_EQ_MSG CHECK_EQ_MSG
#define DCHECK_GE_MSG CHECK_GE_MSG
#define DCHECK_LE_MSG CHECK_LE_MSG
#define DCHECK_GT_MSG CHECK_GT_MSG
#define DCHECK_LT_MSG CHECK_LT_MSG
#define DCHECK_NE CHECK_NE
#define DCHECK_EQ CHECK_EQ
#define DCHECK_GE CHECK_GE
#define DCHECK_LE CHECK_LE
#define DCHECK_GT CHECK_GT
#define DCHECK_LT CHECK_LT
#define DCHECK_NE_PREFIX CHECK_NE_PREFIX
#define DCHECK_EQ_PREFIX CHECK_EQ_PREFIX
#define DCHECK_GE_PREFIX CHECK_GE_PREFIX
#define DCHECK_LE_PREFIX CHECK_LE_PREFIX
#define DCHECK_GT_PREFIX CHECK_GT_PREFIX
#define DCHECK_LT_PREFIX CHECK_LT_PREFIX
#else
#define DCHECK(x, ...)
#define DCHECK_NOTNULL(p, ...)
#define DCHECK_NE_MSG(var1, var2, ...)
#define DCHECK_EQ_MSG(var1, var2, ...)
#define DCHECK_GE_MSG(var1, var2, ...)
#define DCHECK_LE_MSG(var1, var2, ...)
#define DCHECK_GT_MSG(var1, var2, ...)
#define DCHECK_LT_MSG(var1, var2, ...)
#define DCHECK_NE(var1, var2)
#define DCHECK_EQ(var1, var2)
#define DCHECK_GE(var1, var2)
#define DCHECK_LE(var1, var2)
#define DCHECK_GT(var1, var2)
#define DCHECK_LT(var1, var2)
#define DCHECK_NE_PREFIX(var1, var2)
#define DCHECK_EQ_PREFIX(var1, var2)
#define DCHECK_GE_PREFIX(var1, var2)
#define DCHECK_LE_PREFIX(var1, var2)
#define DCHECK_GT_PREFIX(var1, var2)
#define DCHECK_LT_PREFIX(var1, var2)
#endif
// Macro that allows definition of a variable appended with the current line
// number in the source file. Typically for use by other macros to allow the
// user to declare multiple variables with the same "base" name inside the same
// lexical block.
#define VARNAME_LINENUM(varname) VARNAME_LINENUM_INTERNAL(varname##_L, __LINE__)
#define VARNAME_LINENUM_INTERNAL(v, line) VARNAME_LINENUM_INTERNAL2(v, line)
#define VARNAME_LINENUM_INTERNAL2(v, line) v##line