mdbx: добавление mdbx_setup_debug_nofmt() и возможности установки логера без функционала printf().

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2024-03-25 18:39:56 +03:00
parent af060b4960
commit 5c84c405ac
4 changed files with 70 additions and 14 deletions

12
mdbx.h
View File

@ -1012,6 +1012,7 @@ typedef void MDBX_debug_func(MDBX_log_level_t loglevel, const char *function,
/** \brief The "don't change `logger`" value for mdbx_setup_debug() */
#define MDBX_LOGGER_DONTCHANGE ((MDBX_debug_func *)(intptr_t)-1)
#define MDBX_LOGGER_NOFMT_DONTCHANGE ((MDBX_debug_func_nofmt *)(intptr_t)-1)
/** \brief Setup global log-level, debug options and debug logger.
* \returns The previously `debug_flags` in the 0-15 bits
@ -1020,6 +1021,17 @@ LIBMDBX_API int mdbx_setup_debug(MDBX_log_level_t log_level,
MDBX_debug_flags_t debug_flags,
MDBX_debug_func *logger);
typedef void MDBX_debug_func_nofmt(MDBX_log_level_t loglevel,
const char *function, int line,
const char *msg,
unsigned length) MDBX_CXX17_NOEXCEPT;
LIBMDBX_API int mdbx_setup_debug_nofmt(MDBX_log_level_t log_level,
MDBX_debug_flags_t debug_flags,
MDBX_debug_func_nofmt *logger,
char *logger_buffer,
size_t logger_buffer_size);
/** \brief A callback function for most MDBX assert() failures,
* called before printing the message and aborting.
* \see mdbx_env_set_assert()

View File

@ -1445,6 +1445,10 @@ __cold void thread_dtor(void *rthc) {
#endif
}
MDBX_INTERNAL_VAR_INSTA struct mdbx_static mdbx_static = {
MDBX_RUNTIME_FLAGS_INIT, MDBX_LOG_FATAL, {nullptr}, 0, nullptr};
static osal_fastmutex_t debug_lock;
MDBX_EXCLUDE_FOR_GPROF
__cold void global_dtor(void) {
const uint32_t current_pid = osal_getpid();
@ -1547,6 +1551,7 @@ __cold void global_dtor(void) {
osal_dtor();
TRACE("<< pid %d\n", current_pid);
ENSURE(nullptr, osal_fastmutex_destroy(&debug_lock) == 0);
}
__cold int rthc_register(MDBX_env *const env) {
@ -3233,9 +3238,6 @@ static __always_inline int __must_check_result dpl_append(MDBX_txn *txn,
/*----------------------------------------------------------------------------*/
MDBX_INTERNAL_VAR_INSTA struct mdbx_static mdbx_static = {
MDBX_RUNTIME_FLAGS_INIT, MDBX_LOG_FATAL, nullptr, 0, nullptr};
static __must_check_result __inline int page_retire(MDBX_cursor *mc,
MDBX_page *mp);
@ -3587,9 +3589,18 @@ const char *mdbx_strerror_ANSI2OEM(int errnum) {
__cold void debug_log_va(int level, const char *function, int line,
const char *fmt, va_list args) {
if (mdbx_static.logger)
mdbx_static.logger(level, function, line, fmt, args);
else {
ENSURE(nullptr, osal_fastmutex_acquire(&debug_lock) == 0);
if (mdbx_static.logger.ptr) {
if (mdbx_static.logger_buffer == nullptr)
mdbx_static.logger.fmt(level, function, line, fmt, args);
else {
const int len = vsnprintf(mdbx_static.logger_buffer,
mdbx_static.logger_buffer_size, fmt, args);
if (len > 0)
mdbx_static.logger.nofmt(level, function, line,
mdbx_static.logger_buffer, len);
}
} else {
#if defined(_WIN32) || defined(_WIN64)
if (IsDebuggerPresent()) {
int prefix_len = 0;
@ -3622,6 +3633,7 @@ __cold void debug_log_va(int level, const char *function, int line,
fflush(stderr);
#endif
}
ENSURE(nullptr, osal_fastmutex_release(&debug_lock) == 0);
}
__cold void debug_log(int level, const char *function, int line,
@ -24621,10 +24633,12 @@ __cold MDBX_INTERNAL_FUNC int cleanup_dead_readers(MDBX_env *env,
return rc;
}
__cold int mdbx_setup_debug(MDBX_log_level_t level, MDBX_debug_flags_t flags,
MDBX_debug_func *logger) {
const int rc = mdbx_static.flags | (mdbx_static.loglevel << 16);
__cold static int setup_debug(MDBX_log_level_t level, MDBX_debug_flags_t flags,
union logger_union logger, char *buffer,
size_t buffer_size) {
ENSURE(nullptr, osal_fastmutex_acquire(&debug_lock) == 0);
const int rc = mdbx_static.flags | (mdbx_static.loglevel << 16);
if (level != MDBX_LOG_DONTCHANGE)
mdbx_static.loglevel = (uint8_t)level;
@ -24638,11 +24652,34 @@ __cold int mdbx_setup_debug(MDBX_log_level_t level, MDBX_debug_flags_t flags,
mdbx_static.flags = (uint8_t)flags;
}
if (logger != MDBX_LOGGER_DONTCHANGE)
mdbx_static.logger = logger;
assert(MDBX_LOGGER_DONTCHANGE == ((MDBX_debug_func *)(intptr_t)-1));
if (logger.ptr != (void *)((intptr_t)-1)) {
mdbx_static.logger.ptr = logger.ptr;
mdbx_static.logger_buffer = buffer;
mdbx_static.logger_buffer_size = buffer_size;
}
ENSURE(nullptr, osal_fastmutex_release(&debug_lock) == 0);
return rc;
}
__cold int mdbx_setup_debug_nofmt(MDBX_log_level_t level,
MDBX_debug_flags_t flags,
MDBX_debug_func_nofmt *logger, char *buffer,
size_t buffer_size) {
union logger_union thunk;
thunk.nofmt =
(logger && buffer && buffer_size) ? logger : MDBX_LOGGER_NOFMT_DONTCHANGE;
return setup_debug(level, flags, thunk, buffer, buffer_size);
}
__cold int mdbx_setup_debug(MDBX_log_level_t level, MDBX_debug_flags_t flags,
MDBX_debug_func *logger) {
union logger_union thunk;
thunk.fmt = logger;
return setup_debug(level, flags, thunk, nullptr, 0);
}
__cold static txnid_t kick_longlived_readers(MDBX_env *env,
const txnid_t laggard) {
DEBUG("DB size maxed out by reading #%" PRIaTXN, laggard);
@ -26761,6 +26798,7 @@ __cold static void rthc_afterfork(void) {
#endif /* ! Windows */
__cold void global_ctor(void) {
ENSURE(nullptr, osal_fastmutex_init(&debug_lock) == 0);
osal_ctor();
rthc_limit = RTHC_INITIAL_LIMIT;
rthc_table = rthc_table_static;

View File

@ -244,10 +244,16 @@ extern LIBMDBX_API const char *const mdbx_sourcery_anchor;
#define MDBX_RUNTIME_FLAGS_INIT \
((MDBX_DEBUG) > 0) * MDBX_DBG_ASSERT + ((MDBX_DEBUG) > 1) * MDBX_DBG_AUDIT
union logger_union {
void *ptr;
MDBX_debug_func *fmt;
MDBX_debug_func_nofmt *nofmt;
};
MDBX_INTERNAL_VAR_PROTO struct mdbx_static {
uint8_t flags;
uint8_t loglevel;
MDBX_debug_func *logger;
union logger_union logger;
size_t logger_buffer_size;
char *logger_buffer;
} mdbx_static;

View File

@ -244,7 +244,7 @@ MDBX_NORETURN __cold void assert_fail(const char *msg, const char *func,
unsigned line) {
#endif /* MDBX_DEBUG */
if (mdbx_static.logger)
if (mdbx_static.logger.ptr)
debug_log(MDBX_LOG_FATAL, func, line, "assert: %s\n", msg);
else {
#if defined(_WIN32) || defined(_WIN64)
@ -287,7 +287,7 @@ __cold void mdbx_panic(const char *fmt, ...) {
? "<troubles with panic-message preparation>"
: message;
if (mdbx_static.logger)
if (mdbx_static.logger.ptr)
debug_log(MDBX_LOG_FATAL, "panic", 0, "%s", const_message);
while (1) {