/***********************************************************//** Moves the query threads in the sig reply wait list of trx to the SUSPENDED state. */ static void trx_sig_reply_wait_to_suspended( /*============================*/ trx_t* trx) /*!< in: transaction */ { trx_sig_t* sig; que_thr_t* thr; ut_ad(mutex_own(&kernel_mutex)); sig = UT_LIST_GET_FIRST(trx->reply_signals); while (sig != NULL) { thr = sig->receiver; ut_ad(thr->state == QUE_THR_SIG_REPLY_WAIT); thr->state = QUE_THR_SUSPENDED; sig->receiver = NULL; UT_LIST_REMOVE(reply_signals, trx->reply_signals, sig); sig = UT_LIST_GET_FIRST(trx->reply_signals); } }
/*********************************************************************** Initializes the old blocks pointer in the LRU list. This function should be called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */ static void buf_LRU_old_init(void) /*==================*/ { buf_block_t* block; ut_ad(mutex_own(&(buf_pool->mutex))); ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN); /* We first initialize all blocks in the LRU list as old and then use the adjust function to move the LRU_old pointer to the right position */ block = UT_LIST_GET_FIRST(buf_pool->LRU); while (block != NULL) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->in_LRU_list); block->old = TRUE; block = UT_LIST_GET_NEXT(LRU, block); } buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU); buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU); buf_LRU_old_adjust_len(); }
void OSEventThread::firePending() { TRACE("~~~~ +firePending ~~~~\n"); event_req_t * ev; while (ev = UT_LIST_GET_FIRST(mPendingList)) { UT_LIST_REMOVE(activeNode,mPendingList,ev); try { ev->func(ev->fd, OSEventContext::EV_RE, ev->param); ev->status = 0; } catch (...) { ERR("Falut req = %p\n",ev); ASSERT_C(0); } } event_timer_t * tev; while (tev = UT_LIST_GET_FIRST(mTimeoutList)) { UT_LIST_REMOVE(activeNode,mTimeoutList,tev); try { tev->func(tev->timeout, tev->param); tev->status = 0; } catch (...) { ERR("Falut timer = %p\n",tev); ASSERT_C(0); } } TRACE("~~~~ -firePending ~~~~\n"); }
/******************************************************************//** Frees the memory allocated dynamically AFTER parsing phase for variables etc. in the symbol table. Does not free the mem heap where the table was originally created. Frees also SQL explicit cursor definitions. */ UNIV_INTERN void sym_tab_free_private( /*=================*/ sym_tab_t* sym_tab) /*!< in, own: symbol table */ { sym_node_t* sym; func_node_t* func; sym = UT_LIST_GET_FIRST(sym_tab->sym_list); while (sym) { eval_node_free_val_buf(sym); if (sym->prefetch_buf) { sel_col_prefetch_buf_free(sym->prefetch_buf); } if (sym->cursor_def) { que_graph_free_recursive(sym->cursor_def); } sym = UT_LIST_GET_NEXT(sym_list, sym); } func = UT_LIST_GET_FIRST(sym_tab->func_node_list); while (func) { eval_node_free_val_buf(func); func = UT_LIST_GET_NEXT(func_node_list, func); } }
/*********************************************************//** Frees created events and OS 'slow' mutexes. */ UNIV_INTERN void os_sync_free(void) /*==============*/ { os_event_t event; os_mutex_t mutex; os_sync_free_called = TRUE; event = UT_LIST_GET_FIRST(os_event_list); while (event) { os_event_free(event); event = UT_LIST_GET_FIRST(os_event_list); } mutex = UT_LIST_GET_FIRST(os_mutex_list); while (mutex) { if (mutex == os_sync_mutex) { /* Set the flag to FALSE so that we do not try to reserve os_sync_mutex any more in remaining freeing operations in shutdown */ os_sync_mutex_inited = FALSE; } os_mutex_free(mutex); mutex = UT_LIST_GET_FIRST(os_mutex_list); } os_sync_free_called = FALSE; }
/***************************************************************//** Prints debug info of currently locked rw-locks. */ UNIV_INTERN void rw_lock_list_print_info( /*====================*/ FILE* file) /*!< in: file where to print */ { rw_lock_t* lock; ulint count = 0; rw_lock_debug_t* info; mutex_enter(&rw_lock_list_mutex); fputs("-------------\n" "RW-LATCH INFO\n" "-------------\n", file); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { count++; #ifndef INNODB_RW_LOCKS_USE_ATOMICS mutex_enter(&(lock->mutex)); #endif if (lock->lock_word != X_LOCK_DECR) { fprintf(file, "RW-LOCK: %p ", (void*) lock); if (rw_lock_get_waiters(lock)) { fputs(" Waiters for the lock exist\n", file); } else { putc('\n', file); } rw_lock_debug_mutex_enter(); info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(file, info); info = UT_LIST_GET_NEXT(list, info); } rw_lock_debug_mutex_exit(); } #ifndef INNODB_RW_LOCKS_USE_ATOMICS mutex_exit(&(lock->mutex)); #endif lock = UT_LIST_GET_NEXT(list, lock); } fprintf(file, "Total number of rw-locks %ld\n", count); mutex_exit(&rw_lock_list_mutex); }
void rw_lock_list_print_info(void) /*=========================*/ { #ifndef UNIV_SYNC_DEBUG #else rw_lock_t* lock; ulint count = 0; rw_lock_debug_t* info; mutex_enter(&rw_lock_list_mutex); printf("-------------\n"); printf("RW-LATCH INFO\n"); printf("-------------\n"); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { count++; mutex_enter(&(lock->mutex)); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0) || (rw_lock_get_waiters(lock) != 0)) { printf("RW-LOCK: %lx ", (ulint)lock); if (rw_lock_get_waiters(lock)) { printf(" Waiters for the lock exist\n"); } else { printf("\n"); } info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } } mutex_exit(&(lock->mutex)); lock = UT_LIST_GET_NEXT(list, lock); } printf("Total number of rw-locks %ld\n", count); mutex_exit(&rw_lock_list_mutex); #endif }
void rw_lock_list_print_info( /*====================*/ FILE* file) /* in: file where to print */ { rw_lock_t* lock; ulint count = 0; rw_lock_debug_t* info; mutex_enter(&rw_lock_list_mutex); fputs("-------------\n" "RW-LATCH INFO\n" "-------------\n", file); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { count++; mutex_enter(&(lock->mutex)); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0) || (rw_lock_get_waiters(lock) != 0)) { fprintf(file, "RW-LOCK: %p ", (void*) lock); if (rw_lock_get_waiters(lock)) { fputs(" Waiters for the lock exist\n", file); } else { putc('\n', file); } info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } } mutex_exit(&(lock->mutex)); lock = UT_LIST_GET_NEXT(list, lock); } fprintf(file, "Total number of rw-locks %ld\n", count); mutex_exit(&rw_lock_list_mutex); }
/******************************************************************//** Assigns a rollback segment to a transaction in a round-robin fashion. Skips the SYSTEM rollback segment if another is available. @return assigned rollback segment id */ UNIV_INLINE ulint trx_assign_rseg(void) /*=================*/ { trx_rseg_t* rseg = trx_sys->latest_rseg; ut_ad(mutex_own(&kernel_mutex)); loop: /* Get next rseg in a round-robin fashion */ rseg = UT_LIST_GET_NEXT(rseg_list, rseg); if (rseg == NULL) { rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); } /* If it is the SYSTEM rollback segment, and there exist others, skip it */ if ((rseg->id == TRX_SYS_SYSTEM_RSEG_ID) && (UT_LIST_GET_LEN(trx_sys->rseg_list) > 1)) { goto loop; } trx_sys->latest_rseg = rseg; return(rseg->id); }
/********************************************************************** Validates the flush list. */ static ibool buf_flush_validate_low(void) /*========================*/ /* out: TRUE if ok */ { buf_block_t* block; dulint om; UT_LIST_VALIDATE(flush_list, buf_block_t, buf_pool->flush_list); block = UT_LIST_GET_FIRST(buf_pool->flush_list); while (block != NULL) { om = block->oldest_modification; ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(ut_dulint_cmp(om, ut_dulint_zero) > 0); block = UT_LIST_GET_NEXT(flush_list, block); if (block) { ut_a(ut_dulint_cmp(om, block->oldest_modification) >= 0); } } return(TRUE); }
ulint rw_lock_n_locked(void) /*==================*/ { #ifndef UNIV_SYNC_DEBUG printf( "Sorry, cannot give rw-lock info in non-debug version!\n"); ut_error; return(0); #else rw_lock_t* lock; ulint count = 0; mutex_enter(&rw_lock_list_mutex); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { mutex_enter(rw_lock_get_mutex(lock)); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0)) { count++; } mutex_exit(rw_lock_get_mutex(lock)); lock = UT_LIST_GET_NEXT(list, lock); } mutex_exit(&rw_lock_list_mutex); return(count); #endif }
void rw_lock_print( /*==========*/ rw_lock_t* lock) /* in: rw-lock */ { #ifndef UNIV_SYNC_DEBUG printf( "Sorry, cannot give rw-lock info in non-debug version!\n"); #else ulint count = 0; rw_lock_debug_t* info; printf("-------------\n"); printf("RW-LATCH INFO\n"); printf("RW-LATCH: %lx ", (ulint)lock); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0) || (rw_lock_get_waiters(lock) != 0)) { if (rw_lock_get_waiters(lock)) { printf(" Waiters for the lock exist\n"); } else { printf("\n"); } info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } } #endif }
void OSEventThread::processReadReadies(fd_set * rfds, int n) { TRACE("~~~~ +processReadReadies (%d) ~~~~\n", n); OSMutexLocker _locker(&mMutex); event_req_t* rev = UT_LIST_GET_FIRST(mWatchList); event_req_t* next; while((NULL != rev) && (n > 0)){ next = UT_LIST_GET_NEXT(watchNode,rev); if (FD_ISSET(rev->fd, rfds)) { rev->status = 1; UT_LIST_ADD_FIRST(activeNode,mPendingList,rev); if (rev->persist == false) { removeWatch(rev); DecreaseWatchNum(); } n--; } rev = next; } TRACE("~~~~ -processReadReadies (%d) ~~~~\n", n); }
void OSEventThread::processTimeouts() { TRACE("~~~~ +processTimeouts ~~~~\n"); ULONG now = OS::GetTickCount(); OSMutexLocker _locker(&mMutex); event_timer_t * tev = UT_LIST_GET_FIRST(mTimerList); event_timer_t * next; // walk list, see if now >= ev->timeout for any events TRACE("~~~~ Looking for timers <= %lu ~~~~\n", (unsigned long)now); while ((tev) && (now > tev->timeout)) { // Timer expired TRACE("~~~~ firing timer ~~~~\n"); next = UT_LIST_GET_NEXT(watchNode,tev); tev->status = 1; UT_LIST_ADD_FIRST(activeNode,mTimeoutList,tev); if (tev->persist == false){ UT_LIST_REMOVE(watchNode,mTimerList,tev); //if(tev != &mIdleTimer) DecreaseWatchNum(); } tev = next; } TRACE("~~~~ -processTimeouts ~~~~\n"); }
/****************************************************************//** Inserts the trx handle in the trx system trx list in the right position. The list is sorted on the trx id so that the biggest id is at the list start. This function is used at the database startup to insert incomplete transactions to the list. */ static void trx_list_insert_ordered( /*====================*/ trx_t* trx) /*!< in: trx handle */ { trx_t* trx2; ut_ad(mutex_own(&kernel_mutex)); trx2 = UT_LIST_GET_FIRST(trx_sys->trx_list); while (trx2 != NULL) { if (ut_dulint_cmp(trx->id, trx2->id) >= 0) { ut_ad(ut_dulint_cmp(trx->id, trx2->id) == 1); break; } trx2 = UT_LIST_GET_NEXT(trx_list, trx2); } if (trx2 != NULL) { trx2 = UT_LIST_GET_PREV(trx_list, trx2); if (trx2 == NULL) { UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx); } else { UT_LIST_INSERT_AFTER(trx_list, trx_sys->trx_list, trx2, trx); } } else { UT_LIST_ADD_LAST(trx_list, trx_sys->trx_list, trx); } }
/***************************************************************//** Returns the number of currently locked rw-locks. Works only in the debug version. @return number of locked rw-locks */ UNIV_INTERN ulint rw_lock_n_locked(void) /*==================*/ { rw_lock_t* lock; ulint count = 0; mutex_enter(&rw_lock_list_mutex); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { if (lock->lock_word != X_LOCK_DECR) { count++; } lock = UT_LIST_GET_NEXT(list, lock); } mutex_exit(&rw_lock_list_mutex); return(count); }
ulint buf_LRU_get_recent_limit(void) /*==========================*/ /* out: the limit; zero if could not determine it */ { buf_block_t* block; ulint len; ulint limit; mutex_enter(&(buf_pool->mutex)); len = UT_LIST_GET_LEN(buf_pool->LRU); if (len < BUF_LRU_OLD_MIN_LEN) { /* The LRU list is too short to do read-ahead */ mutex_exit(&(buf_pool->mutex)); return(0); } block = UT_LIST_GET_FIRST(buf_pool->LRU); limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO; mutex_exit(&(buf_pool->mutex)); return(limit); }
/**********************************************************************//** Frees in shutdown all allocated memory not freed yet. */ UNIV_INTERN void ut_free_all_mem(void) /*=================*/ { ut_mem_block_t* block; ut_a(ut_mem_block_list_inited); ut_mem_block_list_inited = FALSE; os_fast_mutex_free(&ut_list_mutex); while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) { ut_a(block->magic_n == UT_MEM_MAGIC_N); ut_a(ut_total_allocated_memory >= block->size); ut_total_allocated_memory -= block->size; UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block); free(block); } if (ut_total_allocated_memory != 0) { fprintf(stderr, "InnoDB: Warning: after shutdown" " total allocated memory is %lu\n", (ulong) ut_total_allocated_memory); } ut_mem_block_list_inited = FALSE; }
/*******************************************************************//** Frees savepoint structs starting from savep, if savep == NULL then free all savepoints. */ UNIV_INTERN void trx_roll_savepoints_free( /*=====================*/ trx_t* trx, /*!< in: transaction handle */ trx_named_savept_t* savep) /*!< in: free all savepoints > this one; if this is NULL, free all savepoints of trx */ { trx_named_savept_t* next_savep; if (savep == NULL) { savep = UT_LIST_GET_FIRST(trx->trx_savepoints); } else { savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } while (savep != NULL) { next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep); trx_roll_savepoint_free(trx, savep); savep = next_savep; } }
ulint rw_lock_n_locked(void) /*==================*/ { rw_lock_t* lock; ulint count = 0; mutex_enter(&rw_lock_list_mutex); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { mutex_enter(rw_lock_get_mutex(lock)); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0)) { count++; } mutex_exit(rw_lock_get_mutex(lock)); lock = UT_LIST_GET_NEXT(list, lock); } mutex_exit(&rw_lock_list_mutex); return(count); }
void rw_lock_print( /*==========*/ rw_lock_t* lock) /* in: rw-lock */ { rw_lock_debug_t* info; fprintf(stderr, "-------------\n" "RW-LATCH INFO\n" "RW-LATCH: %p ", (void*) lock); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0) || (rw_lock_get_waiters(lock) != 0)) { if (rw_lock_get_waiters(lock)) { fputs(" Waiters for the lock exist\n", stderr); } else { putc('\n', stderr); } info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } } }
ibool rw_lock_own( /*========*/ /* out: TRUE if locked */ rw_lock_t* lock, /* in: rw-lock */ ulint lock_type) /* in: lock type: RW_LOCK_SHARED, RW_LOCK_EX */ { rw_lock_debug_t* info; ut_ad(lock); ut_ad(rw_lock_validate(lock)); mutex_enter(&(lock->mutex)); info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { if (os_thread_eq(info->thread_id, os_thread_get_curr_id()) && (info->pass == 0) && (info->lock_type == lock_type)) { mutex_exit(&(lock->mutex)); /* Found! */ return(TRUE); } info = UT_LIST_GET_NEXT(list, info); } mutex_exit(&(lock->mutex)); return(FALSE); }
void buf_flush_insert_sorted_into_flush_list( /*====================================*/ buf_block_t* block) /* in: block which is modified */ { buf_block_t* prev_b; buf_block_t* b; ut_ad(mutex_own(&(buf_pool->mutex))); prev_b = NULL; b = UT_LIST_GET_FIRST(buf_pool->flush_list); while (b && (ut_dulint_cmp(b->oldest_modification, block->oldest_modification) > 0)) { prev_b = b; b = UT_LIST_GET_NEXT(flush_list, b); } if (prev_b == NULL) { UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block); } else { UT_LIST_INSERT_AFTER(flush_list, buf_pool->flush_list, prev_b, block); } ut_ad(buf_flush_validate_low()); }
void buf_flush_insert_into_flush_list( /*=============================*/ buf_block_t* block) /* in: block which is modified */ { ut_ad(mutex_own(&(buf_pool->mutex))); ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL) || (ut_dulint_cmp((UT_LIST_GET_FIRST(buf_pool->flush_list)) ->oldest_modification, block->oldest_modification) <= 0)); UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block); ut_ad(buf_flush_validate_low()); }
/*******************************************************************//** Rolls back a transaction back to a named savepoint. Modifications after the savepoint are undone but InnoDB does NOT release the corresponding locks which are stored in memory. If a lock is 'implicit', that is, a new inserted row holds a lock where the lock information is carried by the trx id stored in the row, these locks are naturally released in the rollback. Savepoints which were set after this savepoint are deleted. @return if no savepoint of the name found then DB_NO_SAVEPOINT, otherwise DB_SUCCESS */ UNIV_INTERN ulint trx_rollback_to_savepoint_for_mysql( /*================================*/ trx_t* trx, /*!< in: transaction handle */ const char* savepoint_name, /*!< in: savepoint name */ ib_int64_t* mysql_binlog_cache_pos) /*!< out: the MySQL binlog cache position corresponding to this savepoint; MySQL needs this information to remove the binlog entries of the queries executed after the savepoint */ { trx_named_savept_t* savep; ulint err; savep = UT_LIST_GET_FIRST(trx->trx_savepoints); while (savep != NULL) { if (0 == ut_strcmp(savep->name, savepoint_name)) { /* Found */ break; } savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } if (savep == NULL) { return(DB_NO_SAVEPOINT); } if (trx->conc_state == TRX_NOT_STARTED) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: transaction has a savepoint ", stderr); ut_print_name(stderr, trx, FALSE, savep->name); fputs(" though it is not started\n", stderr); return(DB_ERROR); } /* We can now free all savepoints strictly later than this one */ trx_roll_savepoints_free(trx, savep); *mysql_binlog_cache_pos = savep->mysql_binlog_cache_pos; trx->op_info = "rollback to a savepoint"; err = trx_general_rollback_for_mysql(trx, &savep->savept); /* Store the current undo_no of the transaction so that we know where to roll back if we have to roll back the next SQL statement: */ trx_mark_sql_stat_end(trx); trx->op_info = ""; return(err); }
void buf_LRU_print(void) /*===============*/ { buf_block_t* block; buf_frame_t* frame; ulint len; ut_ad(buf_pool); mutex_enter(&(buf_pool->mutex)); fprintf(stderr, "Pool ulint clock %lu\n", (ulong) buf_pool->ulint_clock); block = UT_LIST_GET_FIRST(buf_pool->LRU); len = 0; while (block != NULL) { fprintf(stderr, "BLOCK %lu ", (ulong) block->offset); if (block->old) { fputs("old ", stderr); } if (block->buf_fix_count) { fprintf(stderr, "buffix count %lu ", (ulong) block->buf_fix_count); } if (block->io_fix) { fprintf(stderr, "io_fix %lu ", (ulong) block->io_fix); } if (ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) { fputs("modif. ", stderr); } frame = buf_block_get_frame(block); fprintf(stderr, "LRU pos %lu type %lu index id %lu ", (ulong) block->LRU_position, (ulong) fil_page_get_type(frame), (ulong) ut_dulint_get_low (btr_page_get_index_id(frame))); block = UT_LIST_GET_NEXT(LRU, block); if (++len == 10) { len = 0; putc('\n', stderr); } } mutex_exit(&(buf_pool->mutex)); }
/***************************************************************//** Creates an index tree for the index if it is not a member of a cluster. @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ static ulint dict_create_index_tree_step( /*========================*/ ind_node_t* node) /*!< in: index create node */ { dict_index_t* index; dict_table_t* sys_indexes; dict_table_t* table; dtuple_t* search_tuple; ulint zip_size; btr_pcur_t pcur; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); index = node->index; table = node->table; sys_indexes = dict_sys->sys_indexes; /* Run a mini-transaction in which the index tree is allocated for the index and its root address is written to the index entry in sys_indexes */ mtr_start(&mtr); search_tuple = dict_create_search_tuple(node->ind_row, node->heap); btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes), search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF, &pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr); zip_size = dict_table_zip_size(index->table); node->page_no = btr_create(index->type, index->space, zip_size, index->id, index, &mtr); /* printf("Created a new index tree in space %lu root page %lu\n", index->space, index->page_no); */ page_rec_write_index_page_no(btr_pcur_get_rec(&pcur), DICT_SYS_INDEXES_PAGE_NO_FIELD, node->page_no, &mtr); btr_pcur_close(&pcur); mtr_commit(&mtr); if (node->page_no == FIL_NULL) { return(DB_OUT_OF_FILE_SPACE); } return(DB_SUCCESS); }
/***********************************************************************//** Free's an instance of the rollback segment in memory. */ UNIV_INTERN void trx_rseg_mem_free( /*==============*/ trx_rseg_t* rseg) /* in, own: instance to free */ { trx_undo_t* undo; mutex_free(&rseg->mutex); if (!srv_apply_log_only) { /* There can't be any active transactions. */ ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0); ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0); } undo = UT_LIST_GET_FIRST(rseg->update_undo_cached); while (undo != NULL) { trx_undo_t* prev_undo = undo; undo = UT_LIST_GET_NEXT(undo_list, undo); UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo); trx_undo_mem_free(prev_undo); } undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached); while (undo != NULL) { trx_undo_t* prev_undo = undo; undo = UT_LIST_GET_NEXT(undo_list, undo); UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo); trx_undo_mem_free(prev_undo); } trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL); mem_free(rseg); }
/************************************************************************* Checks if possible foreign key constraints hold after a delete of the record under pcur. NOTE that this function will temporarily commit mtr and lose pcur position! */ static ulint row_upd_check_references_constraints( /*=================================*/ /* out: DB_SUCCESS, DB_LOCK_WAIT, or an error code */ btr_pcur_t* pcur, /* in: cursor positioned on a record; NOTE: the cursor position is lost in this function! */ dict_table_t* table, /* in: table in question */ dict_index_t* index, /* in: index of the cursor */ que_thr_t* thr, /* in: query thread */ mtr_t* mtr) /* in: mtr */ { dict_foreign_t* foreign; mem_heap_t* heap; dtuple_t* entry; rec_t* rec; ulint err; rec = btr_pcur_get_rec(pcur); heap = mem_heap_create(500); entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); mtr_commit(mtr); mtr_start(mtr); rw_lock_s_lock(&dict_foreign_key_check_lock); foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign) { if (foreign->referenced_index == index) { err = row_ins_check_foreign_constraint(FALSE, foreign, table, index, entry, thr); if (err != DB_SUCCESS) { rw_lock_s_unlock(&dict_foreign_key_check_lock); mem_heap_free(heap); return(err); } } foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } rw_lock_s_unlock(&dict_foreign_key_check_lock); mem_heap_free(heap); return(DB_SUCCESS); }
/******************************************************************//** Calling this function is obligatory only if the memory buffer containing the mutex is freed. Removes a mutex object from the mutex list. The mutex is checked to be in the reset state. */ UNIV_INTERN void mutex_free( /*=======*/ mutex_t* mutex) /*!< in: mutex */ { ut_ad(mutex_validate(mutex)); ut_a(mutex_get_lock_word(mutex) == 0); ut_a(mutex_get_waiters(mutex) == 0); #ifdef UNIV_MEM_DEBUG if (mutex == &mem_hash_mutex) { ut_ad(UT_LIST_GET_LEN(mutex_list) == 1); ut_ad(UT_LIST_GET_FIRST(mutex_list) == &mem_hash_mutex); UT_LIST_REMOVE(list, mutex_list, mutex); goto func_exit; } #endif /* UNIV_MEM_DEBUG */ if (mutex != &mutex_list_mutex #ifdef UNIV_SYNC_DEBUG && mutex != &sync_thread_mutex #endif /* UNIV_SYNC_DEBUG */ ) { mutex_enter(&mutex_list_mutex); ut_ad(!UT_LIST_GET_PREV(list, mutex) || UT_LIST_GET_PREV(list, mutex)->magic_n == MUTEX_MAGIC_N); ut_ad(!UT_LIST_GET_NEXT(list, mutex) || UT_LIST_GET_NEXT(list, mutex)->magic_n == MUTEX_MAGIC_N); UT_LIST_REMOVE(list, mutex_list, mutex); mutex_exit(&mutex_list_mutex); } os_event_free(mutex->event); #ifdef UNIV_MEM_DEBUG func_exit: #endif /* UNIV_MEM_DEBUG */ #if !defined(HAVE_ATOMIC_BUILTINS) os_fast_mutex_free(&(mutex->os_fast_mutex)); #endif /* If we free the mutex protecting the mutex list (freeing is not necessary), we have to reset the magic number AFTER removing it from the list. */ #ifdef UNIV_DEBUG mutex->magic_n = 0; #endif /* UNIV_DEBUG */ }