Loading innobase/btr/btr0btr.c +2 −0 Original line number Diff line number Diff line Loading @@ -2347,6 +2347,8 @@ btr_validate_level( mtr_start(&mtr); mtr_x_lock(dict_tree_get_lock(tree), &mtr); page = btr_root_get(tree, &mtr); space = buf_frame_get_space_id(page); Loading innobase/btr/btr0cur.c +92 −38 Original line number Diff line number Diff line Loading @@ -256,7 +256,8 @@ btr_cur_search_to_nth_level( #ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; #endif if (latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ && !estimate && btr_search_guess_on_hash(index, info, tuple, mode, latch_mode, cursor, Loading Loading @@ -344,9 +345,7 @@ btr_cur_search_to_nth_level( retry_page_get: page = buf_page_get_gen(space, page_no, rw_latch, guess, buf_mode, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); if (page == NULL) { Loading Loading @@ -515,9 +514,7 @@ btr_cur_open_at_index_side( for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); ut_ad(0 == ut_dulint_cmp(tree->id, btr_page_get_index_id(page))); Loading Loading @@ -604,9 +601,7 @@ btr_cur_open_at_rnd_pos( for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); ut_ad(0 == ut_dulint_cmp(tree->id, btr_page_get_index_id(page))); Loading Loading @@ -1222,6 +1217,57 @@ btr_cur_parse_update_in_place( return(ptr); } /***************************************************************** Updates a secondary index record when the update causes no size changes in its fields. The only case when this function is currently called is that in a char field characters change to others which are identified in the collation order. */ ulint btr_cur_update_sec_rec_in_place( /*============================*/ /* out: DB_SUCCESS or error number */ btr_cur_t* cursor, /* in: cursor on the record to update; cursor stays valid and positioned on the same record */ upd_t* update, /* in: update vector */ que_thr_t* thr, /* in: query thread */ mtr_t* mtr) /* in: mtr */ { dict_index_t* index = cursor->index; dict_index_t* clust_index; ulint err; rec_t* rec; dulint roll_ptr = ut_dulint_zero; trx_t* trx = thr_get_trx(thr); /* Only secondary index records are updated using this function */ ut_ad(0 == (index->type & DICT_CLUSTERED)); rec = btr_cur_get_rec(cursor); err = lock_sec_rec_modify_check_and_lock(0, rec, index, thr); if (err != DB_SUCCESS) { return(err); } /* Remove possible hash index pointer to this record */ btr_search_update_hash_on_delete(cursor); row_upd_rec_in_place(rec, update); clust_index = dict_table_get_first_index(index->table); /* Note that roll_ptr is really just a dummy value since a secondary index record does not contain any sys columns */ btr_cur_update_in_place_log(BTR_KEEP_SYS_FLAG, rec, clust_index, update, trx, roll_ptr, mtr); return(DB_SUCCESS); } /***************************************************************** Updates a record when the update causes no size changes in its fields. */ Loading @@ -1248,7 +1294,7 @@ btr_cur_update_in_place( ibool was_delete_marked; /* Only clustered index records are updated using this function */ ut_ad((cursor->index)->type & DICT_CLUSTERED); ut_ad(cursor->index->type & DICT_CLUSTERED); rec = btr_cur_get_rec(cursor); index = cursor->index; Loading Loading @@ -2477,27 +2523,33 @@ btr_estimate_n_rows_in_range( } /*********************************************************************** Estimates the number of different key values in a given index. */ Estimates the number of different key values in a given index, for each n-column prefix of the index where n <= dict_index_get_n_unique(index). The estimates are stored in the array index->stat_n_diff_key_vals. */ ulint void btr_estimate_number_of_different_key_vals( /*======================================*/ /* out: estimated number of key values */ dict_index_t* index) /* in: index */ { btr_cur_t cursor; page_t* page; rec_t* rec; ulint total_n_recs = 0; ulint n_diff_in_page; ulint n_diff = 0; ulint n_cols; ulint matched_fields; ulint matched_bytes; ulint* n_diff; ulint not_empty_flag = 0; ulint i; ulint j; mtr_t mtr; if (index->type & DICT_UNIQUE) { return(index->table->stat_n_rows); n_cols = dict_index_get_n_unique(index); n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong)); for (j = 0; j <= n_cols; j++) { n_diff[j] = 0; } /* We sample some pages in the index to get an estimate */ Loading @@ -2507,17 +2559,19 @@ btr_estimate_number_of_different_key_vals( btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); /* Count the number of different key values minus one on this index page: we subtract one because otherwise our algorithm would give a wrong estimate for an index where there is just one key value */ /* Count the number of different key values minus one for each prefix of the key on this index page: we subtract one because otherwise our algorithm would give a wrong estimate for an index where there is just one key value */ page = btr_cur_get_page(&cursor); rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); n_diff_in_page = 0; if (rec != page_get_supremum_rec(page)) { not_empty_flag = 1; } while (rec != page_get_supremum_rec(page) && page_rec_get_next(rec) Loading @@ -2528,30 +2582,30 @@ btr_estimate_number_of_different_key_vals( cmp_rec_rec_with_match(rec, page_rec_get_next(rec), index, &matched_fields, &matched_bytes); if (matched_fields < dict_index_get_n_ordering_defined_by_user( index)) { n_diff_in_page++; for (j = matched_fields + 1; j <= n_cols; j++) { n_diff[j]++; } rec = page_rec_get_next(rec); } n_diff += n_diff_in_page; total_n_recs += page_get_n_recs(page); mtr_commit(&mtr); } if (n_diff == 0) { /* We play safe and assume that there are just two different key values in the index */ /* If we saw k borders between different key values on BTR_KEY_VAL_ESTIMATE_N_PAGES leaf pages, we can estimate how many there will be in index->stat_n_leaf_pages */ return(2); for (j = 0; j <= n_cols; j++) { index->stat_n_diff_key_vals[j] = (n_diff[j] * index->stat_n_leaf_pages + BTR_KEY_VAL_ESTIMATE_N_PAGES - 1 + not_empty_flag) / BTR_KEY_VAL_ESTIMATE_N_PAGES; } return(index->table->stat_n_rows / (total_n_recs / n_diff)); mem_free(n_diff); } /*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/ Loading innobase/btr/btr0pcur.c +52 −18 Original line number Diff line number Diff line Loading @@ -62,8 +62,10 @@ btr_pcur_free_for_mysql( /****************************************************************** The position of the cursor is stored by taking an initial segment of the record the cursor is positioned on, before, or after, and copying it to the cursor data structure. NOTE that the page where the cursor is positioned must not be empty! */ cursor data structure, or just setting a flag if the cursor id before the first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the page where the cursor is positioned must not be empty if the index tree is not totally empty! */ void btr_pcur_store_position( Loading Loading @@ -93,9 +95,21 @@ btr_pcur_store_position( ut_a(cursor->latch_mode != BTR_NO_LATCHES); if (page_get_n_recs(page) == 0) { /* It must be an empty index tree */ /* Cannot store position! */ btr_pcur_close(cursor); ut_a(btr_page_get_next(page, mtr) == FIL_NULL && btr_page_get_prev(page, mtr) == FIL_NULL); if (rec == page_get_supremum_rec(page)) { cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; cursor->old_stored = BTR_PCUR_OLD_STORED; return; } cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE; cursor->old_stored = BTR_PCUR_OLD_STORED; return; } Loading Loading @@ -140,13 +154,15 @@ btr_pcur_copy_stored_position( ut_memcpy((byte*)pcur_receive, (byte*)pcur_donate, sizeof(btr_pcur_t)); if (pcur_donate->old_rec_buf) { pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size); ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf, pcur_donate->buf_size); pcur_receive->old_rec = pcur_receive->old_rec_buf + (pcur_donate->old_rec - pcur_donate->old_rec_buf); } } /****************************************************************** Loading @@ -158,7 +174,9 @@ to the last record LESS OR EQUAL to the stored record; the last record LESS than the user record which was the successor of the page infimum; (3) cursor was positioned on the page supremum: restores to the first record GREATER than the user record which was the predecessor of the supremum. */ GREATER than the user record which was the predecessor of the supremum. (4) cursor was positioned before the first or after the last in an empty tree: restores to before first or after the last in the tree. */ ibool btr_pcur_restore_position( Loading @@ -177,17 +195,33 @@ btr_pcur_restore_position( dtuple_t* tuple; ulint mode; ulint old_mode; ibool from_left; mem_heap_t* heap; ut_a((cursor->pos_state == BTR_PCUR_WAS_POSITIONED) || (cursor->pos_state == BTR_PCUR_IS_POSITIONED)); ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED || cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { from_left = TRUE; } else { from_left = FALSE; } btr_cur_open_at_index_side(from_left, btr_pcur_get_btr_cur(cursor)->index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr); return(FALSE); } ut_a(cursor->old_rec); page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); if ((latch_mode == BTR_SEARCH_LEAF) || (latch_mode == BTR_MODIFY_LEAF)) { if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) { /* Try optimistic restoration */ if (buf_page_optimistic_get(latch_mode, page, Loading Loading @@ -242,16 +276,15 @@ btr_pcur_restore_position( /* Restore the old search mode */ cursor->search_mode = old_mode; if ((cursor->rel_pos == BTR_PCUR_ON) if (cursor->rel_pos == BTR_PCUR_ON && btr_pcur_is_on_user_rec(cursor, mtr) && (0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor)))) { && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor))) { /* We have to store the NEW value for the modify clock, since the cursor can now be on a different page! */ cursor->modify_clock = buf_frame_get_modify_clock( buf_frame_align( btr_pcur_get_rec(cursor))); buf_frame_align(btr_pcur_get_rec(cursor))); mem_heap_free(heap); return(TRUE); Loading Loading @@ -366,6 +399,7 @@ btr_pcur_move_backward_from_page( latch_mode2 = BTR_MODIFY_PREV; } else { latch_mode2 = 0; /* To eliminate compiler warning */ ut_error; } Loading innobase/btr/btr0sea.c +0 −2 Original line number Diff line number Diff line Loading @@ -680,9 +680,7 @@ btr_search_guess_on_hash( success = buf_page_get_known_nowait(latch_mode, page, BUF_MAKE_YOUNG, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); rw_lock_s_unlock(&btr_search_latch); Loading innobase/buf/buf0buf.c +151 −50 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ Created 11/5/1995 Heikki Tuuri #include "ibuf0ibuf.h" #include "dict0dict.h" #include "log0recv.h" #include "trx0undo.h" #include "srv0srv.h" /* IMPLEMENTATION OF THE BUFFER POOL Loading Loading @@ -240,6 +242,11 @@ buf_page_is_corrupted( checksum = buf_calc_page_checksum(read_buf); /* Note that InnoDB initializes empty pages to zero, and early versions of InnoDB did not store page checksum to the 4 most significant bytes of the page lsn field at the end of a page: */ if ((mach_read_from_4(read_buf + FIL_PAGE_LSN + 4) != mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN + 4)) Loading @@ -256,6 +263,71 @@ buf_page_is_corrupted( return(FALSE); } /************************************************************************ Prints a page to stderr. */ void buf_page_print( /*===========*/ byte* read_buf) /* in: a database page */ { dict_index_t* index; ulint checksum; char* buf; buf = mem_alloc(4 * UNIV_PAGE_SIZE); ut_sprintf_buf(buf, read_buf, UNIV_PAGE_SIZE); fprintf(stderr, "InnoDB: Page dump in ascii and hex (%lu bytes):\n%s", UNIV_PAGE_SIZE, buf); fprintf(stderr, "InnoDB: End of page dump\n"); mem_free(buf); checksum = buf_calc_page_checksum(read_buf); fprintf(stderr, "InnoDB: Page checksum %lu stored checksum %lu\n", checksum, mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN)); fprintf(stderr, "InnoDB: Page lsn %lu %lu, low 4 bytes of lsn at page end %lu\n", mach_read_from_4(read_buf + FIL_PAGE_LSN), mach_read_from_4(read_buf + FIL_PAGE_LSN + 4), mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN + 4)); if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT) { fprintf(stderr, "InnoDB: Page may be an insert undo log page\n"); } else if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE) { fprintf(stderr, "InnoDB: Page may be an update undo log page\n"); } if (fil_page_get_type(read_buf) == FIL_PAGE_INDEX) { fprintf(stderr, "InnoDB: Page may be an index page "); fprintf(stderr, "where index id is %lu %lu\n", ut_dulint_get_high(btr_page_get_index_id(read_buf)), ut_dulint_get_low(btr_page_get_index_id(read_buf))); index = dict_index_find_on_id_low( btr_page_get_index_id(read_buf)); if (index) { fprintf(stderr, "InnoDB: and table %s index %s\n", index->table_name, index->name); } } } /************************************************************************ Initializes a buffer control block when the buf_pool is created. */ static Loading Loading @@ -334,6 +406,8 @@ buf_pool_create( frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE); buf_pool->frame_zero = frame; buf_pool->high_end = frame + UNIV_PAGE_SIZE * curr_size; /* Init block structs and assign frames for them */ for (i = 0; i < max_size; i++) { Loading @@ -345,6 +419,9 @@ buf_pool_create( buf_pool->page_hash = hash_create(2 * max_size); buf_pool->n_pend_reads = 0; buf_pool->last_printout_time = time(NULL); buf_pool->n_pages_read = 0; buf_pool->n_pages_written = 0; buf_pool->n_pages_created = 0; Loading @@ -352,6 +429,8 @@ buf_pool_create( buf_pool->n_page_gets = 0; buf_pool->n_page_gets_old = 0; buf_pool->n_pages_read_old = 0; buf_pool->n_pages_written_old = 0; buf_pool->n_pages_created_old = 0; /* 2. Initialize flushing fields ---------------------------- */ Loading Loading @@ -379,6 +458,10 @@ buf_pool_create( for (i = 0; i < curr_size; i++) { block = buf_pool_get_nth_block(buf_pool, i); /* Wipe contents of page to eliminate a Purify warning */ memset(block->frame, '\0', UNIV_PAGE_SIZE); UT_LIST_ADD_FIRST(free, buf_pool->free, block); } Loading Loading @@ -650,10 +733,8 @@ buf_page_get_gen( buf_frame_t* guess, /* in: guessed frame or NULL */ ulint mode, /* in: BUF_GET, BUF_GET_IF_IN_POOL, BUF_GET_NO_LATCH, BUF_GET_NOWAIT */ #ifdef UNIV_SYNC_DEBUG char* file, /* in: file name */ ulint line, /* in: line where called */ #endif mtr_t* mtr) /* in: mini-transaction */ { buf_block_t* block; Loading Loading @@ -759,19 +840,13 @@ buf_page_get_gen( if (mode == BUF_GET_NOWAIT) { if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG ,file, line #endif ); success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { ut_ad(rw_latch == RW_X_LATCH); success = rw_lock_x_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG ,file, line #endif ); success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading @@ -796,18 +871,12 @@ buf_page_get_gen( fix_type = MTR_MEMO_BUF_FIX; } else if (rw_latch == RW_S_LATCH) { rw_lock_s_lock_func(&(block->lock) #ifdef UNIV_SYNC_DEBUG ,0, file, line #endif ); rw_lock_s_lock_func(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { rw_lock_x_lock_func(&(block->lock), 0 #ifdef UNIV_SYNC_DEBUG , file, line #endif ); rw_lock_x_lock_func(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading Loading @@ -838,10 +907,8 @@ buf_page_optimistic_get_func( buf_frame_t* guess, /* in: guessed frame */ dulint modify_clock,/* in: modify clock value if mode is ..._GUESS_ON_CLOCK */ #ifdef UNIV_SYNC_DEBUG char* file, /* in: file name */ ulint line, /* in: line where called */ #endif mtr_t* mtr) /* in: mini-transaction */ { buf_block_t* block; Loading Loading @@ -883,18 +950,12 @@ buf_page_optimistic_get_func( ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset)); if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { success = rw_lock_x_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading Loading @@ -971,10 +1032,8 @@ buf_page_get_known_nowait( ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */ buf_frame_t* guess, /* in: the known page frame */ ulint mode, /* in: BUF_MAKE_YOUNG or BUF_KEEP_OLD */ #ifdef UNIV_SYNC_DEBUG char* file, /* in: file name */ ulint line, /* in: line where called */ #endif mtr_t* mtr) /* in: mini-transaction */ { buf_block_t* block; Loading Loading @@ -1017,18 +1076,12 @@ buf_page_get_known_nowait( ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { success = rw_lock_x_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading Loading @@ -1315,13 +1368,30 @@ buf_page_io_complete( to the 4 upper bytes of the page end lsn field */ if (buf_page_is_corrupted(block->frame)) { fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, "InnoDB: You may have to recover from a backup.\n"); buf_page_print(block->frame); fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, "InnoDB: You may have to recover from a backup.\n"); fprintf(stderr, "InnoDB: It is also possible that your operating\n" "InnoDB: system has corrupted its own file cache\n" "InnoDB: and rebooting your computer removes the\n" "InnoDB: error.\n"); if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { exit(1); } } if (recv_recovery_is_on()) { recv_recover_page(TRUE, block->frame, block->space, Loading Loading @@ -1622,6 +1692,19 @@ buf_print(void) ut_a(buf_validate()); } /************************************************************************* Returns the number of pending buf pool ios. */ ulint buf_get_n_pending_ios(void) /*=======================*/ { return(buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU] + buf_pool->n_flush[BUF_FLUSH_LIST] + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); } /************************************************************************* Prints info of the buffer i/o. */ Loading @@ -1629,6 +1712,8 @@ void buf_print_io(void) /*==============*/ { time_t current_time; double time_elapsed; ulint size; ut_ad(buf_pool); Loading @@ -1637,11 +1722,11 @@ buf_print_io(void) mutex_enter(&(buf_pool->mutex)); printf("LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU)); 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", UT_LIST_GET_LEN(buf_pool->flush_list)); printf("Buffer pool size in pages %lu\n", size); printf("Buffer pool size %lu\n", size); printf("Pending reads %lu \n", buf_pool->n_pend_reads); Loading @@ -1650,9 +1735,21 @@ buf_print_io(void) buf_pool->n_flush[BUF_FLUSH_LIST], buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); current_time = time(NULL); time_elapsed = difftime(current_time, buf_pool->last_printout_time); buf_pool->last_printout_time = current_time; printf("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_pool->n_pages_read - buf_pool->n_pages_read_old) / time_elapsed, (buf_pool->n_pages_created - buf_pool->n_pages_created_old) / time_elapsed, (buf_pool->n_pages_written - buf_pool->n_pages_written_old) / time_elapsed); if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) { printf("Buffer pool hit rate %lu / 1000\n", Loading @@ -1660,10 +1757,14 @@ buf_print_io(void) - ((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_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; mutex_exit(&(buf_pool->mutex)); } Loading Loading
innobase/btr/btr0btr.c +2 −0 Original line number Diff line number Diff line Loading @@ -2347,6 +2347,8 @@ btr_validate_level( mtr_start(&mtr); mtr_x_lock(dict_tree_get_lock(tree), &mtr); page = btr_root_get(tree, &mtr); space = buf_frame_get_space_id(page); Loading
innobase/btr/btr0cur.c +92 −38 Original line number Diff line number Diff line Loading @@ -256,7 +256,8 @@ btr_cur_search_to_nth_level( #ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; #endif if (latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ && !estimate && btr_search_guess_on_hash(index, info, tuple, mode, latch_mode, cursor, Loading Loading @@ -344,9 +345,7 @@ btr_cur_search_to_nth_level( retry_page_get: page = buf_page_get_gen(space, page_no, rw_latch, guess, buf_mode, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); if (page == NULL) { Loading Loading @@ -515,9 +514,7 @@ btr_cur_open_at_index_side( for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); ut_ad(0 == ut_dulint_cmp(tree->id, btr_page_get_index_id(page))); Loading Loading @@ -604,9 +601,7 @@ btr_cur_open_at_rnd_pos( for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); ut_ad(0 == ut_dulint_cmp(tree->id, btr_page_get_index_id(page))); Loading Loading @@ -1222,6 +1217,57 @@ btr_cur_parse_update_in_place( return(ptr); } /***************************************************************** Updates a secondary index record when the update causes no size changes in its fields. The only case when this function is currently called is that in a char field characters change to others which are identified in the collation order. */ ulint btr_cur_update_sec_rec_in_place( /*============================*/ /* out: DB_SUCCESS or error number */ btr_cur_t* cursor, /* in: cursor on the record to update; cursor stays valid and positioned on the same record */ upd_t* update, /* in: update vector */ que_thr_t* thr, /* in: query thread */ mtr_t* mtr) /* in: mtr */ { dict_index_t* index = cursor->index; dict_index_t* clust_index; ulint err; rec_t* rec; dulint roll_ptr = ut_dulint_zero; trx_t* trx = thr_get_trx(thr); /* Only secondary index records are updated using this function */ ut_ad(0 == (index->type & DICT_CLUSTERED)); rec = btr_cur_get_rec(cursor); err = lock_sec_rec_modify_check_and_lock(0, rec, index, thr); if (err != DB_SUCCESS) { return(err); } /* Remove possible hash index pointer to this record */ btr_search_update_hash_on_delete(cursor); row_upd_rec_in_place(rec, update); clust_index = dict_table_get_first_index(index->table); /* Note that roll_ptr is really just a dummy value since a secondary index record does not contain any sys columns */ btr_cur_update_in_place_log(BTR_KEEP_SYS_FLAG, rec, clust_index, update, trx, roll_ptr, mtr); return(DB_SUCCESS); } /***************************************************************** Updates a record when the update causes no size changes in its fields. */ Loading @@ -1248,7 +1294,7 @@ btr_cur_update_in_place( ibool was_delete_marked; /* Only clustered index records are updated using this function */ ut_ad((cursor->index)->type & DICT_CLUSTERED); ut_ad(cursor->index->type & DICT_CLUSTERED); rec = btr_cur_get_rec(cursor); index = cursor->index; Loading Loading @@ -2477,27 +2523,33 @@ btr_estimate_n_rows_in_range( } /*********************************************************************** Estimates the number of different key values in a given index. */ Estimates the number of different key values in a given index, for each n-column prefix of the index where n <= dict_index_get_n_unique(index). The estimates are stored in the array index->stat_n_diff_key_vals. */ ulint void btr_estimate_number_of_different_key_vals( /*======================================*/ /* out: estimated number of key values */ dict_index_t* index) /* in: index */ { btr_cur_t cursor; page_t* page; rec_t* rec; ulint total_n_recs = 0; ulint n_diff_in_page; ulint n_diff = 0; ulint n_cols; ulint matched_fields; ulint matched_bytes; ulint* n_diff; ulint not_empty_flag = 0; ulint i; ulint j; mtr_t mtr; if (index->type & DICT_UNIQUE) { return(index->table->stat_n_rows); n_cols = dict_index_get_n_unique(index); n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong)); for (j = 0; j <= n_cols; j++) { n_diff[j] = 0; } /* We sample some pages in the index to get an estimate */ Loading @@ -2507,17 +2559,19 @@ btr_estimate_number_of_different_key_vals( btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); /* Count the number of different key values minus one on this index page: we subtract one because otherwise our algorithm would give a wrong estimate for an index where there is just one key value */ /* Count the number of different key values minus one for each prefix of the key on this index page: we subtract one because otherwise our algorithm would give a wrong estimate for an index where there is just one key value */ page = btr_cur_get_page(&cursor); rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); n_diff_in_page = 0; if (rec != page_get_supremum_rec(page)) { not_empty_flag = 1; } while (rec != page_get_supremum_rec(page) && page_rec_get_next(rec) Loading @@ -2528,30 +2582,30 @@ btr_estimate_number_of_different_key_vals( cmp_rec_rec_with_match(rec, page_rec_get_next(rec), index, &matched_fields, &matched_bytes); if (matched_fields < dict_index_get_n_ordering_defined_by_user( index)) { n_diff_in_page++; for (j = matched_fields + 1; j <= n_cols; j++) { n_diff[j]++; } rec = page_rec_get_next(rec); } n_diff += n_diff_in_page; total_n_recs += page_get_n_recs(page); mtr_commit(&mtr); } if (n_diff == 0) { /* We play safe and assume that there are just two different key values in the index */ /* If we saw k borders between different key values on BTR_KEY_VAL_ESTIMATE_N_PAGES leaf pages, we can estimate how many there will be in index->stat_n_leaf_pages */ return(2); for (j = 0; j <= n_cols; j++) { index->stat_n_diff_key_vals[j] = (n_diff[j] * index->stat_n_leaf_pages + BTR_KEY_VAL_ESTIMATE_N_PAGES - 1 + not_empty_flag) / BTR_KEY_VAL_ESTIMATE_N_PAGES; } return(index->table->stat_n_rows / (total_n_recs / n_diff)); mem_free(n_diff); } /*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/ Loading
innobase/btr/btr0pcur.c +52 −18 Original line number Diff line number Diff line Loading @@ -62,8 +62,10 @@ btr_pcur_free_for_mysql( /****************************************************************** The position of the cursor is stored by taking an initial segment of the record the cursor is positioned on, before, or after, and copying it to the cursor data structure. NOTE that the page where the cursor is positioned must not be empty! */ cursor data structure, or just setting a flag if the cursor id before the first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the page where the cursor is positioned must not be empty if the index tree is not totally empty! */ void btr_pcur_store_position( Loading Loading @@ -93,9 +95,21 @@ btr_pcur_store_position( ut_a(cursor->latch_mode != BTR_NO_LATCHES); if (page_get_n_recs(page) == 0) { /* It must be an empty index tree */ /* Cannot store position! */ btr_pcur_close(cursor); ut_a(btr_page_get_next(page, mtr) == FIL_NULL && btr_page_get_prev(page, mtr) == FIL_NULL); if (rec == page_get_supremum_rec(page)) { cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; cursor->old_stored = BTR_PCUR_OLD_STORED; return; } cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE; cursor->old_stored = BTR_PCUR_OLD_STORED; return; } Loading Loading @@ -140,13 +154,15 @@ btr_pcur_copy_stored_position( ut_memcpy((byte*)pcur_receive, (byte*)pcur_donate, sizeof(btr_pcur_t)); if (pcur_donate->old_rec_buf) { pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size); ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf, pcur_donate->buf_size); pcur_receive->old_rec = pcur_receive->old_rec_buf + (pcur_donate->old_rec - pcur_donate->old_rec_buf); } } /****************************************************************** Loading @@ -158,7 +174,9 @@ to the last record LESS OR EQUAL to the stored record; the last record LESS than the user record which was the successor of the page infimum; (3) cursor was positioned on the page supremum: restores to the first record GREATER than the user record which was the predecessor of the supremum. */ GREATER than the user record which was the predecessor of the supremum. (4) cursor was positioned before the first or after the last in an empty tree: restores to before first or after the last in the tree. */ ibool btr_pcur_restore_position( Loading @@ -177,17 +195,33 @@ btr_pcur_restore_position( dtuple_t* tuple; ulint mode; ulint old_mode; ibool from_left; mem_heap_t* heap; ut_a((cursor->pos_state == BTR_PCUR_WAS_POSITIONED) || (cursor->pos_state == BTR_PCUR_IS_POSITIONED)); ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED || cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { from_left = TRUE; } else { from_left = FALSE; } btr_cur_open_at_index_side(from_left, btr_pcur_get_btr_cur(cursor)->index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr); return(FALSE); } ut_a(cursor->old_rec); page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); if ((latch_mode == BTR_SEARCH_LEAF) || (latch_mode == BTR_MODIFY_LEAF)) { if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) { /* Try optimistic restoration */ if (buf_page_optimistic_get(latch_mode, page, Loading Loading @@ -242,16 +276,15 @@ btr_pcur_restore_position( /* Restore the old search mode */ cursor->search_mode = old_mode; if ((cursor->rel_pos == BTR_PCUR_ON) if (cursor->rel_pos == BTR_PCUR_ON && btr_pcur_is_on_user_rec(cursor, mtr) && (0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor)))) { && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor))) { /* We have to store the NEW value for the modify clock, since the cursor can now be on a different page! */ cursor->modify_clock = buf_frame_get_modify_clock( buf_frame_align( btr_pcur_get_rec(cursor))); buf_frame_align(btr_pcur_get_rec(cursor))); mem_heap_free(heap); return(TRUE); Loading Loading @@ -366,6 +399,7 @@ btr_pcur_move_backward_from_page( latch_mode2 = BTR_MODIFY_PREV; } else { latch_mode2 = 0; /* To eliminate compiler warning */ ut_error; } Loading
innobase/btr/btr0sea.c +0 −2 Original line number Diff line number Diff line Loading @@ -680,9 +680,7 @@ btr_search_guess_on_hash( success = buf_page_get_known_nowait(latch_mode, page, BUF_MAKE_YOUNG, #ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, #endif mtr); rw_lock_s_unlock(&btr_search_latch); Loading
innobase/buf/buf0buf.c +151 −50 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ Created 11/5/1995 Heikki Tuuri #include "ibuf0ibuf.h" #include "dict0dict.h" #include "log0recv.h" #include "trx0undo.h" #include "srv0srv.h" /* IMPLEMENTATION OF THE BUFFER POOL Loading Loading @@ -240,6 +242,11 @@ buf_page_is_corrupted( checksum = buf_calc_page_checksum(read_buf); /* Note that InnoDB initializes empty pages to zero, and early versions of InnoDB did not store page checksum to the 4 most significant bytes of the page lsn field at the end of a page: */ if ((mach_read_from_4(read_buf + FIL_PAGE_LSN + 4) != mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN + 4)) Loading @@ -256,6 +263,71 @@ buf_page_is_corrupted( return(FALSE); } /************************************************************************ Prints a page to stderr. */ void buf_page_print( /*===========*/ byte* read_buf) /* in: a database page */ { dict_index_t* index; ulint checksum; char* buf; buf = mem_alloc(4 * UNIV_PAGE_SIZE); ut_sprintf_buf(buf, read_buf, UNIV_PAGE_SIZE); fprintf(stderr, "InnoDB: Page dump in ascii and hex (%lu bytes):\n%s", UNIV_PAGE_SIZE, buf); fprintf(stderr, "InnoDB: End of page dump\n"); mem_free(buf); checksum = buf_calc_page_checksum(read_buf); fprintf(stderr, "InnoDB: Page checksum %lu stored checksum %lu\n", checksum, mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN)); fprintf(stderr, "InnoDB: Page lsn %lu %lu, low 4 bytes of lsn at page end %lu\n", mach_read_from_4(read_buf + FIL_PAGE_LSN), mach_read_from_4(read_buf + FIL_PAGE_LSN + 4), mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN + 4)); if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT) { fprintf(stderr, "InnoDB: Page may be an insert undo log page\n"); } else if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE) { fprintf(stderr, "InnoDB: Page may be an update undo log page\n"); } if (fil_page_get_type(read_buf) == FIL_PAGE_INDEX) { fprintf(stderr, "InnoDB: Page may be an index page "); fprintf(stderr, "where index id is %lu %lu\n", ut_dulint_get_high(btr_page_get_index_id(read_buf)), ut_dulint_get_low(btr_page_get_index_id(read_buf))); index = dict_index_find_on_id_low( btr_page_get_index_id(read_buf)); if (index) { fprintf(stderr, "InnoDB: and table %s index %s\n", index->table_name, index->name); } } } /************************************************************************ Initializes a buffer control block when the buf_pool is created. */ static Loading Loading @@ -334,6 +406,8 @@ buf_pool_create( frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE); buf_pool->frame_zero = frame; buf_pool->high_end = frame + UNIV_PAGE_SIZE * curr_size; /* Init block structs and assign frames for them */ for (i = 0; i < max_size; i++) { Loading @@ -345,6 +419,9 @@ buf_pool_create( buf_pool->page_hash = hash_create(2 * max_size); buf_pool->n_pend_reads = 0; buf_pool->last_printout_time = time(NULL); buf_pool->n_pages_read = 0; buf_pool->n_pages_written = 0; buf_pool->n_pages_created = 0; Loading @@ -352,6 +429,8 @@ buf_pool_create( buf_pool->n_page_gets = 0; buf_pool->n_page_gets_old = 0; buf_pool->n_pages_read_old = 0; buf_pool->n_pages_written_old = 0; buf_pool->n_pages_created_old = 0; /* 2. Initialize flushing fields ---------------------------- */ Loading Loading @@ -379,6 +458,10 @@ buf_pool_create( for (i = 0; i < curr_size; i++) { block = buf_pool_get_nth_block(buf_pool, i); /* Wipe contents of page to eliminate a Purify warning */ memset(block->frame, '\0', UNIV_PAGE_SIZE); UT_LIST_ADD_FIRST(free, buf_pool->free, block); } Loading Loading @@ -650,10 +733,8 @@ buf_page_get_gen( buf_frame_t* guess, /* in: guessed frame or NULL */ ulint mode, /* in: BUF_GET, BUF_GET_IF_IN_POOL, BUF_GET_NO_LATCH, BUF_GET_NOWAIT */ #ifdef UNIV_SYNC_DEBUG char* file, /* in: file name */ ulint line, /* in: line where called */ #endif mtr_t* mtr) /* in: mini-transaction */ { buf_block_t* block; Loading Loading @@ -759,19 +840,13 @@ buf_page_get_gen( if (mode == BUF_GET_NOWAIT) { if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG ,file, line #endif ); success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { ut_ad(rw_latch == RW_X_LATCH); success = rw_lock_x_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG ,file, line #endif ); success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading @@ -796,18 +871,12 @@ buf_page_get_gen( fix_type = MTR_MEMO_BUF_FIX; } else if (rw_latch == RW_S_LATCH) { rw_lock_s_lock_func(&(block->lock) #ifdef UNIV_SYNC_DEBUG ,0, file, line #endif ); rw_lock_s_lock_func(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { rw_lock_x_lock_func(&(block->lock), 0 #ifdef UNIV_SYNC_DEBUG , file, line #endif ); rw_lock_x_lock_func(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading Loading @@ -838,10 +907,8 @@ buf_page_optimistic_get_func( buf_frame_t* guess, /* in: guessed frame */ dulint modify_clock,/* in: modify clock value if mode is ..._GUESS_ON_CLOCK */ #ifdef UNIV_SYNC_DEBUG char* file, /* in: file name */ ulint line, /* in: line where called */ #endif mtr_t* mtr) /* in: mini-transaction */ { buf_block_t* block; Loading Loading @@ -883,18 +950,12 @@ buf_page_optimistic_get_func( ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset)); if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { success = rw_lock_x_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading Loading @@ -971,10 +1032,8 @@ buf_page_get_known_nowait( ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */ buf_frame_t* guess, /* in: the known page frame */ ulint mode, /* in: BUF_MAKE_YOUNG or BUF_KEEP_OLD */ #ifdef UNIV_SYNC_DEBUG char* file, /* in: file name */ ulint line, /* in: line where called */ #endif mtr_t* mtr) /* in: mini-transaction */ { buf_block_t* block; Loading Loading @@ -1017,18 +1076,12 @@ buf_page_get_known_nowait( ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_s_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { success = rw_lock_x_lock_func_nowait(&(block->lock) #ifdef UNIV_SYNC_DEBUG , file, line #endif ); success = rw_lock_x_lock_func_nowait(&(block->lock), file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } Loading Loading @@ -1315,13 +1368,30 @@ buf_page_io_complete( to the 4 upper bytes of the page end lsn field */ if (buf_page_is_corrupted(block->frame)) { fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, "InnoDB: You may have to recover from a backup.\n"); buf_page_print(block->frame); fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, "InnoDB: You may have to recover from a backup.\n"); fprintf(stderr, "InnoDB: It is also possible that your operating\n" "InnoDB: system has corrupted its own file cache\n" "InnoDB: and rebooting your computer removes the\n" "InnoDB: error.\n"); if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { exit(1); } } if (recv_recovery_is_on()) { recv_recover_page(TRUE, block->frame, block->space, Loading Loading @@ -1622,6 +1692,19 @@ buf_print(void) ut_a(buf_validate()); } /************************************************************************* Returns the number of pending buf pool ios. */ ulint buf_get_n_pending_ios(void) /*=======================*/ { return(buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU] + buf_pool->n_flush[BUF_FLUSH_LIST] + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); } /************************************************************************* Prints info of the buffer i/o. */ Loading @@ -1629,6 +1712,8 @@ void buf_print_io(void) /*==============*/ { time_t current_time; double time_elapsed; ulint size; ut_ad(buf_pool); Loading @@ -1637,11 +1722,11 @@ buf_print_io(void) mutex_enter(&(buf_pool->mutex)); printf("LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU)); 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", UT_LIST_GET_LEN(buf_pool->flush_list)); printf("Buffer pool size in pages %lu\n", size); printf("Buffer pool size %lu\n", size); printf("Pending reads %lu \n", buf_pool->n_pend_reads); Loading @@ -1650,9 +1735,21 @@ buf_print_io(void) buf_pool->n_flush[BUF_FLUSH_LIST], buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); current_time = time(NULL); time_elapsed = difftime(current_time, buf_pool->last_printout_time); buf_pool->last_printout_time = current_time; printf("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_pool->n_pages_read - buf_pool->n_pages_read_old) / time_elapsed, (buf_pool->n_pages_created - buf_pool->n_pages_created_old) / time_elapsed, (buf_pool->n_pages_written - buf_pool->n_pages_written_old) / time_elapsed); if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) { printf("Buffer pool hit rate %lu / 1000\n", Loading @@ -1660,10 +1757,14 @@ buf_print_io(void) - ((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_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; mutex_exit(&(buf_pool->mutex)); } Loading