diff options
author | heikki@hundin.mysql.fi <> | 2002-07-08 19:34:49 +0300 |
---|---|---|
committer | heikki@hundin.mysql.fi <> | 2002-07-08 19:34:49 +0300 |
commit | 7390d81f43c5c02004039a27bff27e558639aab0 (patch) | |
tree | b4e7fbd4d1817aa205132578bc6b11e6dd0fad86 /innobase | |
parent | 3135924745a221a579f5a49aaee4b112a3a1bb4c (diff) | |
download | mariadb-git-7390d81f43c5c02004039a27bff27e558639aab0.tar.gz |
Many files:
Merge InnoDB-3.23.52b
Diffstat (limited to 'innobase')
29 files changed, 579 insertions, 248 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 88472d6dbe0..15642e6ccbc 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -2076,8 +2076,7 @@ btr_discard_page( btr_search_drop_page_hash_index(page); - if ((left_page_no == FIL_NULL) - && (btr_page_get_level(page, mtr) > 0)) { + if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) { /* We have to mark the leftmost node pointer on the right side page as the predefined minimum record */ diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index f3aebb7f96f..50f9584e86d 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -44,6 +44,8 @@ ulint btr_cur_rnd = 0; ulint btr_cur_n_non_sea = 0; ulint btr_cur_n_sea = 0; +ulint btr_cur_n_non_sea_old = 0; +ulint btr_cur_n_sea_old = 0; /* In the optimistic insert, if the insert does not fit, but this much space can be released by page reorganize, then it is reorganized */ diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 5e1c8401e28..5db737561aa 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -451,7 +451,9 @@ btr_search_info_update_slow( rw_lock_x_unlock(&btr_search_latch); } - if (build_index) { + if (build_index) { + ut_a(block->n_fields + block->n_bytes > 0); + btr_search_build_page_hash_index(block->frame, block->n_fields, block->n_bytes, @@ -676,6 +678,9 @@ btr_search_guess_on_hash( rw_lock_s_lock(&btr_search_latch); } + ut_a(btr_search_latch.writer != RW_LOCK_EX); + ut_a(btr_search_latch.reader_count > 0); + rec = ha_search_and_get_data(btr_search_sys->hash_index, fold); if (!rec) { @@ -902,7 +907,7 @@ btr_search_drop_page_hash_index( fold = rec_fold(rec, n_fields, n_bytes, tree_id); - if ((fold == prev_fold) && (prev_fold != 0)) { + if (fold == prev_fold && prev_fold != 0) { goto next_rec; } @@ -914,6 +919,7 @@ btr_search_drop_page_hash_index( n_cached++; next_rec: rec = page_rec_get_next(rec); + prev_fold = fold; } rw_lock_x_lock(&btr_search_latch); @@ -954,7 +960,7 @@ btr_search_drop_page_hash_when_freed( mtr_start(&mtr); /* We assume that if the caller has a latch on the page, - then the caller has already drooped the hash index for the page, + then the caller has already dropped the hash index for the page, and we never get here. Therefore we can acquire the s-latch to the page without fearing a deadlock. */ @@ -1177,6 +1183,8 @@ btr_search_move_or_delete_hash_entries( rw_lock_s_unlock(&btr_search_latch); + ut_a(n_fields + n_bytes > 0); + btr_search_build_page_hash_index(new_page, n_fields, n_bytes, side); ut_a(n_fields == block->curr_n_fields); @@ -1217,9 +1225,11 @@ btr_search_update_hash_on_delete( return; } + ut_a(block->curr_n_fields + block->curr_n_bytes > 0); + table = btr_search_sys->hash_index; - tree_id = ((cursor->index)->tree)->id; + tree_id = cursor->index->tree->id; fold = rec_fold(rec, block->curr_n_fields, block->curr_n_bytes, tree_id); @@ -1336,7 +1346,6 @@ btr_search_update_hash_on_insert( if (rec != page_get_infimum_rec(page)) { fold = rec_fold(rec, n_fields, n_bytes, tree_id); - } else { if (side == BTR_SEARCH_LEFT_SIDE) { @@ -1421,7 +1430,7 @@ btr_search_print_info(void) rw_lock_x_lock(&btr_search_latch); - ha_print_info(btr_search_sys->hash_index); +/* ha_print_info(btr_search_sys->hash_index); */ rw_lock_x_unlock(&btr_search_latch); } @@ -1487,11 +1496,71 @@ btr_search_validate(void) /*=====================*/ /* out: TRUE if ok */ { + buf_block_t* block; + page_t* page; + ha_node_t* node; + ulint n_page_dumps = 0; + ibool ok = TRUE; + ulint i; + char rec_str[500]; + rw_lock_x_lock(&btr_search_latch); + + for (i = 0; i < hash_get_n_cells(btr_search_sys->hash_index); i++) { + node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; + + while (node != NULL) { + block = buf_block_align(node->data); + page = buf_frame_align(node->data); + + if (!block->is_hashed + || node->fold != rec_fold((rec_t*)(node->data), + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))) { + ok = FALSE; + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Error in an adaptive hash index pointer to page %lu\n" +"ptr mem address %lu index id %lu %lu, node fold %lu, rec fold %lu\n", + buf_frame_get_page_no(page), + (ulint)(node->data), + ut_dulint_get_high(btr_page_get_index_id(page)), + ut_dulint_get_low(btr_page_get_index_id(page)), + node->fold, rec_fold((rec_t*)(node->data), + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))); + + rec_sprintf(rec_str, 450, (rec_t*)(node->data)); + + fprintf(stderr, + "InnoDB: Record %s\n" + "InnoDB: on that page.", rec_str); + + fprintf(stderr, +"Page mem address %lu, is hashed %lu, n fields %lu, n bytes %lu\n" +"side %lu\n", + (ulint)page, block->is_hashed, block->curr_n_fields, + block->curr_n_bytes, block->curr_side); + + if (n_page_dumps < 20) { + buf_page_print(page); + n_page_dumps++; + } + } + + node = node->next; + } + } - ut_a(ha_validate(btr_search_sys->hash_index)); + if (!ha_validate(btr_search_sys->hash_index)) { + + ok = FALSE; + } rw_lock_x_unlock(&btr_search_latch); - return(TRUE); + return(ok); } diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 7d001a6953d..80e89e16588 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1798,8 +1798,10 @@ buf_get_n_pending_ios(void) Prints info of the buffer i/o. */ void -buf_print_io(void) -/*==============*/ +buf_print_io( +/*=========*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end)/* in: buffer end */ { time_t current_time; double time_elapsed; @@ -1807,19 +1809,28 @@ buf_print_io(void) ut_ad(buf_pool); + if (buf_end - buf < 400) { + + return; + } + size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE; mutex_enter(&(buf_pool->mutex)); - printf("Free list length %lu \n", UT_LIST_GET_LEN(buf_pool->free)); - printf("LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU)); - printf("Flush list length %lu \n", + buf += sprintf(buf, + "Free list length %lu \n", UT_LIST_GET_LEN(buf_pool->free)); + buf += sprintf(buf, + "LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU)); + buf += sprintf(buf, + "Flush list length %lu \n", UT_LIST_GET_LEN(buf_pool->flush_list)); - printf("Buffer pool size %lu\n", size); + buf += sprintf(buf, "Buffer pool size %lu\n", size); - printf("Pending reads %lu \n", buf_pool->n_pend_reads); + buf += sprintf(buf, "Pending reads %lu \n", buf_pool->n_pend_reads); - printf("Pending writes: LRU %lu, flush list %lu, single page %lu\n", + buf += sprintf(buf, + "Pending writes: LRU %lu, flush list %lu, single page %lu\n", buf_pool->n_flush[BUF_FLUSH_LRU], buf_pool->n_flush[BUF_FLUSH_LIST], buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); @@ -1829,10 +1840,10 @@ buf_print_io(void) buf_pool->last_printout_time = current_time; - printf("Pages read %lu, created %lu, written %lu\n", + buf += sprintf(buf, "Pages read %lu, created %lu, written %lu\n", buf_pool->n_pages_read, buf_pool->n_pages_created, buf_pool->n_pages_written); - printf("%.2f reads/s, %.2f creates/s, %.2f writes/s\n", + buf += sprintf(buf, "%.2f reads/s, %.2f creates/s, %.2f writes/s\n", (buf_pool->n_pages_read - buf_pool->n_pages_read_old) / time_elapsed, (buf_pool->n_pages_created - buf_pool->n_pages_created_old) @@ -1841,13 +1852,14 @@ buf_print_io(void) / time_elapsed); if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) { - printf("Buffer pool hit rate %lu / 1000\n", + buf += sprintf(buf, "Buffer pool hit rate %lu / 1000\n", 1000 - ((1000 * (buf_pool->n_pages_read - buf_pool->n_pages_read_old)) / (buf_pool->n_page_gets - buf_pool->n_page_gets_old))); } else { - printf("No buffer pool activity since the last printout\n"); + buf += sprintf(buf, + "No buffer pool activity since the last printout\n"); } buf_pool->n_page_gets_old = buf_pool->n_page_gets; diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c index 3e4473126cf..c3ad6cdca76 100644 --- a/innobase/ha/ha0ha.c +++ b/innobase/ha/ha0ha.c @@ -194,7 +194,7 @@ ha_delete( node = ha_search_with_data(table, fold, data); - ut_ad(node); + ut_a(node); ha_delete_hash_node(table, node); } @@ -232,6 +232,16 @@ ha_remove_all_nodes_to_page( node = ha_chain_get_next(table, node); } } + + /* Check that all nodes really got deleted */ + + node = ha_chain_get_first(table, fold); + + while (node) { + ut_a(buf_frame_align(ha_node_get_data(node)) != page); + + node = ha_chain_get_next(table, node); + } } /***************************************************************** @@ -245,6 +255,7 @@ ha_validate( { hash_cell_t* cell; ha_node_t* node; + ibool ok = TRUE; ulint i; for (i = 0; i < hash_get_n_cells(table); i++) { @@ -254,13 +265,21 @@ ha_validate( node = cell->node; while (node) { - ut_a(hash_calc_hash(node->fold, table) == i); + if (hash_calc_hash(node->fold, table) != i) { + ut_print_timestamp(stderr); + fprintf(stderr, +"InnoDB: Error: hash table node fold value %lu does not\n" +"InnoDB: match with the cell number %lu.\n", + node->fold, i); + + ok = FALSE; + } node = node->next; } } - return(TRUE); + return(ok); } /***************************************************************** @@ -269,16 +288,22 @@ Prints info of a hash table. */ void ha_print_info( /*==========*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end,/* in: buffer end */ hash_table_t* table) /* in: hash table */ { hash_cell_t* cell; - ha_node_t* node; +/* ha_node_t* node; */ ulint nodes = 0; ulint cells = 0; ulint len = 0; ulint max_len = 0; ulint i; + if (buf_end - buf < 200) { + return; + } + for (i = 0; i < hash_get_n_cells(table); i++) { cell = hash_get_nth_cell(table, i); @@ -286,7 +311,7 @@ ha_print_info( if (cell->node) { cells++; - +/* len = 0; node = cell->node; @@ -306,12 +331,10 @@ ha_print_info( if (len > max_len) { max_len = len; } +*/ } } - printf("Hash table size %lu, used cells %lu, nodes %lu\n", - hash_get_n_cells(table), cells, nodes); - printf("max chain length %lu\n", max_len); - - ut_a(ha_validate(table)); + buf += sprintf(buf, "Hash table size %lu, used cells %lu\n", + hash_get_n_cells(table), cells); } diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index f51a924c87f..2cbffadf6a9 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -2703,22 +2703,30 @@ ibuf_validate_low(void) Prints info of ibuf. */ void -ibuf_print(void) -/*============*/ +ibuf_print( +/*=======*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end)/* in: buffer end */ { ibuf_data_t* data; #ifdef UNIV_IBUF_DEBUG ulint i; #endif + if (buf_end - buf < 500) { + return; + } + mutex_enter(&ibuf_mutex); data = UT_LIST_GET_FIRST(ibuf->data_list); while (data) { - printf( + buf += sprintf(buf, "Ibuf for space %lu: size %lu, free list len %lu, seg size %lu,\n", data->space, data->size, data->free_list_len, data->seg_size); - printf("%lu inserts, %lu merged recs, %lu merges\n", + + buf += sprintf(buf, + "%lu inserts, %lu merged recs, %lu merges\n", data->n_inserts, data->n_merged_recs, data->n_merges); #ifdef UNIV_IBUF_DEBUG for (i = 0; i < IBUF_COUNT_N_PAGES; i++) { diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h index 7af34deb30f..b01cbd9a875 100644 --- a/innobase/include/btr0cur.h +++ b/innobase/include/btr0cur.h @@ -710,6 +710,8 @@ allowed to free an inherited external field. */ extern ulint btr_cur_n_non_sea; extern ulint btr_cur_n_sea; +extern ulint btr_cur_n_non_sea_old; +extern ulint btr_cur_n_sea_old; #ifndef UNIV_NONINL #include "btr0cur.ic" diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index ca0692f1e17..b80ed96f54c 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -448,7 +448,7 @@ Prints info of the buffer pool data structure. */ void buf_print(void); -/*===========*/ +/*============*/ /************************************************************************* Returns the number of pending buf pool ios. */ @@ -459,8 +459,10 @@ buf_get_n_pending_ios(void); Prints info of the buffer i/o. */ void -buf_print_io(void); -/*==============*/ +buf_print_io( +/*=========*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end);/* in: buffer end */ /************************************************************************* 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 aeed7c32eff..945b1198a41 100644 --- a/innobase/include/ha0ha.h +++ b/innobase/include/ha0ha.h @@ -127,6 +127,8 @@ Prints info of a hash table. */ void ha_print_info( /*==========*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end,/* in: buffer end */ hash_table_t* table); /* in: hash table */ diff --git a/innobase/include/ibuf0ibuf.h b/innobase/include/ibuf0ibuf.h index fac28461be4..a290e90e4db 100644 --- a/innobase/include/ibuf0ibuf.h +++ b/innobase/include/ibuf0ibuf.h @@ -269,8 +269,10 @@ ibuf_count_get( Prints info of ibuf. */ void -ibuf_print(void); -/*============*/ +ibuf_print( +/*=======*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end);/* in: buffer end */ #define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO #define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 5a15b78b869..80afba97416 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -460,6 +460,8 @@ Prints info of a table lock. */ void lock_table_print( /*=============*/ + char* buf, /* in/out: buffer where to print, must be at least + 500 bytes */ lock_t* lock); /* in: table type lock */ /************************************************************************* Prints info of a record lock. */ @@ -467,13 +469,17 @@ Prints info of a record lock. */ void lock_rec_print( /*===========*/ + char* buf, /* in/out: buffer where to print, must be at least + 500 bytes */ lock_t* lock); /* in: record type lock */ /************************************************************************* Prints info of locks for all transactions. */ void -lock_print_info(void); -/*=================*/ +lock_print_info( +/*============*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end);/* in: buffer end */ /************************************************************************* Validates the lock queue on a table. */ diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h index d4bd0036c5a..5d848b85658 100644 --- a/innobase/include/log0log.h +++ b/innobase/include/log0log.h @@ -493,8 +493,10 @@ log_block_convert_lsn_to_no( Prints info of the log. */ void -log_print(void); -/*===========*/ +log_print( +/*======*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end);/* in: buffer end */ extern log_t* log_sys; diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index d4d12e4a9d9..b7911c5014a 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -403,8 +403,10 @@ os_aio_validate(void); Prints info of the aio arrays. */ void -os_aio_print(void); -/*==============*/ +os_aio_print( +/*=========*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end);/* in: buffer end */ /************************************************************************** Checks that all slots in the system have been freed, that is, there are no pending io operations. */ diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 6b96e3056fa..aaa3c58a003 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -970,8 +970,6 @@ rec_fold( ut_ad(n_fields <= rec_get_n_fields(rec)); ut_ad((n_fields < rec_get_n_fields(rec)) || (n_bytes == 0)); ut_ad(n_fields + n_bytes > 0); - /* Only the page supremum and infimum records have 1 field: */ - ut_ad(rec_get_n_fields(rec) > 1); n_fields_rec = rec_get_n_fields(rec); diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 903dd9afc90..1f76974b03d 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -356,6 +356,14 @@ srv_error_monitor_thread( /* out: a dummy parameter */ void* arg); /* in: a dummy parameter required by os_thread_create */ +/********************************************************************** +Sprintfs to a buffer the output of the InnoDB Monitor. */ + +void +srv_sprintf_innodb_monitor( +/*=======================*/ + char* buf, /* in/out: buffer which must be at least 4 kB */ + ulint len); /* in: length of the buffer */ /* Types for the threads existing in the system. Threads of types 4 - 9 diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h index f0134894997..765ad33afea 100644 --- a/innobase/include/sync0arr.h +++ b/innobase/include/sync0arr.h @@ -114,6 +114,8 @@ Prints info of the wait array. */ void sync_array_print_info( /*==================*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end,/* in: buffer end */ sync_array_t* arr); /* in: wait array */ diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h index 4f55709a5d7..5bfa0bc2d48 100644 --- a/innobase/include/sync0sync.h +++ b/innobase/include/sync0sync.h @@ -117,14 +117,18 @@ FUNCTION PROTOTYPES FOR DEBUGGING */ Prints wait info of the sync system. */ void -sync_print_wait_info(void); -/*======================*/ +sync_print_wait_info( +/*=================*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end); /* in: buffer end */ /*********************************************************************** Prints info of the sync system. */ void -sync_print(void); -/*============*/ +sync_print( +/*=======*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end); /* in: buffer end */ /********************************************************************** Checks that the mutex has been initialized. */ diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 090473f3a5a..83789966514 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -261,7 +261,9 @@ own the kernel mutex. */ void trx_print( /*======*/ - trx_t* trx); /* in: transaction */ + char* buf, /* in/out: buffer where to print, must be at least + 500 bytes */ + trx_t* trx); /* in: transaction */ /* Signal to a transaction */ diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 1bdbf72bda6..f7ba49004d7 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -3326,34 +3326,37 @@ Prints info of a table lock. */ void lock_table_print( /*=============*/ + char* buf, /* in/out: buffer where to print, must be at least + 500 bytes */ lock_t* lock) /* in: table type lock */ { ut_ad(mutex_own(&kernel_mutex)); ut_a(lock_get_type(lock) == LOCK_TABLE); - printf("TABLE LOCK table %s trx id %lu %lu", + buf += sprintf(buf, "TABLE LOCK table %s trx id %lu %lu", lock->un_member.tab_lock.table->name, (lock->trx)->id.high, (lock->trx)->id.low); if (lock_get_mode(lock) == LOCK_S) { - printf(" lock mode S"); + buf += sprintf(buf, " lock mode S"); } else if (lock_get_mode(lock) == LOCK_X) { - printf(" lock_mode X"); + buf += sprintf(buf, " lock_mode X"); } else if (lock_get_mode(lock) == LOCK_IS) { - printf(" lock_mode IS"); + buf += sprintf(buf, " lock_mode IS"); } else if (lock_get_mode(lock) == LOCK_IX) { - printf(" lock_mode IX"); + buf += sprintf(buf, " lock_mode IX"); } else if (lock_get_mode(lock) == LOCK_AUTO_INC) { - printf(" lock_mode AUTO-INC"); + buf += sprintf(buf, " lock_mode AUTO-INC"); } else { - printf(" unknown lock_mode %lu", lock_get_mode(lock)); + buf += sprintf(buf, + " unknown lock_mode %lu", lock_get_mode(lock)); } if (lock_get_wait(lock)) { - printf(" waiting"); + buf += sprintf(buf, " waiting"); } - printf("\n"); + buf += sprintf(buf, "\n"); } /************************************************************************* @@ -3362,6 +3365,8 @@ Prints info of a record lock. */ void lock_rec_print( /*===========*/ + char* buf, /* in/out: buffer where to print, must be at least + 500 bytes */ lock_t* lock) /* in: record type lock */ { page_t* page; @@ -3369,8 +3374,7 @@ lock_rec_print( ulint page_no; ulint i; ulint count = 0; - ulint len; - char buf[200]; + char* buf_start = buf; mtr_t mtr; ut_ad(mutex_own(&kernel_mutex)); @@ -3379,32 +3383,32 @@ lock_rec_print( space = lock->un_member.rec_lock.space; page_no = lock->un_member.rec_lock.page_no; - printf("RECORD LOCKS space id %lu page no %lu n bits %lu", + buf += sprintf(buf, "RECORD LOCKS space id %lu page no %lu n bits %lu", space, page_no, lock_rec_get_n_bits(lock)); - printf(" table %s index %s trx id %lu %lu", + buf += sprintf(buf, " table %s index %s trx id %lu %lu", lock->index->table->name, lock->index->name, (lock->trx)->id.high, (lock->trx)->id.low); if (lock_get_mode(lock) == LOCK_S) { - printf(" lock mode S"); + buf += sprintf(buf, " lock mode S"); } else if (lock_get_mode(lock) == LOCK_X) { - printf(" lock_mode X"); + buf += sprintf(buf, " lock_mode X"); } else { ut_error; } if (lock_rec_get_gap(lock)) { - printf(" gap type lock"); + buf += sprintf(buf, " gap type lock"); } if (lock_get_wait(lock)) { - printf(" waiting"); + buf += sprintf(buf, " waiting"); } mtr_start(&mtr); - printf("\n"); + buf += sprintf(buf, "\n"); /* If the page is not in the buffer pool, we cannot load it because we have the kernel mutex and ibuf operations would @@ -3423,28 +3427,28 @@ lock_rec_print( for (i = 0; i < lock_rec_get_n_bits(lock); i++) { + if (buf - buf_start > 300) { + + buf += sprintf(buf, + "Suppressing further record lock prints for this page\n"); + return; + } + if (lock_rec_get_nth_bit(lock, i)) { - printf("Record lock, heap no %lu ", i); + buf += sprintf(buf, "Record lock, heap no %lu ", i); if (page) { - len = rec_sprintf(buf, 190, + buf += rec_sprintf(buf, 120, page_find_rec_with_heap_no(page, i)); - buf[len] = '\0'; - printf("%s", buf); + *buf = '\0'; } - printf("\n"); + buf += sprintf(buf, "\n"); count++; } - - if (count >= 3) { - printf( - "3 LOCKS PRINTED FOR THIS TRX AND PAGE: SUPPRESSING FURTHER PRINTS\n"); - goto end_prints; - } } -end_prints: + mtr_commit(&mtr); } @@ -3479,8 +3483,10 @@ lock_get_n_rec_locks(void) Prints info of locks for all transactions. */ void -lock_print_info(void) -/*=================*/ +lock_print_info( +/*============*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end)/* in: buffer end */ { lock_t* lock; trx_t* trx; @@ -3493,11 +3499,15 @@ lock_print_info(void) ulint i; mtr_t mtr; - printf("Trx id counter %lu %lu\n", + if (buf_end - buf < 600) { + return; + } + + 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)); - printf( + buf += sprintf(buf, "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n", ut_dulint_get_high(purge_sys->purge_trx_no), ut_dulint_get_low(purge_sys->purge_trx_no), @@ -3506,7 +3516,8 @@ lock_print_info(void) lock_mutex_enter_kernel(); - printf("Total number of lock structs in row lock hash table %lu\n", + buf += sprintf(buf, + "Total number of lock structs in row lock hash table %lu\n", lock_get_n_rec_locks()); /* First print info on non-active transactions */ @@ -3514,9 +3525,15 @@ lock_print_info(void) trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); while (trx) { + if (buf_end - buf < 600) { + return; + } + if (trx->conc_state == TRX_NOT_STARTED) { - printf("---"); - trx_print(trx); + buf += sprintf(buf, "---"); + trx_print(buf, trx); + + buf += strlen(buf); } trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); @@ -3545,12 +3562,22 @@ loop: return; } + if (buf_end - buf < 600) { + return; + } + if (nth_lock == 0) { - printf("---"); - trx_print(trx); + buf += sprintf(buf, "---"); + trx_print(buf, trx); + buf += strlen(buf); + + if (buf_end - buf < 500) { + return; + } + if (trx->read_view) { - printf( + buf += sprintf(buf, "Trx read view will not see trx with id >= %lu %lu, sees < %lu %lu\n", ut_dulint_get_high(trx->read_view->low_limit_id), ut_dulint_get_low(trx->read_view->low_limit_id), @@ -3559,16 +3586,17 @@ loop: } if (trx->que_state == TRX_QUE_LOCK_WAIT) { - printf( + buf += sprintf(buf, "------------------TRX IS WAITING FOR THE LOCK:\n"); if (lock_get_type(trx->wait_lock) == LOCK_REC) { - lock_rec_print(trx->wait_lock); + lock_rec_print(buf, trx->wait_lock); } else { - lock_table_print(trx->wait_lock); + lock_table_print(buf, trx->wait_lock); } - printf( + buf += strlen(buf); + buf += sprintf(buf, "------------------\n"); } } @@ -3597,6 +3625,10 @@ loop: goto loop; } + if (buf_end - buf < 500) { + return; + } + if (lock_get_type(lock) == LOCK_REC) { space = lock->un_member.rec_lock.space; page_no = lock->un_member.rec_lock.page_no; @@ -3617,19 +3649,21 @@ loop: goto loop; } - lock_rec_print(lock); + lock_rec_print(buf, lock); } else { ut_ad(lock_get_type(lock) == LOCK_TABLE); - lock_table_print(lock); + lock_table_print(buf, lock); } + buf += strlen(buf); + load_page_first = TRUE; nth_lock++; if (nth_lock >= 10) { - printf( + buf += sprintf(buf, "10 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n"); nth_trx++; diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index d6e9deaa151..9d79c19a586 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -3081,15 +3081,22 @@ log_check_log_recs( Prints info of the log. */ void -log_print(void) -/*===========*/ +log_print( +/*======*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end)/* in: buffer end */ { double time_elapsed; time_t current_time; + if (buf_end - buf < 300) { + + return; + } + mutex_enter(&(log_sys->mutex)); - printf("Log sequence number %lu %lu\n" + buf += sprintf(buf, "Log sequence number %lu %lu\n" "Log flushed up to %lu %lu\n" "Last checkpoint at %lu %lu\n", ut_dulint_get_high(log_sys->lsn), @@ -3103,7 +3110,7 @@ log_print(void) time_elapsed = difftime(current_time, log_sys->last_printout_time); - printf( + 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", log_sys->n_pending_writes, diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index e98b9e95cf7..34e13b80c58 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -1094,7 +1094,9 @@ os_file_write( fprintf(stderr, " InnoDB: Error: File pointer positioning to file %s failed at\n" -"InnoDB: offset %lu %lu. Operating system error number %lu.\n", +"InnoDB: offset %lu %lu. Operating system error number %lu.\n" +"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" +"InnoDB: what the error number means.\n", name, offset_high, offset, (ulint)GetLastError()); @@ -1125,8 +1127,10 @@ os_file_write( " InnoDB: Error: Write to file %s failed at offset %lu %lu.\n" "InnoDB: %lu bytes should have been written, only %lu were written.\n" "InnoDB: Operating system error number %lu.\n" +"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" +"InnoDB: what the error number means.\n" "InnoDB: Check that your OS and file system support files of this size.\n" -"InnoDB: Check also the disk is not full or a disk quota exceeded.\n", +"InnoDB: Check also that the disk is not full or a disk quota exceeded.\n", name, offset_high, offset, n, len, (ulint)GetLastError()); @@ -1152,8 +1156,10 @@ os_file_write( " InnoDB: Error: Write to file %s failed at offset %lu %lu.\n" "InnoDB: %lu bytes should have been written, only %lu were written.\n" "InnoDB: Operating system error number %lu.\n" +"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" +"InnoDB: what the error number means or use the perror program of MySQL.\n" "InnoDB: Check that your OS and file system support files of this size.\n" -"InnoDB: Check also the disk is not full or a disk quota exceeded.\n", +"InnoDB: Check also that the disk is not full or a disk quota exceeded.\n", name, offset_high, offset, n, (ulint)ret, (ulint)errno); os_has_said_disk_full = TRUE; @@ -1744,7 +1750,6 @@ os_aio( ut_ad(buf); ut_ad(n > 0); ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0); - ut_ad((ulint)buf % OS_FILE_LOG_BLOCK_SIZE == 0) ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(os_aio_validate()); @@ -2388,8 +2393,10 @@ os_aio_validate(void) Prints info of the aio arrays. */ void -os_aio_print(void) -/*==============*/ +os_aio_print( +/*=========*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end)/* in: buffer end */ { os_aio_array_t* array; os_aio_slot_t* slot; @@ -2399,12 +2406,17 @@ os_aio_print(void) double avg_bytes_read; ulint i; + if (buf_end - buf < 1000) { + + return; + } + for (i = 0; i < srv_n_file_io_threads; i++) { - printf("I/O thread %lu state: %s\n", i, + buf += sprintf(buf, "I/O thread %lu state: %s\n", i, srv_io_thread_op_info[i]); } - printf("Pending normal aio reads:"); + buf += sprintf(buf, "Pending normal aio reads:"); array = os_aio_read_array; loop: @@ -2431,12 +2443,12 @@ loop: ut_a(array->n_reserved == n_reserved); - printf(" %lu", n_reserved); + buf += sprintf(buf, " %lu", n_reserved); os_mutex_exit(array->mutex); if (array == os_aio_read_array) { - printf(", aio writes:"); + buf += sprintf(buf, ", aio writes:"); array = os_aio_write_array; @@ -2444,34 +2456,36 @@ loop: } if (array == os_aio_write_array) { - printf(",\n ibuf aio reads:"); + buf += sprintf(buf, ",\n ibuf aio reads:"); array = os_aio_ibuf_array; goto loop; } if (array == os_aio_ibuf_array) { - printf(", log i/o's:"); + buf += sprintf(buf, ", log i/o's:"); array = os_aio_log_array; goto loop; } if (array == os_aio_log_array) { - printf(", sync i/o's:"); + buf += sprintf(buf, ", sync i/o's:"); array = os_aio_sync_array; goto loop; } - printf("\n"); + buf += sprintf(buf, "\n"); current_time = time(NULL); time_elapsed = difftime(current_time, os_last_printout); - printf("Pending flushes (fsync) log: %lu; buffer pool: %lu\n", + buf += sprintf(buf, + "Pending flushes (fsync) log: %lu; buffer pool: %lu\n", fil_n_pending_log_flushes, fil_n_pending_tablespace_flushes); - printf("%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n", + buf += sprintf(buf, + "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n", os_n_file_reads, os_n_file_writes, os_n_fsyncs); if (os_n_file_reads == os_n_file_reads_old) { @@ -2481,7 +2495,7 @@ loop: (os_n_file_reads - os_n_file_reads_old); } - printf( + buf += sprintf(buf, "%.2f reads/s, %lu avg bytes/read, %.2f writes/s, %.2f fsyncs/s\n", (os_n_file_reads - os_n_file_reads_old) / time_elapsed, diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index b05476e0a3d..638df1b6380 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2416,6 +2416,14 @@ row_check_table_for_mysql( index = dict_table_get_next_index(index); } + /* We validate also the whole adaptive hash index for all tables + at every CHECK TABLE */ + + if (!btr_search_validate()) { + + ret = DB_ERROR; + } + prebuilt->trx->op_info = ""; return(ret); diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c index 9e8ba87fc2f..bbffda39352 100644 --- a/innobase/row/row0umod.c +++ b/innobase/row/row0umod.c @@ -437,11 +437,12 @@ row_undo_mod_del_unmark_sec( rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur)); fprintf(stderr, "InnoDB: record %s\n", err_buf); + trx_print(err_buf, thr_get_trx(thr)); fprintf(stderr, - "InnoDB: Make a detailed bug report and send it\n"); + "%s\nInnoDB: Make a detailed bug report and send it\n", + err_buf); fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); - trx_print(thr_get_trx(thr)); } else { btr_cur = btr_pcur_get_btr_cur(&pcur); diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index 77af2390786..6eaab79060e 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -1095,11 +1095,12 @@ row_upd_sec_index_entry( rec_sprintf(err_buf, 900, rec); fprintf(stderr, "InnoDB: record %s\n", err_buf); + trx_print(err_buf, thr_get_trx(thr)); + fprintf(stderr, - "InnoDB: Make a detailed bug report and send it\n"); + "%s\nInnoDB: Make a detailed bug report and send it\n", + err_buf); fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); - - trx_print(thr_get_trx(thr)); } else { /* Delete mark the old index record; it can already be delete marked if we return after a lock wait in diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 19e2b08d5a6..81b3333cbe8 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -272,6 +272,8 @@ i/o handler thread */ char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS]; +time_t srv_last_monitor_time; + /* IMPLEMENTATION OF THE SERVER MAIN PROGRAM ========================================= @@ -2131,106 +2133,106 @@ srv_release_mysql_thread_if_suspended( /* not found */ } -/************************************************************************* -A thread which wakes up threads whose lock wait may have lasted too long. -This also prints the info output by various InnoDB monitors. */ +/********************************************************************** +Sprintfs to a buffer the output of the InnoDB Monitor. */ -#ifndef __WIN__ -void* -#else -ulint -#endif -srv_lock_timeout_and_monitor_thread( -/*================================*/ - /* out: a dummy parameter */ - void* arg) /* in: a dummy parameter required by - os_thread_create */ +void +srv_sprintf_innodb_monitor( +/*=======================*/ + char* buf, /* in/out: buffer which must be at least 4 kB */ + ulint len) /* in: length of the buffer */ { - srv_slot_t* slot; - double time_elapsed; - time_t current_time; - time_t last_monitor_time; - time_t last_table_monitor_time; - ibool some_waits; - double wait_time; - ulint i; + char* buf_end = buf + len - 2000; + double time_elapsed; + time_t current_time; - UT_NOT_USED(arg); - last_monitor_time = time(NULL); - last_table_monitor_time = time(NULL); -loop: - srv_lock_timeout_and_monitor_active = TRUE; - - /* 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); + current_time = time(NULL); - /* In case mutex_exit is not a memory barrier, it is - theoretically possible some threads are left waiting though - the semaphore is already released. Wake up those threads: */ - - sync_arr_wake_threads_if_sema_free(); + time_elapsed = difftime(current_time, srv_last_monitor_time); - current_time = time(NULL); + srv_last_monitor_time = time(NULL); - time_elapsed = difftime(current_time, last_monitor_time); - - if (time_elapsed > 15) { + ut_a(len >= 4096); - if (srv_print_innodb_monitor) { + buf += sprintf(buf, "\n=====================================\n"); - last_monitor_time = time(NULL); + ut_sprintf_timestamp(buf); + buf = buf + strlen(buf); - printf("=====================================\n"); - ut_print_timestamp(stdout); - - printf(" INNODB MONITOR OUTPUT\n" + buf += sprintf(buf, " INNODB MONITOR OUTPUT\n" "=====================================\n"); - printf("----------\n" + + buf += sprintf(buf, +"Per second values calculated from the last %lu seconds\n", + (ulint)time_elapsed); + + buf += sprintf(buf, "----------\n" "SEMAPHORES\n" "----------\n"); - sync_print(); - printf("------------\n" + sync_print(buf, buf_end); + + buf = buf + strlen(buf); + + buf += sprintf(buf, "------------\n" "TRANSACTIONS\n" "------------\n"); - lock_print_info(); - printf("--------\n" + lock_print_info(buf, buf_end); + buf = buf + strlen(buf); + + buf += sprintf(buf, "--------\n" "FILE I/O\n" "--------\n"); - os_aio_print(); - printf("-------------------------------------\n" + os_aio_print(buf, buf_end); + buf = buf + strlen(buf); + + buf += sprintf(buf, "-------------------------------------\n" "INSERT BUFFER AND ADAPTIVE HASH INDEX\n" "-------------------------------------\n"); - ibuf_print(); - printf("Successful hash searches %lu, non-hash searches %lu\n", - btr_cur_n_sea, btr_cur_n_non_sea); - printf("---\n" + ibuf_print(buf, buf_end); + buf = buf + strlen(buf); + + ha_print_info(buf, buf_end, btr_search_sys->hash_index); + buf = buf + strlen(buf); + + buf += sprintf(buf, + "%.2f hash searches/s, %.2f non-hash searches/s\n", + (btr_cur_n_sea - btr_cur_n_sea_old) + / 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; + + buf += sprintf(buf,"---\n" "LOG\n" "---\n"); - log_print(); - printf("----------------------\n" + log_print(buf, buf_end); + buf = buf + strlen(buf); + + buf += sprintf(buf, "----------------------\n" "BUFFER POOL AND MEMORY\n" "----------------------\n"); - printf( + buf += sprintf(buf, "Total memory allocated %lu; in additional pool allocated %lu\n", ut_total_allocated_memory, mem_pool_get_reserved(mem_comm_pool)); - buf_print_io(); - printf("--------------\n" + buf_print_io(buf, buf_end); + buf = buf + strlen(buf); + + buf += sprintf(buf, "--------------\n" "ROW OPERATIONS\n" "--------------\n"); - printf( + buf += sprintf(buf, "%ld queries inside InnoDB, %ld queries in queue; main thread: %s\n", srv_conc_n_threads, srv_conc_n_waiting_threads, srv_main_thread_op_info); - printf( + buf += sprintf(buf, "Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n", srv_n_rows_inserted, srv_n_rows_updated, srv_n_rows_deleted, srv_n_rows_read); - printf( + buf += sprintf(buf, "%.2f inserts/s, %.2f updates/s, %.2f deletes/s, %.2f reads/s\n", (srv_n_rows_inserted - srv_n_rows_inserted_old) / time_elapsed, @@ -2246,9 +2248,70 @@ loop: srv_n_rows_deleted_old = srv_n_rows_deleted; srv_n_rows_read_old = srv_n_rows_read; - printf("----------------------------\n" + buf += sprintf(buf, "----------------------------\n" "END OF INNODB MONITOR OUTPUT\n" "============================\n"); +} + +/************************************************************************* +A thread which wakes up threads whose lock wait may have lasted too long. +This also prints the info output by various InnoDB monitors. */ + +#ifndef __WIN__ +void* +#else +ulint +#endif +srv_lock_timeout_and_monitor_thread( +/*================================*/ + /* out: a dummy parameter */ + void* arg) /* in: a dummy parameter required by + os_thread_create */ +{ + srv_slot_t* slot; + double time_elapsed; + time_t current_time; + time_t last_table_monitor_time; + time_t last_monitor_time; + ibool some_waits; + double wait_time; + char* buf; + ulint i; + + UT_NOT_USED(arg); + srv_last_monitor_time = time(NULL); + last_table_monitor_time = time(NULL); + last_monitor_time = time(NULL); +loop: + srv_lock_timeout_and_monitor_active = TRUE; + + /* 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); + + /* In case mutex_exit is not a memory barrier, it is + theoretically possible some threads are left waiting though + the semaphore is already released. Wake up those threads: */ + + sync_arr_wake_threads_if_sema_free(); + + current_time = time(NULL); + + time_elapsed = difftime(current_time, last_monitor_time); + + if (time_elapsed > 15) { + last_monitor_time = time(NULL); + + if (srv_print_innodb_monitor) { + + buf = mem_alloc(100000); + + srv_sprintf_innodb_monitor(buf, 100000); + + printf("%s", buf); + + mem_free(buf); } if (srv_print_innodb_tablespace_monitor @@ -2380,7 +2443,13 @@ loop: srv_error_monitor_active = TRUE; os_thread_sleep(10000000); + /* + printf("Validating has index\n"); + + btr_search_validate(); + printf("Hash index validated\n"); + */ sync_array_print_long_waits(); /* Flush stdout and stderr so that a database user gets their output diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index ff4c4f021b0..9768d484ce6 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -896,7 +896,7 @@ test_measure_cont( "Mutex res. l %lu, p %lu, k %lu s x %lu s s %lu s mut %lu of %lu\n", lcount, pcount, kcount, s_xcount, s_scount, s_mcount, j); - sync_print_wait_info(); +/* sync_print_wait_info(); */ fprintf(stderr, "log i/o %lu n non sea %lu n succ %lu n h fail %lu\n", diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index 7788b104120..81b5b7de195 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -441,7 +441,8 @@ static void sync_array_cell_print( /*==================*/ - FILE* file, /* in: file where to print */ + char* buf, /* in: buffer where to print, must be + at least 400 characters */ sync_cell_t* cell) /* in: sync cell */ { mutex_t* mutex; @@ -451,7 +452,7 @@ sync_array_cell_print( type = cell->request_type; - fprintf(file, + buf += sprintf(buf, "--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n", (ulint)cell->thread, cell->file, cell->line, difftime(time(NULL), cell->reservation_time)); @@ -461,54 +462,58 @@ sync_array_cell_print( been freed meanwhile */ mutex = cell->old_wait_mutex; - fprintf(file, + buf += sprintf(buf, "Mutex at %lx created file %s line %lu, lock var %lu\n", (ulint)mutex, mutex->cfile_name, mutex->cline, mutex->lock_word); - fprintf(file, + buf += sprintf(buf, "Last time reserved in file %s line %lu, waiters flag %lu\n", mutex->file_name, mutex->line, mutex->waiters); } else if (type == RW_LOCK_EX || type == RW_LOCK_SHARED) { if (type == RW_LOCK_EX) { - fprintf(file, "X-lock on"); + buf += sprintf(buf, "X-lock on"); } else { - fprintf(file, "S-lock on"); + buf += sprintf(buf, "S-lock on"); } rwlock = cell->old_wait_rw_lock; - fprintf(file, " RW-latch at %lx created in file %s line %lu\n", + buf += sprintf(buf, + " RW-latch at %lx created in file %s line %lu\n", (ulint)rwlock, rwlock->cfile_name, rwlock->cline); if (rwlock->writer != RW_LOCK_NOT_LOCKED) { - fprintf(file, + buf += sprintf(buf, "a writer (thread id %lu) has reserved it in mode", (ulint)rwlock->writer_thread); if (rwlock->writer == RW_LOCK_EX) { - fprintf(file, " exclusive\n"); + buf += sprintf(buf, " exclusive\n"); } else { - fprintf(file, " wait exclusive\n"); + buf += sprintf(buf, " wait exclusive\n"); } } - fprintf(file, "number of readers %lu, waiters flag %lu\n", + buf += sprintf(buf, + "number of readers %lu, waiters flag %lu\n", rwlock->reader_count, rwlock->waiters); - fprintf(file, "Last time read locked in file %s line %lu\n", + buf += sprintf(buf, + "Last time read locked in file %s line %lu\n", rwlock->last_s_file_name, rwlock->last_s_line); - fprintf(file, "Last time write locked in file %s line %lu\n", + buf += sprintf(buf, + "Last time write locked in file %s line %lu\n", rwlock->last_x_file_name, rwlock->last_x_line); } else { ut_error; } if (!cell->waiting) { - fprintf(file, "wait has ended\n"); + buf += sprintf(buf, "wait has ended\n"); } if (cell->event_set) { - fprintf(file, "wait is ending\n"); + buf += sprintf(buf, "wait is ending\n"); } } @@ -610,6 +615,7 @@ sync_array_detect_deadlock( os_thread_id_t thread; ibool ret; rw_lock_debug_t* debug; + char buf[500]; ut_a(arr && start && cell); ut_ad(cell->wait_object); @@ -642,11 +648,12 @@ sync_array_detect_deadlock( ret = sync_array_deadlock_step(arr, start, thread, 0, depth); if (ret) { + sync_array_cell_print(buf, cell); printf( - "Mutex %lx owned by thread %lu file %s line %lu\n", + "Mutex %lx owned by thread %lu file %s line %lu\n%s", (ulint)mutex, mutex->thread_id, - mutex->file_name, mutex->line); - sync_array_cell_print(stdout, cell); + mutex->file_name, mutex->line, + buf); return(TRUE); } } @@ -678,9 +685,9 @@ sync_array_detect_deadlock( debug->pass, depth); if (ret) { - printf("rw-lock %lx ", (ulint) lock); + sync_array_cell_print(buf, cell); + printf("rw-lock %lx %s ", (ulint) lock, buf); rw_lock_debug_print(debug); - sync_array_cell_print(stdout, cell); return(TRUE); } @@ -711,9 +718,9 @@ sync_array_detect_deadlock( debug->pass, depth); if (ret) { - printf("rw-lock %lx ", (ulint) lock); + sync_array_cell_print(buf, cell); + printf("rw-lock %lx %s ", (ulint) lock, buf); rw_lock_debug_print(debug); - sync_array_cell_print(stdout, cell); return(TRUE); } @@ -898,6 +905,7 @@ sync_array_print_long_waits(void) sync_cell_t* cell; ibool old_val; ibool noticed = FALSE; + char buf[500]; ulint i; for (i = 0; i < sync_primary_wait_array->n_cells; i++) { @@ -907,9 +915,10 @@ sync_array_print_long_waits(void) if (cell->wait_object != NULL && difftime(time(NULL), cell->reservation_time) > 240) { + sync_array_cell_print(buf, cell); + fprintf(stderr, - "InnoDB: Warning: a long semaphore wait:\n"); - sync_array_cell_print(stderr, cell); + "InnoDB: Warning: a long semaphore wait:\n%s", buf); noticed = TRUE; } @@ -948,6 +957,8 @@ static void sync_array_output_info( /*===================*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end,/* in: buffer end */ sync_array_t* arr) /* in: wait array; NOTE! caller must own the mutex */ { @@ -955,18 +966,29 @@ sync_array_output_info( ulint count; ulint i; - printf("OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n", + if (buf_end - buf < 500) { + return; + } + + buf += sprintf(buf, + "OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n", arr->res_count, arr->sg_count); i = 0; count = 0; while (count < arr->n_reserved) { + if (buf_end - buf < 500) { + return; + } + cell = sync_array_get_nth_cell(arr, i); if (cell->wait_object != NULL) { count++; - sync_array_cell_print(stdout, cell); + sync_array_cell_print(buf, cell); + + buf = buf + strlen(buf); } i++; @@ -979,11 +1001,13 @@ Prints info of the wait array. */ void sync_array_print_info( /*==================*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end,/* in: buffer end */ sync_array_t* arr) /* in: wait array */ { sync_array_enter(arr); - sync_array_output_info(arr); + sync_array_output_info(buf, buf_end, arr); sync_array_exit(arr); } diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index f5b4e35e8d2..c070e97f692 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -874,6 +874,7 @@ sync_thread_levels_empty_gen( sync_level_t* slot; rw_lock_t* lock; mutex_t* mutex; + char* buf; ulint i; if (!sync_order_checks_on) { @@ -907,7 +908,9 @@ sync_thread_levels_empty_gen( mutex = slot->latch; mutex_exit(&sync_thread_mutex); - sync_print(); + buf = mem_alloc(20000); + + sync_print(buf, buf + 18000); ut_error; return(FALSE); @@ -1243,14 +1246,21 @@ sync_close(void) Prints wait info of the sync system. */ void -sync_print_wait_info(void) -/*======================*/ +sync_print_wait_info( +/*=================*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end) /* in: buffer end */ { #ifdef UNIV_SYNC_DEBUG printf("Mutex exits %lu, rws exits %lu, rwx exits %lu\n", mutex_exit_count, rw_s_exit_count, rw_x_exit_count); #endif - printf( + if (buf_end - buf < 500) { + + return; + } + + sprintf(buf, "Mutex spin waits %lu, rounds %lu, OS waits %lu\n" "RW-shared spins %lu, OS waits %lu; RW-excl spins %lu, OS waits %lu\n", mutex_spin_wait_count, mutex_spin_round_count, @@ -1263,11 +1273,18 @@ sync_print_wait_info(void) Prints info of the sync system. */ void -sync_print(void) -/*============*/ +sync_print( +/*=======*/ + char* buf, /* in/out: buffer where to print */ + char* buf_end) /* in: buffer end */ { mutex_list_print_info(); + rw_lock_list_print_info(); - sync_array_print_info(sync_primary_wait_array); - sync_print_wait_info(); + + sync_array_print_info(buf, buf_end, sync_primary_wait_array); + + buf = buf + strlen(buf); + + sync_print_wait_info(buf, buf_end); } diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 9c49abbd287..c2d99424d33 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -26,9 +26,11 @@ Created 3/26/1996 Heikki Tuuri /* Copy of the prototype for innobase_mysql_print_thd: this -copy must be equal to the one in mysql/sql/ha_innobase.cc ! */ +copy MUST be equal to the one in mysql/sql/ha_innobase.cc ! */ -void innobase_mysql_print_thd(void* thd); +void innobase_mysql_print_thd( + char* buf, + void* thd); /* Dummy session used currently in MySQL interface */ sess_t* trx_dummy_sess = NULL; @@ -1459,54 +1461,63 @@ own the kernel mutex. */ void trx_print( /*======*/ + char* buf, /* in/out: buffer where to print, must be at least + 500 bytes */ trx_t* trx) /* in: transaction */ { - printf("TRANSACTION %lu %lu, OS thread id %lu", + buf += sprintf(buf, "TRANSACTION %lu %lu, OS thread id %lu", ut_dulint_get_high(trx->id), ut_dulint_get_low(trx->id), (ulint)trx->mysql_thread_id); if (ut_strlen(trx->op_info) > 0) { - printf(" %s", trx->op_info); + buf += sprintf(buf, " %s", trx->op_info); } if (trx->type != TRX_USER) { - printf(" purge trx"); + buf += sprintf(buf, " purge trx"); } switch (trx->conc_state) { - case TRX_NOT_STARTED: printf(", not started"); break; - case TRX_ACTIVE: printf(", active"); break; - case TRX_COMMITTED_IN_MEMORY: printf(", committed in memory"); + case TRX_NOT_STARTED: buf += sprintf(buf, + ", not started"); break; + case TRX_ACTIVE: buf += sprintf(buf, + ", active"); break; + case TRX_COMMITTED_IN_MEMORY: buf += sprintf(buf, + ", committed in memory"); break; - default: printf(" state %lu", trx->conc_state); + default: buf += sprintf(buf, " state %lu", trx->conc_state); } switch (trx->que_state) { - case TRX_QUE_RUNNING: printf(", runs or sleeps"); break; - case TRX_QUE_LOCK_WAIT: printf(", lock wait"); break; - case TRX_QUE_ROLLING_BACK: printf(", rolling back"); break; - case TRX_QUE_COMMITTING: printf(", committing"); break; - default: printf(" que state %lu", trx->que_state); + case TRX_QUE_RUNNING: buf += sprintf(buf, + ", runs or sleeps"); break; + case TRX_QUE_LOCK_WAIT: buf += sprintf(buf, + ", lock wait"); break; + case TRX_QUE_ROLLING_BACK: buf += sprintf(buf, + ", rolling back"); break; + case TRX_QUE_COMMITTING: buf += sprintf(buf, + ", committing"); break; + default: buf += sprintf(buf, " que state %lu", trx->que_state); } if (0 < UT_LIST_GET_LEN(trx->trx_locks)) { - printf(", has %lu lock struct(s)", + buf += sprintf(buf, ", has %lu lock struct(s)", UT_LIST_GET_LEN(trx->trx_locks)); } if (trx->has_search_latch) { - printf(", holds adaptive hash latch"); + buf += sprintf(buf, ", holds adaptive hash latch"); } if (ut_dulint_cmp(trx->undo_no, ut_dulint_zero) != 0) { - printf(", undo log entries %lu", + buf += sprintf(buf, ", undo log entries %lu", ut_dulint_get_low(trx->undo_no)); } - printf("\n"); + buf += sprintf(buf, "\n"); if (trx->mysql_thd != NULL) { - innobase_mysql_print_thd(trx->mysql_thd); + innobase_mysql_print_thd(buf, trx->mysql_thd); } } |