📄 que0que.c
字号:
return(TRUE);}/**************************************************************************Calls que_graph_free_recursive for statements in a statement list. */staticvoidque_graph_free_stat_list(/*=====================*/ que_node_t* node) /* in: first query graph node in the list */{ while (node) { que_graph_free_recursive(node); node = que_node_get_next(node); }}/**************************************************************************Frees a query graph, but not the heap where it was created. Does not freeexplicit cursor declarations, they are freed in que_graph_free. */voidque_graph_free_recursive(/*=====================*/ que_node_t* node) /* in: query graph node */{ que_fork_t* fork; que_thr_t* thr; undo_node_t* undo; sel_node_t* sel; ins_node_t* ins; upd_node_t* upd; tab_node_t* cre_tab; ind_node_t* cre_ind; if (node == NULL) { return; } switch (que_node_get_type(node)) { case QUE_NODE_FORK: fork = node; thr = UT_LIST_GET_FIRST(fork->thrs); while (thr) { que_graph_free_recursive(thr); thr = UT_LIST_GET_NEXT(thrs, thr); } break; case QUE_NODE_THR: thr = node; if (thr->magic_n != QUE_THR_MAGIC_N) { fprintf(stderr, "que_thr struct appears corrupt; magic n %lu\n", (unsigned long) thr->magic_n); mem_analyze_corruption((byte*)thr); ut_error; } thr->magic_n = QUE_THR_MAGIC_FREED; que_graph_free_recursive(thr->child); break; case QUE_NODE_UNDO: undo = node; mem_heap_free(undo->heap); break; case QUE_NODE_SELECT: sel = node; sel_node_free_private(sel); break; case QUE_NODE_INSERT: ins = node; que_graph_free_recursive(ins->select); mem_heap_free(ins->entry_sys_heap); break; case QUE_NODE_UPDATE: upd = node; if (upd->in_mysql_interface) { btr_pcur_free_for_mysql(upd->pcur); } que_graph_free_recursive(upd->cascade_node); if (upd->cascade_heap) { mem_heap_free(upd->cascade_heap); } que_graph_free_recursive(upd->select); mem_heap_free(upd->heap); break; case QUE_NODE_CREATE_TABLE: cre_tab = node; que_graph_free_recursive(cre_tab->tab_def); que_graph_free_recursive(cre_tab->col_def); que_graph_free_recursive(cre_tab->commit_node); mem_heap_free(cre_tab->heap); break; case QUE_NODE_CREATE_INDEX: cre_ind = node; que_graph_free_recursive(cre_ind->ind_def); que_graph_free_recursive(cre_ind->field_def); que_graph_free_recursive(cre_ind->commit_node); mem_heap_free(cre_ind->heap); break; case QUE_NODE_PROC: que_graph_free_stat_list(((proc_node_t*)node)->stat_list); break; case QUE_NODE_IF: que_graph_free_stat_list(((if_node_t*)node)->stat_list); que_graph_free_stat_list(((if_node_t*)node)->else_part); que_graph_free_stat_list(((if_node_t*)node)->elsif_list); break; case QUE_NODE_ELSIF: que_graph_free_stat_list(((elsif_node_t*)node)->stat_list); break; case QUE_NODE_WHILE: que_graph_free_stat_list(((while_node_t*)node)->stat_list); break; case QUE_NODE_FOR: que_graph_free_stat_list(((for_node_t*)node)->stat_list); break; case QUE_NODE_ASSIGNMENT: case QUE_NODE_RETURN: case QUE_NODE_COMMIT: case QUE_NODE_ROLLBACK: case QUE_NODE_LOCK: case QUE_NODE_FUNC: case QUE_NODE_ORDER: case QUE_NODE_ROW_PRINTF: case QUE_NODE_OPEN: case QUE_NODE_FETCH: /* No need to do anything */ break; default: fprintf(stderr, "que_node struct appears corrupt; type %lu\n", (unsigned long) que_node_get_type(node)); mem_analyze_corruption((byte*)node); ut_error; }}/**************************************************************************Frees a query graph. */voidque_graph_free(/*===========*/ que_t* graph) /* in: query graph; we assume that the memory heap where this graph was created is private to this graph: if not, then use que_graph_free_recursive and free the heap afterwards! */{ ut_ad(graph); if (graph->sym_tab) { /* The following call frees dynamic memory allocated for variables etc. during execution. Frees also explicit cursor definitions. */ sym_tab_free_private(graph->sym_tab); } que_graph_free_recursive(graph); mem_heap_free(graph->heap);}/**************************************************************************Checks if the query graph is in a state where it should be freed, andfrees it in that case. If the session is in a state where it should beclosed, also this is done. */iboolque_graph_try_free(/*===============*/ /* out: TRUE if freed */ que_t* graph) /* in: query graph */{ sess_t* sess;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */ sess = (graph->trx)->sess; if ((graph->state == QUE_FORK_BEING_FREED) && (graph->n_active_thrs == 0)) { UT_LIST_REMOVE(graphs, sess->graphs, graph); que_graph_free(graph); sess_try_close(sess); return(TRUE); } return(FALSE);}/**************************************************************************Handles an SQL error noticed during query thread execution. Currently,does nothing! */voidque_thr_handle_error(/*=================*/ que_thr_t* thr __attribute__((unused)), /* in: query thread */ ulint err_no __attribute__((unused)), /* in: error number */ byte* err_str __attribute__((unused)), /* in, own: error string or NULL; NOTE: the function will take care of freeing of the string! */ ulint err_len __attribute__((unused))) /* in: error string length */ { /* Does nothing */}/********************************************************************Performs an execution step on a thr node. */staticque_thr_t*que_thr_node_step(/*==============*/ /* out: query thread to run next, or NULL if none */ que_thr_t* thr) /* in: query thread where run_node must be the thread node itself */{ ut_ad(thr->run_node == thr); if (thr->prev_node == thr->common.parent) { /* If control to the node came from above, it is just passed on */ thr->run_node = thr->child; return(thr); } mutex_enter(&kernel_mutex); if (que_thr_peek_stop(thr)) { mutex_exit(&kernel_mutex); return(thr); } /* Thread execution completed */ thr->state = QUE_THR_COMPLETED; mutex_exit(&kernel_mutex); return(NULL);}/**************************************************************************Moves a thread from another state to the QUE_THR_RUNNING state. Incrementsthe n_active_thrs counters of the query graph and transaction if thr wasnot active.***NOTE***: This and ..._mysql are the only functions in which such atransition is allowed to happen! */staticvoidque_thr_move_to_run_state(/*======================*/ que_thr_t* thr) /* in: an query thread */{ trx_t* trx; ut_ad(thr->state != QUE_THR_RUNNING); trx = thr_get_trx(thr); if (!thr->is_active) { (thr->graph)->n_active_thrs++; trx->n_active_thrs++; thr->is_active = TRUE; ut_ad((thr->graph)->n_active_thrs == 1); ut_ad(trx->n_active_thrs == 1); } thr->state = QUE_THR_RUNNING;}/**************************************************************************Decrements the query thread reference counts in the query graph and thetransaction. May start signal handling, e.g., a rollback.*** NOTE ***:This and que_thr_stop_for_mysql arethe only functions where the reference count can be decremented andthis function may only be called from inside que_run_threads orque_thr_check_if_switch! These restrictions exist to make the rollback codeeasier to maintain. */staticvoidque_thr_dec_refer_count(/*====================*/ que_thr_t* thr, /* in: query thread */ que_thr_t** next_thr) /* in/out: next query thread to run; if the value which is passed in is a pointer to a NULL pointer, then the calling function can start running a new query thread */ { que_fork_t* fork; trx_t* trx; sess_t* sess; ulint fork_type; ibool stopped; fork = thr->common.parent; trx = thr->graph->trx; sess = trx->sess; mutex_enter(&kernel_mutex); ut_a(thr->is_active); if (thr->state == QUE_THR_RUNNING) { stopped = que_thr_stop(thr); if (!stopped) { /* The reason for the thr suspension or wait was already canceled before we came here: continue running the thread */ /* fputs("!!!!!!!! Wait already ended: continue thr\n", stderr); */ if (next_thr && *next_thr == NULL) { *next_thr = thr; } else { ut_a(0); srv_que_task_enqueue_low(thr); } mutex_exit(&kernel_mutex); return; } } ut_ad(fork->n_active_thrs == 1); ut_ad(trx->n_active_thrs == 1); fork->n_active_thrs--; trx->n_active_thrs--; thr->is_active = FALSE; if (trx->n_active_thrs > 0) { mutex_exit(&kernel_mutex); return; } fork_type = fork->fork_type; /* Check if all query threads in the same fork are completed */ if (que_fork_all_thrs_in_state(fork, QUE_THR_COMPLETED)) { if (fork_type == QUE_FORK_ROLLBACK) { /* This is really the undo graph used in rollback, no roll_node in this graph */ ut_ad(UT_LIST_GET_LEN(trx->signals) > 0); ut_ad(trx->handling_signals == TRUE); trx_finish_rollback_off_kernel(fork, trx, next_thr); } else if (fork_type == QUE_FORK_PURGE) { /* Do nothing */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -