static int check_lock(struct st_lock_list *list, const char* lock_type, const char *where, my_bool same_owner, my_bool no_cond) { THR_LOCK_DATA *data,**prev; uint count=0; THR_LOCK_INFO *first_owner= NULL; prev= &list->data; if (list->data) { enum thr_lock_type last_lock_type=list->data->type; if (same_owner && list->data) first_owner= list->data->owner; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { if (data->type != last_lock_type) last_lock_type=TL_IGNORE; if (data->prev != prev) { my_message_stderr(0, "prev link %d didn't point at " "previous lock at %s: %s", count, lock_type, where); return 1; } if (same_owner && !thr_lock_owner_equal(data->owner, first_owner) && last_lock_type != TL_WRITE_ALLOW_WRITE) { my_message_stderr(0, "Found locks from different threads " "in %s: %s", lock_type, where); return 1; } if (no_cond && data->cond) { my_message_stderr(0, "Found active lock with not reset " "cond %s: %s", lock_type, where); return 1; } prev= &data->next; } if (data) { my_message_stderr(0, "found too many locks at %s: %s", lock_type, where); return 1; } } if (prev != list->last) { my_message_stderr(0, "last didn't point at last lock at %s: %s", lock_type, where); return 1; } return 0; }
time_t my_time(myf flags) { time_t t; /* The following loop is here beacuse time() may fail on some systems. We're using a hardcoded my_message_stderr() here rather than going through the hook in my_message_local() because it's far too easy to come full circle with any logging function that writes timestamps ... */ while ((t= time(0)) == (time_t) -1) { if (flags & MY_WME) my_message_stderr(0, "time() call failed", MYF(0)); } return t; }
/** Issue a message locally (i.e. on the same host the program is running on, don't transmit to a client). This is the default value for local_message_hook, and therefore the default printer for my_message_local(). mysys users should not call this directly, but go through my_message_local() instead. This printer prepends an Error/Warning/Note label to the string, then prints it to stderr using my_message_stderr(). Since my_message_stderr() appends a '\n', the format string should not end in a newline. @param ll log level: (ERROR|WARNING|INFORMATION)_LEVEL the printer may use these to filter for verbosity @param format a format string a la printf. Should not end in '\n' @param args parameters to go with that format string */ void my_message_local_stderr(enum loglevel ll, const char *format, va_list args) { char buff[1024]; size_t len; DBUG_ENTER("my_message_local_stderr"); len= my_snprintf(buff, sizeof(buff), "[%s] ", (ll == ERROR_LEVEL ? "ERROR" : ll == WARNING_LEVEL ? "Warning" : "Note")); my_vsnprintf(buff + len, sizeof(buff) - len, format, args); my_message_stderr(0, buff, MYF(0)); DBUG_VOID_RETURN; }
static void check_locks(THR_LOCK *lock, const char *where, my_bool allow_no_locks) { uint old_found_errors=found_errors; DBUG_ENTER("check_locks"); if (found_errors < MAX_FOUND_ERRORS) { if (check_lock(&lock->write,"write",where,1,1) | check_lock(&lock->write_wait,"write_wait",where,0,0) | check_lock(&lock->read,"read",where,0,1) | check_lock(&lock->read_wait,"read_wait",where,0,0)) found_errors++; if (found_errors < MAX_FOUND_ERRORS) { uint count=0; THR_LOCK_DATA *data; for (data=lock->read.data ; data ; data=data->next) { if ((int) data->type == (int) TL_READ_NO_INSERT) count++; /* Protect against infinite loop. */ DBUG_ASSERT(count <= lock->read_no_write_count); } if (count != lock->read_no_write_count) { found_errors++; my_message_stderr(0, "at '%s': Locks read_no_write_count " "was %u when it should have been %u", where, lock->read_no_write_count,count); } if (!lock->write.data) { if (!allow_no_locks && !lock->read.data && (lock->write_wait.data || lock->read_wait.data)) { found_errors++; my_message_stderr(0, "at '%s': No locks in use but locks " "are in wait queue", where); } if (!lock->write_wait.data) { if (!allow_no_locks && lock->read_wait.data) { found_errors++; my_message_stderr(0, "at '%s': No write locks and " "waiting read locks", where); } } else { if (!allow_no_locks && (((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT || lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) && !lock->read_no_write_count))) { found_errors++; my_message_stderr(0, "at '%s': Write lock %d waiting " "while no exclusive read locks", where, (int) lock->write_wait.data->type); } } } else { /* Have write lock */ if (lock->write_wait.data) { if (!allow_no_locks && lock->write.data->type == TL_WRITE_ALLOW_WRITE && lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) { found_errors++; my_message_stderr(0, "at '%s': Found WRITE_ALLOW_WRITE " "lock waiting for WRITE_ALLOW_WRITE lock", where); } } if (lock->read.data) { if (!thr_lock_owner_equal(lock->write.data->owner, lock->read.data->owner) && ((lock->write.data->type > TL_WRITE_CONCURRENT_INSERT && lock->write.data->type != TL_WRITE_ONLY) || ((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT || lock->write.data->type == TL_WRITE_ALLOW_WRITE) && lock->read_no_write_count))) { found_errors++; my_message_stderr(0, "at '%s': Found lock of type %d " "that is write and read locked", where, lock->write.data->type); DBUG_PRINT("warning",("At '%s': Found lock of type %d that is write and read locked\n", where, lock->write.data->type)); } } if (lock->read_wait.data) { if (!allow_no_locks && lock->write.data->type <= TL_WRITE_CONCURRENT_INSERT && lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY) { found_errors++; my_message_stderr(0, "at '%s': Found read lock of " "type %d waiting for write lock of type %d", where, (int) lock->read_wait.data->type, (int) lock->write.data->type); } } } } if (found_errors != old_found_errors) { DBUG_PRINT("error",("Found wrong lock")); } } DBUG_VOID_RETURN; }
void my_end(int infoflag) { /* this code is suboptimal to workaround a bug in Sun CC: Sun C++ 5.6 2004/06/02 for x86, and should not be optimized until this compiler is not in use anymore */ FILE *info_file= DBUG_FILE; my_bool print_info= (info_file != stderr); if (!my_init_done) return; /* We do not use DBUG_ENTER here, as after cleanup DBUG is no longer operational, so we cannot use DBUG_RETURN. */ DBUG_PRINT("info",("Shutting down: infoflag: %d print_info: %d", infoflag, print_info)); if (!info_file) { info_file= stderr; print_info= 0; } if ((infoflag & MY_CHECK_ERROR) || print_info) { /* Test if some file is left open */ if (my_file_opened | my_stream_opened) { char ebuff[512]; my_snprintf(ebuff, sizeof(ebuff), EE(EE_OPEN_WARNING), my_file_opened, my_stream_opened); my_message_stderr(EE_OPEN_WARNING, ebuff, ME_BELL); DBUG_PRINT("error", ("%s", ebuff)); my_print_open_files(); } } free_charsets(); my_error_unregister_all(); my_once_free(); if ((infoflag & MY_GIVE_INFO) || print_info) { #ifdef HAVE_GETRUSAGE struct rusage rus; #ifdef HAVE_purify /* Purify assumes that rus is uninitialized after getrusage call */ bzero((char*) &rus, sizeof(rus)); #endif if (!getrusage(RUSAGE_SELF, &rus)) fprintf(info_file,"\n\ User time %.2f, System time %.2f\n\ Maximum resident set size %ld, Integral resident set size %ld\n\ Non-physical pagefaults %ld, Physical pagefaults %ld, Swaps %ld\n\ Blocks in %ld out %ld, Messages in %ld out %ld, Signals %ld\n\ Voluntary context switches %ld, Involuntary context switches %ld\n", (rus.ru_utime.tv_sec * SCALE_SEC + rus.ru_utime.tv_usec / SCALE_USEC) / 100.0, (rus.ru_stime.tv_sec * SCALE_SEC + rus.ru_stime.tv_usec / SCALE_USEC) / 100.0, rus.ru_maxrss, rus.ru_idrss, rus.ru_minflt, rus.ru_majflt, rus.ru_nswap, rus.ru_inblock, rus.ru_oublock, rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #endif #if defined(__WIN__) && defined(_MSC_VER) _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR ); _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); _CrtCheckMemory(); _CrtDumpMemoryLeaks(); #endif } if (!(infoflag & MY_DONT_FREE_DBUG)) { DBUG_END(); /* Must be done before my_thread_end */ } my_thread_end(); my_thread_global_end(); #if defined(SAFE_MUTEX) /* Check on destroying of mutexes. A few may be left that will get cleaned up by C++ destructors */ safe_mutex_end((infoflag & (MY_GIVE_INFO | MY_CHECK_ERROR)) ? stderr : (FILE *) 0); #endif /* defined(SAFE_MUTEX) */ #ifdef __WIN__ if (have_tcpip) WSACleanup(); #endif /* __WIN__ */ my_init_done=0; } /* my_end */