#include #include "proxysql.h" #include "proxysql_atomic.h" #include #ifdef DEBUG #ifdef DEBUG_EXTERN #undef DEBUG_EXTERN #endif /* DEBUG_EXTERN */ #endif /* DEBUG */ #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC SYSTEM_CLOCK #endif // CLOCK_MONOTONIC #ifdef DEBUG static unsigned long long pretime=0; static pthread_mutex_t debug_mutex; #endif /* DEBUG */ static inline unsigned long long debug_monotonic_time() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (((unsigned long long) ts.tv_sec) * 1000000) + (ts.tv_nsec / 1000); } #define DEBUG_MSG_MAXSIZE 1024 #ifdef DEBUG // this set will have all the filters related to debug // for convention, the key is: // filename:line:function // this key structure applies also if line is 0 or function is empty // filename is mandatory std::set debug_filters; static bool filter_debug_entry(const char *__file, int __line, const char *__func) { pthread_mutex_lock(&debug_mutex); bool to_filter = false; if (debug_filters.size()) { // if the set is empty we aren't performing any filter, so we won't search std::string key(__file); key += ":" + std::to_string(__line); key += ":"; key += __func; // we start with a full search if (debug_filters.find(key) != debug_filters.end()) { to_filter = true; } else { // we now search filename + line key = __file; key += ":" + std::to_string(__line); // remember to add the final ":" key += ":"; if (debug_filters.find(key) != debug_filters.end()) { to_filter = true; } else { // we now search filename + function key = __file; // no line = 0 key += ":0:"; key += __func; if (debug_filters.find(key) != debug_filters.end()) { to_filter = true; } else { // we now search filename only key = __file; // remember to add ":" even if no line key += ":0:"; if (debug_filters.find(key) != debug_filters.end()) { to_filter = true; } else { // if we reached here, we couldn't find any filter } } } } } pthread_mutex_unlock(&debug_mutex); return to_filter; } // we use this function to sent the filters to Admin // we hold here the mutex on debug_mutex void proxy_debug_get_filters(std::set& f) { pthread_mutex_lock(&debug_mutex); f = debug_filters; pthread_mutex_unlock(&debug_mutex); } // we use this function to get the filters from Admin // we hold here the mutex on debug_mutex void proxy_debug_load_filters(std::set& f) { pthread_mutex_lock(&debug_mutex); debug_filters.erase(debug_filters.begin(), debug_filters.end()); debug_filters = f; pthread_mutex_unlock(&debug_mutex); } void proxy_debug_func(enum debug_module module, int verbosity, int thr, const char *__file, int __line, const char *__func, const char *fmt, ...) { assert(module=10) { void *arr[20]; char **strings; int s; s = backtrace(arr, 20); //backtrace_symbols_fd(arr, s, STDERR_FILENO); strings=backtrace_symbols(arr,s); if (strings == NULL) { perror("backtrace_symbols"); exit(EXIT_FAILURE); } for (int i=0; i 0) { ssize_t ret = write(fd, buf, len); if ((ret == -1) && (errno != EINTR)) break; buf += (size_t) ret; len -= (size_t) ret; } } void print_backtrace(void) { static const char start[] = "BACKTRACE ------------\n"; static const char end[] = "----------------------\n"; void *bt[1024]; int bt_size; char **bt_syms; int i; bt_size = backtrace(bt, 1024); bt_syms = backtrace_symbols(bt, bt_size); full_write(STDERR_FILENO, start, strlen(start)); for (i = 1; i < bt_size; i++) { size_t len = strlen(bt_syms[i]); full_write(STDERR_FILENO, bt_syms[i], len); full_write(STDERR_FILENO, "\n", 1); } full_write(STDERR_FILENO, end, strlen(end)); free(bt_syms); } #ifdef DEBUG void init_debug_struct() { int i; pthread_mutex_init(&debug_mutex,NULL); pretime=debug_monotonic_time(); GloVars.global.gdbg_lvl= (debug_level *) malloc(PROXY_DEBUG_UNKNOWN*sizeof(debug_level)); for (i=0;i