起動プロセス(5) buf_pool_init関数

innobase_start_or_create_for_mysql関数の中で呼び出される。バッファプールがどうなっているのかは、この関数を読めば分かる。



buf0buf.cにて。buf_poolを初期化する。

max_size、curr_size、n_framesの値はinnodb_buffer_pool_sizeをPageサイズで割った値と同じのようだ。block=frame=Pageという図式で捉えてよい(?)

534行目にて、buf_pool構造体のメモリ割り当て。

buf_pool = mem_alloc(sizeof(buf_pool_t));

その後、buf_pool->mutexの初期化を行ってから、mutex_enterして、571行目。

buf_pool->frame_mem = os_mem_alloc_large(
            UNIV_PAGE_SIZE * (n_frames + 1),
            TRUE, FALSE);

ここで、innodb_buffer_pool_sizeで指定したサイズのメモリを割り当て。先頭アドレスをbuf_pool- >frame_memに格納。第3引数TRUEにより、割り当てた領域はゼロクリアされる。第4引数は割り当てに失敗したときにmysqldを終了すべきか否かの指示。

割り当てサイズ実際には以下のようになっている。

innodb_buffer_pool_size + 1page分 + ut_mem_block_tのサイズ(16バイト)

呼び出し先のut_malloc_low関数にてmallocが行われる。

ret = malloc(n + sizeof(ut_mem_block_t));
((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N;
return((void*)((byte*)ret + sizeof(ut_mem_block_t)));

mallocされた領域の先頭にはut_mem_block_t構造体があるが、返されるアドレスはこのサイズ分進めたものが返される。

581行目にて、ブロックのためのメモリ割り当て。

buf_pool->blocks = ut_malloc(sizeof(buf_block_t) * max_size);

これで「ブロック=各Pageに割り当てられる制御用の構造体」ということが確定的に。

ちなみにbuf_pool_tのサイズは304バイト、buf_block_tのサイズは344バイト。

595行目。innodb_buffer_poolの先頭アドレスをUNIV_PAGE_SIZEで割り切れる値に切り上げている。

frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE);

os_mem_alloc_large関数に引数を渡すときに+1をしていたのはこのためか。

frame_zeroは1番目のフレームの先頭アドレス。high_endは最後のフレームの終端アドレス+1。

buf_pool->frame_zero = frame;
buf_pool->high_end = frame + UNIV_PAGE_SIZE * n_frames;

612行目。blocks_of_framesはbuf_block_tへのポインタのポインタ。

buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames);

624行目。全てのページを初期化。

for (i = 0; i < max_size; i++) {
    block = buf_pool_get_nth_block(buf_pool, i);
    if (i < n_frames) {
        frame = buf_pool->frame_zero + i * UNIV_PAGE_SIZE;
        *(buf_pool->blocks_of_frames + i) = block;
    } else {
        frame = NULL;
    }
    buf_block_init(block, frame);
    ...
}

buf_pool_get_nth_block関数は、第一引数のbuf_poolから第2引数で指定された番目のblockを返す関数。

645行目。

buf_pool->page_hash = hash_create(2 * max_size);

page_hashは各ページへのハッシュ値

hash_table_t*   page_hash;  /* hash table of the file pages */

687行目。初期処理なので全てのブロックをフリーリストに追加。

/* Add control blocks to the free list */
UT_LIST_INIT(buf_pool->free);
for (i = 0; i < curr_size; i++) {
    block = buf_pool_get_nth_block(buf_pool, i);
    ...
    UT_LIST_ADD_LAST(free, buf_pool->free, block);
    block->in_free_list = TRUE;
}

716行目。最後に検索用のbtreeらしきものを作成している。デフォルト(buffer pool=8MB)の時、この関数の引数は32768になっている。

btr_search_sys_create(curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64);