diff options
Diffstat (limited to 'innobase')
28 files changed, 435 insertions, 128 deletions
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 5db737561aa..a798f28b4ab 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -17,6 +17,7 @@ Created 2/17/1996 Heikki Tuuri #include "btr0cur.h" #include "btr0pcur.h" #include "btr0btr.h" +#include "ha0ha.h" ulint btr_search_n_succ = 0; ulint btr_search_n_hash_fail = 0; diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index a447f9692a7..ee8e8b91f8d 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1844,8 +1844,8 @@ buf_print_io( buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); current_time = time(NULL); - time_elapsed = difftime(current_time, buf_pool->last_printout_time); - + time_elapsed = 0.001 + difftime(current_time, + buf_pool->last_printout_time); buf_pool->last_printout_time = current_time; buf += sprintf(buf, "Pages read %lu, created %lu, written %lu\n", @@ -1878,6 +1878,20 @@ buf_print_io( mutex_exit(&(buf_pool->mutex)); } +/************************************************************************** +Refreshes the statistics used to print per-second averages. */ + +void +buf_refresh_io_stats(void) +/*======================*/ +{ + buf_pool->last_printout_time = time(NULL); + buf_pool->n_page_gets_old = buf_pool->n_page_gets; + buf_pool->n_pages_read_old = buf_pool->n_pages_read; + buf_pool->n_pages_created_old = buf_pool->n_pages_created; + buf_pool->n_pages_written_old = buf_pool->n_pages_written; +} + /************************************************************************* Checks that all file pages in the buffer are in a replaceable state. */ diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index ffdc58f2224..bd69dff740c 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -27,6 +27,7 @@ Created 11/5/1995 Heikki Tuuri #include "buf0rea.h" #include "btr0sea.h" #include "os0file.h" +#include "log0recv.h" /* The number of blocks from the LRU_old pointer onward, including the block pointed to, must be 3/8 of the whole LRU list length, except that the @@ -204,7 +205,7 @@ buf_LRU_get_free_block(void) loop: mutex_enter(&(buf_pool->mutex)); - if (UT_LIST_GET_LEN(buf_pool->free) + if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) { ut_print_timestamp(stderr); @@ -216,7 +217,7 @@ loop: ut_a(0); - } else if (UT_LIST_GET_LEN(buf_pool->free) + } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) { /* Over 80 % of the buffer pool is occupied by lock heaps @@ -232,7 +233,7 @@ loop: srv_print_innodb_monitor = TRUE; - } else if (UT_LIST_GET_LEN(buf_pool->free) + } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) { /* Switch off the InnoDB Monitor; this is a simple way diff --git a/innobase/configure.in b/innobase/configure.in index e98dc3d0f0d..48787b680b2 100644 --- a/innobase/configure.in +++ b/innobase/configure.in @@ -85,6 +85,8 @@ else fi case "$target_os" in + hpux10*) + CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";; hp*) CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";; irix*) diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index b80ed96f54c..591c0ec54ab 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -463,6 +463,12 @@ buf_print_io( /*=========*/ char* buf, /* in/out: buffer where to print */ char* buf_end);/* in: buffer end */ +/************************************************************************** +Refreshes the statistics used to print per-second averages. */ + +void +buf_refresh_io_stats(void); +/*======================*/ /************************************************************************* Checks that all file pages in the buffer are in a replaceable state. */ diff --git a/innobase/include/ha0ha.h b/innobase/include/ha0ha.h index 945b1198a41..0beac928b7e 100644 --- a/innobase/include/ha0ha.h +++ b/innobase/include/ha0ha.h @@ -131,6 +131,14 @@ ha_print_info( char* buf_end,/* in: buffer end */ hash_table_t* table); /* in: hash table */ +/* The hash table external chain node */ + +typedef struct ha_node_struct ha_node_t; +struct ha_node_struct { + ha_node_t* next; /* next chain node or NULL if none */ + void* data; /* pointer to the data */ + ulint fold; /* fold value for the data */ +}; #ifndef UNIV_NONINL #include "ha0ha.ic" diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic index 7b4c624c653..1aad7d5a36f 100644 --- a/innobase/include/ha0ha.ic +++ b/innobase/include/ha0ha.ic @@ -9,16 +9,6 @@ Created 8/18/1994 Heikki Tuuri #include "ut0rnd.h" #include "mem0mem.h" -/* The hash table external chain node */ - -typedef struct ha_node_struct ha_node_t; - -struct ha_node_struct { - ha_node_t* next; /* next chain node or NULL if none */ - void* data; /* pointer to the data */ - ulint fold; /* fold value for the data */ -}; - /*************************************************************** Deletes a hash node. */ diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h index 4358577c59c..f200371de9d 100644 --- a/innobase/include/log0log.h +++ b/innobase/include/log0log.h @@ -512,6 +512,12 @@ log_print( /*======*/ char* buf, /* in/out: buffer where to print */ char* buf_end);/* in: buffer end */ +/************************************************************************** +Refreshes the statistics used to print per-second averages. */ + +void +log_refresh_stats(void); +/*===================*/ extern log_t* log_sys; diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index b7911c5014a..d65c7fd47e3 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -408,6 +408,12 @@ os_aio_print( char* buf, /* in/out: buffer where to print */ char* buf_end);/* in: buffer end */ /************************************************************************** +Refreshes the statistics used to print per-second averages. */ + +void +os_aio_refresh_stats(void); +/*======================*/ +/************************************************************************** Checks that all slots in the system have been freed, that is, there are no pending io operations. */ diff --git a/innobase/include/os0sync.ic b/innobase/include/os0sync.ic index 6bff75d8ec6..10b85c435e3 100644 --- a/innobase/include/os0sync.ic +++ b/innobase/include/os0sync.ic @@ -27,7 +27,21 @@ os_fast_mutex_trylock( return(0); #else +#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) + /* Since the hot backup version is standalone, MySQL does not redefine + pthread_mutex_trylock for HP-UX-10.20, and consequently we must invert + the return value here */ + + return((ulint) (1 - pthread_mutex_trylock(fast_mutex))); +#else + /* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock + so that it returns 0 on success. In the operating system + libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and + returns 1 on success (but MySQL remaps that to 0), while Linux, + FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */ + return((ulint) pthread_mutex_trylock(fast_mutex)); #endif +#endif } diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h index 0d6fa5a8f37..636cfd79e50 100644 --- a/innobase/include/os0thread.h +++ b/innobase/include/os0thread.h @@ -28,12 +28,30 @@ typedef void* os_thread_t; #else typedef pthread_t os_thread_t; #endif -typedef unsigned long int os_thread_id_t; + +#define os_thread_id_t os_thread_t /* Define a function pointer type to use in a typecast */ typedef void* (*os_posix_f_t) (void*); +/******************************************************************* +Compares two threads or thread ids for equality */ + +ibool +os_thread_eq( +/*=========*/ + /* out: TRUE if equal */ + os_thread_t a, /* in: OS thread or thread id */ + os_thread_t b); /* in: OS thread or thread id */ +/******************************************************************** +Converts an OS thread or thread id to a ulint. It is NOT guaranteed that +the ulint is unique for the thread though! */ +ulint +os_thread_pf( +/*=========*/ + /* out: unsigned long int */ + os_thread_t a); /* in: thread or thread id */ /******************************************************************** Creates a new thread of execution. The execution starts from the function given. The start function takes a void* parameter @@ -73,14 +91,6 @@ os_thread_t os_thread_get_curr(void); /*====================*/ /********************************************************************* -Converts a thread id to a ulint. */ - -ulint -os_thread_conv_id_to_ulint( -/*=======================*/ - /* out: converted to ulint */ - os_thread_id_t id); /* in: thread id */ -/********************************************************************* Waits for a thread to terminate. */ void diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h index 01ac063e1c9..646d2c1bb06 100644 --- a/innobase/include/srv0start.h +++ b/innobase/include/srv0start.h @@ -85,7 +85,7 @@ extern ibool srv_is_being_shut_down; /* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE */ -extern ulint srv_shutdown_state; +extern ulint srv_shutdown_state; #define SRV_SHUTDOWN_CLEANUP 1 #define SRV_SHUTDOWN_LAST_PHASE 2 diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic index af5c4576da6..7015ff34b99 100644 --- a/innobase/include/sync0rw.ic +++ b/innobase/include/sync0rw.ic @@ -311,7 +311,8 @@ rw_lock_x_lock_func_nowait( && ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) || ((rw_lock_get_writer(lock) == RW_LOCK_EX) && (lock->pass == 0) - && (lock->writer_thread == os_thread_get_curr_id())))) { + && os_thread_eq(lock->writer_thread, + os_thread_get_curr_id())))) { rw_lock_set_writer(lock, RW_LOCK_EX); lock->writer_thread = os_thread_get_curr_id(); diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic index 9014eb5fb54..c11cc0d196e 100644 --- a/innobase/include/sync0sync.ic +++ b/innobase/include/sync0sync.ic @@ -104,6 +104,10 @@ mutex_test_and_set( ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex)); if (ret == 0) { + /* We check that os_fast_mutex_trylock does not leak + and allow race conditions */ + ut_a(mutex->lock_word == 0); + mutex->lock_word = 1; } diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 15a6115c37e..f5d083766bc 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -80,8 +80,8 @@ memory is read outside the allocated blocks. */ /* #define UNIV_DEBUG -#define UNIV_MEM_DEBUG #define UNIV_SYNC_DEBUG +#define UNIV_MEM_DEBUG #define UNIV_IBUF_DEBUG #define UNIV_SEARCH_DEBUG diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h index fc5d493ca5e..3407483696c 100644 --- a/innobase/include/ut0dbg.h +++ b/innobase/include/ut0dbg.h @@ -26,9 +26,11 @@ extern ulint* ut_dbg_null_ptr; ulint dbg_i;\ \ if (!((ulint)(EXPR) + ut_dbg_zero)) {\ + ut_print_timestamp(stderr);\ fprintf(stderr,\ - "InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\ - os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\ + " InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\ + os_thread_pf(os_thread_get_curr_id()), IB__FILE__,\ + (ulint)__LINE__);\ fprintf(stderr,\ "InnoDB: We intentionally generate a memory trap.\n");\ fprintf(stderr,\ @@ -42,16 +44,17 @@ extern ulint* ut_dbg_null_ptr; if (ut_dbg_stop_threads) {\ fprintf(stderr,\ "InnoDB: Thread %lu stopped in file %s line %lu\n",\ - os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\ + os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\ os_thread_sleep(1000000000);\ }\ } #define ut_error {\ ulint dbg_i;\ + ut_print_timestamp(stderr);\ fprintf(stderr,\ - "InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\ - os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\ + " InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\ + os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\ fprintf(stderr,\ "InnoDB: We intentionally generate a memory trap.\n");\ fprintf(stderr,\ diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index ea035dbdeb0..2f5ade656d9 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -301,6 +301,11 @@ struct lock_struct{ } un_member; }; +/* We store info on the latest deadlock error to this buffer. InnoDB +Monitor will then fetch it and print */ +ibool lock_deadlock_found = FALSE; +char* lock_latest_err_buf; /* We allocate 5000 bytes for this */ + /************************************************************************ Checks if a lock request results in a deadlock. */ static @@ -575,6 +580,8 @@ lock_sys_create( lock_sys->rec_hash = hash_create(n_cells); /* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */ + + lock_latest_err_buf = mem_alloc(5000); } /************************************************************************* @@ -2698,6 +2705,7 @@ lock_deadlock_occurs( trx_t* mark_trx; ibool ret; ulint cost = 0; + char* err_buf; ut_ad(trx && lock); ut_ad(mutex_own(&kernel_mutex)); @@ -2723,6 +2731,29 @@ lock_deadlock_occurs( index = lock->index; table = index->table; } + + lock_deadlock_found = TRUE; + + err_buf = lock_latest_err_buf + strlen(lock_latest_err_buf); + + err_buf += sprintf(err_buf, + "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n"); + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + if (lock_get_type(lock) == LOCK_REC) { + lock_rec_print(err_buf, lock); + err_buf += strlen(err_buf); + } else { + lock_table_print(err_buf, lock); + err_buf += strlen(err_buf); + } + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + err_buf += sprintf(err_buf, + "*** WE ROLL BACK TRANSACTION (2)\n"); + /* sess_raise_error_low(trx, DB_DEADLOCK, lock->type_mode, table, index, NULL, NULL, NULL); @@ -2750,6 +2781,7 @@ lock_deadlock_recursive( lock_t* lock; ulint bit_no; trx_t* lock_trx; + char* err_buf; ut_a(trx && start && wait_lock); ut_ad(mutex_own(&kernel_mutex)); @@ -2801,6 +2833,53 @@ lock_deadlock_recursive( lock_trx = lock->trx; if (lock_trx == start) { + err_buf = lock_latest_err_buf; + + ut_sprintf_timestamp(err_buf); + err_buf += strlen(err_buf); + + err_buf += sprintf(err_buf, + " LATEST DETECTED DEADLOCK:\n" + "*** (1) TRANSACTION:\n"); + + trx_print(err_buf, wait_lock->trx); + err_buf += strlen(err_buf); + + err_buf += sprintf(err_buf, + "*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n"); + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + if (lock_get_type(wait_lock) == LOCK_REC) { + lock_rec_print(err_buf, wait_lock); + err_buf += strlen(err_buf); + } else { + lock_table_print(err_buf, wait_lock); + err_buf += strlen(err_buf); + } + + ut_a(err_buf <= lock_latest_err_buf + 4000); + err_buf += sprintf(err_buf, + "*** (2) TRANSACTION:\n"); + + trx_print(err_buf, lock->trx); + err_buf += strlen(err_buf); + + err_buf += sprintf(err_buf, + "*** (2) HOLDS THE LOCK(S):\n"); + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + if (lock_get_type(lock) == LOCK_REC) { + lock_rec_print(err_buf, lock); + err_buf += strlen(err_buf); + } else { + lock_table_print(err_buf, lock); + err_buf += strlen(err_buf); + } + + ut_a(err_buf <= lock_latest_err_buf + 4000); + if (lock_print_waits) { printf("Deadlock detected\n"); } @@ -3433,6 +3512,9 @@ lock_rec_print( buf += sprintf(buf, "Suppressing further record lock prints for this page\n"); + + mtr_commit(&mtr); + return; } @@ -3505,10 +3587,6 @@ lock_print_info( return; } - buf += sprintf(buf, "Number of sessions %lu\n", - UT_LIST_GET_LEN(trx_sys->mysql_trx_list) - + UT_LIST_GET_LEN(trx_sys->trx_list)); - buf += sprintf(buf, "Trx id counter %lu %lu\n", ut_dulint_get_high(trx_sys->max_trx_id), ut_dulint_get_low(trx_sys->max_trx_id)); @@ -3525,6 +3603,22 @@ lock_print_info( buf += sprintf(buf, "Total number of lock structs in row lock hash table %lu\n", lock_get_n_rec_locks()); + if (lock_deadlock_found) { + + if ((ulint)(buf_end - buf) + < 100 + strlen(lock_latest_err_buf)) { + + return; + } + + buf += sprintf(buf, "%s", lock_latest_err_buf); + } + + if (buf_end - buf < 600) { + return; + } + + buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n"); /* First print info on non-active transactions */ diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index 644d53ac273..cb85e9d3ba6 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -3096,8 +3096,8 @@ log_print( current_time = time(NULL); - time_elapsed = difftime(current_time, log_sys->last_printout_time); - + time_elapsed = 0.001 + difftime(current_time, + log_sys->last_printout_time); buf += sprintf(buf, "%lu pending log writes, %lu pending chkp writes\n" "%lu log i/o's done, %.2f log i/o's/second\n", @@ -3111,3 +3111,14 @@ log_print( mutex_exit(&(log_sys->mutex)); } + +/************************************************************************** +Refreshes the statistics used to print per-second averages. */ + +void +log_refresh_stats(void) +/*===================*/ +{ + log_sys->n_log_ios_old = log_sys->n_log_ios; + log_sys->last_printout_time = time(NULL); +} diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c index 3681c8ef779..61cf1e50ce9 100644 --- a/innobase/mem/mem0pool.c +++ b/innobase/mem/mem0pool.c @@ -251,6 +251,7 @@ mem_pool_fill_free_list( mem_area_t* area; mem_area_t* area2; ibool ret; + char err_buf[500]; ut_ad(mutex_own(&(pool->mutex))); @@ -279,15 +280,34 @@ mem_pool_fill_free_list( area = UT_LIST_GET_FIRST(pool->free_list[i + 1]); if (area == NULL) { + if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) { + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Error: mem pool free list %lu length is %lu\n" +"InnoDB: though the list is empty!\n", + i + 1, UT_LIST_GET_LEN(pool->free_list[i + 1])); + } + ret = mem_pool_fill_free_list(i + 1, pool); if (ret == FALSE) { + return(FALSE); } area = UT_LIST_GET_FIRST(pool->free_list[i + 1]); } - + + if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) { + ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100); + fprintf(stderr, +"InnoDB: Error: Removing element from mem pool free list %lu\n" +"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n", + i + 1, err_buf); + ut_a(0); + } + UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area); area2 = (mem_area_t*)(((byte*)area) + ut_2_exp(i)); @@ -320,6 +340,7 @@ mem_area_alloc( mem_area_t* area; ulint n; ibool ret; + char err_buf[500]; n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE)); @@ -342,7 +363,24 @@ mem_area_alloc( area = UT_LIST_GET_FIRST(pool->free_list[n]); } - ut_a(mem_area_get_free(area)); + if (!mem_area_get_free(area)) { + ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100); + fprintf(stderr, +"InnoDB: Error: Removing element from mem pool free list %lu though the\n" +"InnoDB: element is not marked free! Dump of 100 bytes around element:\n%s\n", + n, err_buf); + ut_a(0); + } + + if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) { + ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100); + fprintf(stderr, +"InnoDB: Error: Removing element from mem pool free list %lu\n" +"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n", + n, err_buf); + ut_a(0); + } + ut_ad(mem_area_get_size(area) == ut_2_exp(n)); mem_area_set_free(area, FALSE); @@ -413,6 +451,7 @@ mem_area_free( void* new_ptr; ulint size; ulint n; + char err_buf[500]; if (mem_out_of_mem_err_msg_count > 0) { /* It may be that the area was really allocated from the @@ -429,10 +468,18 @@ mem_area_free( area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE); + if (mem_area_get_free(area)) { + ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100); + fprintf(stderr, +"InnoDB: Error: Freeing element to mem pool free list though the\n" +"InnoDB: element is marked free! Dump of 100 bytes around element:\n%s\n", + err_buf); + ut_a(0); + } + size = mem_area_get_size(area); ut_ad(size != 0); - ut_a(!mem_area_get_free(area)); #ifdef UNIV_LIGHT_MEM_DEBUG if (((byte*)area) + size < pool->buf + pool->size) { diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index e40de2198c1..10bb9bb66d7 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2486,7 +2486,7 @@ loop: buf += sprintf(buf, "\n"); current_time = time(NULL); - time_elapsed = difftime(current_time, os_last_printout); + time_elapsed = 0.001 + difftime(current_time, os_last_printout); buf += sprintf(buf, "Pending flushes (fsync) log: %lu; buffer pool: %lu\n", @@ -2521,6 +2521,21 @@ loop: } /************************************************************************** +Refreshes the statistics used to print per-second averages. */ + +void +os_aio_refresh_stats(void) +/*======================*/ +{ + os_n_file_reads_old = os_n_file_reads; + os_n_file_writes_old = os_n_file_writes; + os_n_fsyncs_old = os_n_fsyncs; + os_bytes_read_since_printout = 0; + + os_last_printout = time(NULL); +} + +/************************************************************************** Checks that all slots in the system have been freed, that is, there are no pending io operations. */ diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c index 44817302340..75f19f6d175 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -18,37 +18,63 @@ Created 9/8/1995 Heikki Tuuri #include "srv0srv.h" -/********************************************************************* -Returns the thread identifier of current thread. */ - -os_thread_id_t -os_thread_get_curr_id(void) -/*=======================*/ +/******************************************************************* +Compares two threads or thread ids for equality */ + +ibool +os_thread_eq( +/*=========*/ + /* out: TRUE if equal */ + os_thread_t a, /* in: OS thread or thread id */ + os_thread_t b) /* in: OS thread or thread id */ { #ifdef __WIN__ - return(GetCurrentThreadId()); + if (a == b) { + return(TRUE); + } + + return(FALSE); #else - pthread_t pthr; + if (pthread_equal(a, b)) { + return(TRUE); + } - pthr = pthread_self(); + return(FALSE); +#endif +} -#ifdef HPUX - /* TODO: in the future we have to change os_thread_id - to pthread_t! */ +/******************************************************************** +Converts an OS thread or thread id to a ulint. It is NOT guaranteed that +the ulint is unique for the thread though! */ - /* In HP-UX a pthread_t seems to be a struct of three fields: - field1, field2, field3, and the first probably determines (?) - the thread identity. */ +ulint +os_thread_pf( +/*=========*/ + os_thread_t a) +{ +#ifdef UNIV_HPUX + /* In HP-UX a pthread_t is a struct of 3 fields: field1, field2, + field3. We do not know if field1 determines the thread uniquely. */ - return((os_thread_id_t)(pthr.field1)); + return((ulint)(a.field1)); #else - /* TODO: define os_thread_id_t in Unix as the same as pthread_t - and compare them with appropriate Posix pthread functions! - The following typecast will not work if pthread_t is not - an integer or a pointer to a unique object for the thread! */ - - return((os_thread_id_t)pthr); + return((ulint)a); #endif +} + +/********************************************************************* +Returns the thread identifier of current thread. Currently the thread +identifier is the thread handle itself. Note that in HP-UX pthread_t is +a struct of 3 fields. */ + +os_thread_id_t +os_thread_get_curr_id(void) +/*=======================*/ +{ +#ifdef __WIN__ + return(GetCurrentThread()); +#else + return(pthread_self()); #endif } @@ -81,7 +107,6 @@ os_thread_create( arg, 0, /* thread runs immediately */ thread_id); - ut_a(thread); if (srv_set_thread_priorities) { @@ -118,7 +143,7 @@ Returns handle to the current thread. */ os_thread_t os_thread_get_curr(void) -/*=======================*/ +/*====================*/ { #ifdef __WIN__ return(GetCurrentThread()); @@ -126,18 +151,6 @@ os_thread_get_curr(void) return(pthread_self()); #endif } - -/********************************************************************* -Converts a thread id to a ulint. */ - -ulint -os_thread_conv_id_to_ulint( -/*=======================*/ - /* out: converted to ulint */ - os_thread_id_t id) /* in: thread id */ -{ - return((ulint)id); -} /********************************************************************* Advises the os to give up remainder of the thread's time slice. */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 3af2d96d921..2ce97c34e06 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -2018,7 +2018,7 @@ srv_table_reserve_slot_for_mysql(void) fprintf(stderr, "Slot %lu: thread id %lu, type %lu, in use %lu, susp %lu, time %lu\n", - i, (ulint)(slot->id), + i, os_thread_pf(slot->id), slot->type, slot->in_use, slot->suspended, (ulint)difftime(ut_time(), slot->suspend_time)); @@ -2163,6 +2163,34 @@ srv_release_mysql_thread_if_suspended( } /********************************************************************** +Refreshes the values used to calculate per-second averages. */ +static +void +srv_refresh_innodb_monitor_stats(void) +/*==================================*/ +{ + mutex_enter(&srv_innodb_monitor_mutex); + + srv_last_monitor_time = time(NULL); + + os_aio_refresh_stats(); + + btr_cur_n_sea_old = btr_cur_n_sea; + btr_cur_n_non_sea_old = btr_cur_n_non_sea; + + log_refresh_stats(); + + buf_refresh_io_stats(); + + srv_n_rows_inserted_old = srv_n_rows_inserted; + srv_n_rows_updated_old = srv_n_rows_updated; + srv_n_rows_deleted_old = srv_n_rows_deleted; + srv_n_rows_read_old = srv_n_rows_read; + + mutex_exit(&srv_innodb_monitor_mutex); +} + +/********************************************************************** Sprintfs to a buffer the output of the InnoDB Monitor. */ void @@ -2199,7 +2227,7 @@ srv_sprintf_innodb_monitor( "=====================================\n"); buf += sprintf(buf, -"Per second values calculated from the last %lu seconds\n", +"Per second averages calculated from the last %lu seconds\n", (ulint)time_elapsed); buf += sprintf(buf, "----------\n" @@ -2236,8 +2264,8 @@ srv_sprintf_innodb_monitor( / time_elapsed, (btr_cur_n_non_sea - btr_cur_n_non_sea_old) / time_elapsed); - btr_cur_n_sea_old = btr_cur_n_sea; - btr_cur_n_non_sea_old = btr_cur_n_non_sea; + btr_cur_n_sea_old = btr_cur_n_sea; + btr_cur_n_non_sea_old = btr_cur_n_non_sea; buf += sprintf(buf,"---\n" "LOG\n" @@ -2279,10 +2307,10 @@ srv_sprintf_innodb_monitor( (srv_n_rows_read - srv_n_rows_read_old) / time_elapsed); - srv_n_rows_inserted_old = srv_n_rows_inserted; - srv_n_rows_updated_old = srv_n_rows_updated; - srv_n_rows_deleted_old = srv_n_rows_deleted; - srv_n_rows_read_old = srv_n_rows_read; + srv_n_rows_inserted_old = srv_n_rows_inserted; + srv_n_rows_updated_old = srv_n_rows_updated; + srv_n_rows_deleted_old = srv_n_rows_deleted; + srv_n_rows_read_old = srv_n_rows_read; buf += sprintf(buf, "----------------------------\n" "END OF INNODB MONITOR OUTPUT\n" @@ -2325,7 +2353,7 @@ loop: /* When someone is waiting for a lock, we wake up every second and check if a timeout has passed for a lock wait */ - os_thread_sleep(1000000); + os_thread_sleep(1000000); /* In case mutex_exit is not a memory barrier, it is theoretically possible some threads are left waiting though @@ -2342,9 +2370,9 @@ loop: if (srv_print_innodb_monitor) { - buf = mem_alloc(100000); + buf = mem_alloc(100000); - srv_sprintf_innodb_monitor(buf, 100000); + srv_sprintf_innodb_monitor(buf, 100000); printf("%s", buf); @@ -2485,6 +2513,13 @@ loop: os_thread_sleep(2000000); + if (difftime(time(NULL), srv_last_monitor_time) > 60) { + /* We referesh InnoDB Monitor values so that averages are + printed from at most 60 last seconds */ + + srv_refresh_innodb_monitor_stats(); + } + /* mem_print_new_info(); if (cnt % 10 == 0) { diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index b35bca1ea8e..ea0ed7c961e 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -74,6 +74,12 @@ ulint ios; ulint n[SRV_MAX_N_IO_THREADS + 5]; os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5]; +/* We use this mutex to test the return value of pthread_mutex_trylock + on successful locking. HP-UX does NOT return 0, though Linux et al do. */ +os_fast_mutex_t srv_os_test_mutex; + +ibool srv_os_test_mutex_is_locked = FALSE; + #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD #define SRV_MAX_N_PENDING_SYNC_IOS 100 @@ -1353,6 +1359,22 @@ innobase_start_or_create_for_mysql(void) tablespace_size_in_header, sum_of_data_file_sizes); } + /* Check that os_fast_mutexes work as exptected */ + os_fast_mutex_init(&srv_os_test_mutex); + + if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) { + fprintf(stderr, +"InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n" + "InnoDB: success! Cannot continue.\n"); + exit(1); + } + + os_fast_mutex_unlock(&srv_os_test_mutex); + + os_fast_mutex_lock(&srv_os_test_mutex); + + os_fast_mutex_unlock(&srv_os_test_mutex); + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Started\n"); diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index 81b5b7de195..ad3ac84b6eb 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -454,7 +454,7 @@ sync_array_cell_print( buf += sprintf(buf, "--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n", - (ulint)cell->thread, cell->file, cell->line, + os_thread_pf(cell->thread), cell->file, cell->line, difftime(time(NULL), cell->reservation_time)); if (type == SYNC_MUTEX) { @@ -486,7 +486,7 @@ sync_array_cell_print( if (rwlock->writer != RW_LOCK_NOT_LOCKED) { buf += sprintf(buf, "a writer (thread id %lu) has reserved it in mode", - (ulint)rwlock->writer_thread); + os_thread_pf(rwlock->writer_thread)); if (rwlock->writer == RW_LOCK_EX) { buf += sprintf(buf, " exclusive\n"); } else { @@ -535,8 +535,8 @@ sync_array_find_thread( cell = sync_array_get_nth_cell(arr, i); - if ((cell->wait_object != NULL) - && (cell->thread == thread)) { + if (cell->wait_object != NULL + && os_thread_eq(cell->thread, thread)) { return(cell); /* Found */ } @@ -651,9 +651,9 @@ sync_array_detect_deadlock( sync_array_cell_print(buf, cell); printf( "Mutex %lx owned by thread %lu file %s line %lu\n%s", - (ulint)mutex, mutex->thread_id, - mutex->file_name, mutex->line, - buf); + (ulint)mutex, os_thread_pf(mutex->thread_id), + mutex->file_name, mutex->line, buf); + return(TRUE); } } @@ -671,9 +671,9 @@ sync_array_detect_deadlock( thread = debug->thread_id; if (((debug->lock_type == RW_LOCK_EX) - && (thread != cell->thread)) + && !os_thread_eq(thread, cell->thread)) || ((debug->lock_type == RW_LOCK_WAIT_EX) - && (thread != cell->thread)) + && !os_thread_eq(thread, cell->thread)) || (debug->lock_type == RW_LOCK_SHARED)) { /* The (wait) x-lock request can block infinitely @@ -771,7 +771,7 @@ sync_arr_cell_can_wake_up( if (rw_lock_get_reader_count(lock) == 0 && rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX - && lock->writer_thread == cell->thread) { + && os_thread_eq(lock->writer_thread, cell->thread)) { return(TRUE); } @@ -927,7 +927,7 @@ sync_array_print_long_waits(void) && difftime(time(NULL), cell->reservation_time) > 420) { fprintf(stderr, -"InnoDB: Error: semaphore wait has lasted > 420 seconds\n" +"InnoDB: Error: semaphore wait has lasted > 600 seconds\n" "InnoDB: We intentionally crash the server, because it appears to be hung.\n" ); @@ -1011,3 +1011,4 @@ sync_array_print_info( sync_array_exit(arr); } + diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c index 1ef2920618f..93db9b9d507 100644 --- a/innobase/sync/sync0rw.c +++ b/innobase/sync/sync0rw.c @@ -223,7 +223,7 @@ lock_loop: if (srv_print_latch_waits) { printf( "Thread %lu spin wait rw-s-lock at %lx cfile %s cline %lu rnds %lu\n", - os_thread_get_curr_id(), (ulint)lock, + os_thread_pf(os_thread_get_curr_id()), (ulint)lock, lock->cfile_name, lock->cline, i); } @@ -253,7 +253,7 @@ lock_loop: if (srv_print_latch_waits) { printf( "Thread %lu OS wait rw-s-lock at %lx cfile %s cline %lu\n", - os_thread_get_curr_id(), (ulint)lock, + os_thread_pf(os_thread_get_curr_id()), (ulint)lock, lock->cfile_name, lock->cline); } @@ -343,7 +343,8 @@ rw_lock_x_lock_low( } } else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX) - && (lock->writer_thread == os_thread_get_curr_id())) { + && os_thread_eq(lock->writer_thread, + os_thread_get_curr_id())) { if (rw_lock_get_reader_count(lock) == 0) { @@ -368,7 +369,8 @@ rw_lock_x_lock_low( return(RW_LOCK_WAIT_EX); } else if ((rw_lock_get_writer(lock) == RW_LOCK_EX) - && (lock->writer_thread == os_thread_get_curr_id()) + && os_thread_eq(lock->writer_thread, + os_thread_get_curr_id()) && (lock->pass == 0) && (pass == 0)) { @@ -469,7 +471,7 @@ lock_loop: if (srv_print_latch_waits) { printf( "Thread %lu spin wait rw-x-lock at %lx cfile %s cline %lu rnds %lu\n", - os_thread_get_curr_id(), (ulint)lock, + os_thread_pf(os_thread_get_curr_id()), (ulint)lock, lock->cfile_name, lock->cline, i); } @@ -502,8 +504,8 @@ lock_loop: if (srv_print_latch_waits) { printf( "Thread %lu OS wait for rw-x-lock at %lx cfile %s cline %lu\n", - os_thread_get_curr_id(), (ulint)lock, lock->cfile_name, - lock->cline); + os_thread_pf(os_thread_get_curr_id()), (ulint)lock, + lock->cfile_name, lock->cline); } rw_x_system_call_count++; @@ -621,7 +623,8 @@ rw_lock_remove_debug_info( while (info != NULL) { if ((pass == info->pass) && ((pass != 0) - || (info->thread_id == os_thread_get_curr_id())) + || os_thread_eq(info->thread_id, + os_thread_get_curr_id())) && (info->lock_type == lock_type)) { /* Found! */ @@ -676,7 +679,7 @@ rw_lock_own( while (info != NULL) { - if ((info->thread_id == os_thread_get_curr_id()) + if (os_thread_eq(info->thread_id, os_thread_get_curr_id()) && (info->pass == 0) && (info->lock_type == lock_type)) { @@ -834,7 +837,7 @@ rw_lock_debug_print( rwt = info->lock_type; printf("Locked: thread %ld file %s line %ld ", - info->thread_id, info->file_name, info->line); + os_thread_pf(info->thread_id), info->file_name, info->line); if (rwt == RW_LOCK_SHARED) { printf("S-LOCK"); } else if (rwt == RW_LOCK_EX) { diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index c070e97f692..61bd8e587e6 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -230,7 +230,6 @@ mutex_create_func( mutex->magic_n = MUTEX_MAGIC_N; mutex->line = 0; mutex->file_name = "not yet reserved"; - mutex->thread_id = ULINT_UNDEFINED; mutex->level = SYNC_LEVEL_NONE; mutex->cfile_name = cfile_name; mutex->cline = cline; @@ -392,8 +391,8 @@ spin_loop: if (srv_print_latch_waits) { printf( "Thread %lu spin wait mutex at %lx cfile %s cline %lu rnds %lu\n", - os_thread_get_curr_id(), (ulint)mutex, mutex->cfile_name, - mutex->cline, i); + os_thread_pf(os_thread_get_curr_id()), (ulint)mutex, + mutex->cfile_name, mutex->cline, i); } mutex_spin_round_count += i; @@ -458,7 +457,7 @@ spin_loop: if (srv_print_latch_waits) { printf( "Thread %lu spin wait succeeds at 2: mutex at %lx\n", - os_thread_get_curr_id(), (ulint)mutex); + os_thread_pf(os_thread_get_curr_id()), (ulint)mutex); } return; @@ -476,8 +475,8 @@ spin_loop: if (srv_print_latch_waits) { printf( "Thread %lu OS wait mutex at %lx cfile %s cline %lu rnds %lu\n", - os_thread_get_curr_id(), (ulint)mutex, mutex->cfile_name, - mutex->cline, i); + os_thread_pf(os_thread_get_curr_id()), (ulint)mutex, + mutex->cfile_name, mutex->cline, i); } mutex_system_call_count++; @@ -572,7 +571,7 @@ mutex_own( return(FALSE); } - if (mutex->thread_id != os_thread_get_curr_id()) { + if (!os_thread_eq(mutex->thread_id, os_thread_get_curr_id())) { return(FALSE); } @@ -611,7 +610,8 @@ mutex_list_print_info(void) &thread_id); printf( "Locked mutex: addr %lx thread %ld file %s line %ld\n", - (ulint)mutex, thread_id, file_name, line); + (ulint)mutex, os_thread_pf(thread_id), + file_name, line); } mutex = UT_LIST_GET_NEXT(list, mutex); @@ -716,7 +716,7 @@ sync_thread_level_arrays_find_slot(void) slot = sync_thread_level_arrays_get_nth(i); - if (slot->levels && (slot->id == id)) { + if (slot->levels && os_thread_eq(slot->id, id)) { return(slot); } @@ -780,7 +780,7 @@ sync_thread_levels_g( { char* file_name; ulint line; - ulint thread_id; + os_thread_id_t thread_id; sync_level_t* slot; rw_lock_t* lock; mutex_t* mutex; @@ -810,7 +810,7 @@ sync_thread_levels_g( &file_name, &line, &thread_id); printf("InnoDB: Locked mutex: addr %lx thread %ld file %s line %ld\n", - (ulint)mutex, thread_id, + (ulint)mutex, os_thread_pf(thread_id), file_name, line); } else { printf("Not locked\n"); diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c index d3d7a58d313..fbf3e3a1dad 100644 --- a/innobase/thr/thr0loc.c +++ b/innobase/thr/thr0loc.c @@ -69,8 +69,8 @@ try_again: local = NULL; - HASH_SEARCH(hash, thr_local_hash, os_thread_conv_id_to_ulint(id), - local, local->id == id); + HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id), + local, os_thread_eq(local->id, id)); if (local == NULL) { mutex_exit(&thr_local_mutex); @@ -173,7 +173,7 @@ thr_local_create(void) mutex_enter(&thr_local_mutex); HASH_INSERT(thr_local_t, hash, thr_local_hash, - os_thread_conv_id_to_ulint(os_thread_get_curr_id()), + os_thread_pf(os_thread_get_curr_id()), local); mutex_exit(&thr_local_mutex); @@ -193,8 +193,8 @@ thr_local_free( /* Look for the local struct in the hash table */ - HASH_SEARCH(hash, thr_local_hash, os_thread_conv_id_to_ulint(id), - local, local->id == id); + HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id), + local, os_thread_eq(local->id, id)); if (local == NULL) { mutex_exit(&thr_local_mutex); @@ -202,7 +202,7 @@ thr_local_free( } HASH_DELETE(thr_local_t, hash, thr_local_hash, - os_thread_conv_id_to_ulint(id), local); + os_thread_pf(id), local); mutex_exit(&thr_local_mutex); diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 9c8bfc9f4db..48b1ecc59f2 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -1487,7 +1487,7 @@ trx_print( } buf += sprintf(buf, ", OS thread id %lu", - (ulint)trx->mysql_thread_id); + os_thread_pf(trx->mysql_thread_id)); if (ut_strlen(trx->op_info) > 0) { buf += sprintf(buf, " %s", trx->op_info); |