/********************************************************************* This function should be called before reserving any btr search mutex, if the intended operation might add nodes to the search system hash table. Because of the latching order, once we have reserved the btr search system latch, we cannot allocate a free frame from the buffer pool. Checks that there is a free buffer frame allocated for hash table heap in the btr search system. If not, allocates a free frames for the heap. This check makes it probable that, when have reserved the btr search system latch and we need to allocate a new node to the hash table, it will succeed. However, the check will not guarantee success. */ static void btr_search_check_free_space_in_heap(void) /*=====================================*/ { buf_frame_t* frame; hash_table_t* table; mem_heap_t* heap; #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ table = btr_search_sys->hash_index; heap = table->heap; /* Note that we peek the value of heap->free_block without reserving the latch: this is ok, because we will not guarantee that there will be enough free space in the hash table. */ if (heap->free_block == NULL) { frame = buf_frame_alloc(); rw_lock_x_lock(&btr_search_latch); if (heap->free_block == NULL) { heap->free_block = frame; } else { buf_frame_free(frame); } rw_lock_x_unlock(&btr_search_latch); } }
mem_block_t* mem_heap_create_block( /*==================*/ /* out, own: memory heap block, NULL if did not succeed */ mem_heap_t* heap, /* in: memory heap or NULL if first block should be created */ ulint n, /* in: number of bytes needed for user data, or if init_block is not NULL, its size in bytes */ void* init_block, /* in: init block in fast create, type must be MEM_HEAP_DYNAMIC */ ulint type, /* in: type of heap: MEM_HEAP_DYNAMIC or MEM_HEAP_BUFFER */ const char* file_name,/* in: file name where created */ ulint line) /* in: line where created */ { mem_block_t* block; ulint len; ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER) || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH)); if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) { mem_analyze_corruption((byte*)heap); } /* In dynamic allocation, calculate the size: block header + data. */ if (init_block != NULL) { ut_ad(type == MEM_HEAP_DYNAMIC); ut_ad(n > MEM_BLOCK_START_SIZE + MEM_BLOCK_HEADER_SIZE); len = n; block = init_block; } else if (type == MEM_HEAP_DYNAMIC) { len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n); block = mem_area_alloc(len, mem_comm_pool); } else { ut_ad(n <= MEM_MAX_ALLOC_IN_BUF); len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n); if (len < UNIV_PAGE_SIZE / 2) { block = mem_area_alloc(len, mem_comm_pool); } else { len = UNIV_PAGE_SIZE; if ((type & MEM_HEAP_BTR_SEARCH) && heap) { /* We cannot allocate the block from the buffer pool, but must get the free block from the heap header free block field */ block = (mem_block_t*)heap->free_block; heap->free_block = NULL; } else { block = (mem_block_t*)buf_frame_alloc(); } } } if (block == NULL) { return(NULL); } block->magic_n = MEM_BLOCK_MAGIC_N; ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name)); block->line = line; #ifdef MEM_PERIODIC_CHECK mem_pool_mutex_enter(); if (!mem_block_list_inited) { mem_block_list_inited = TRUE; UT_LIST_INIT(mem_block_list); } UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block); mem_pool_mutex_exit(); #endif mem_block_set_len(block, len); mem_block_set_type(block, type); mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE); mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE); block->free_block = NULL; block->init_block = (init_block != NULL); ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len); return(block); }