⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 que0que.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************Query graph(c) 1996 Innobase OyCreated 5/27/1996 Heikki Tuuri*******************************************************/#include "que0que.h" #ifdef UNIV_NONINL#include "que0que.ic"#endif#include "srv0que.h"#include "usr0sess.h"#include "trx0trx.h"#include "trx0roll.h"#include "row0undo.h"#include "row0ins.h"#include "row0upd.h"#include "row0sel.h"#include "row0purge.h"#include "dict0crea.h"#include "log0log.h"#include "eval0proc.h"#include "eval0eval.h"#define QUE_PARALLELIZE_LIMIT	(64 * 256 * 256 * 256)#define QUE_ROUND_ROBIN_LIMIT	(64 * 256 * 256 * 256)#define QUE_MAX_LOOPS_WITHOUT_CHECK	16/* If the following flag is set TRUE, the module will print trace infoof SQL execution in the UNIV_SQL_DEBUG version */ibool	que_trace_on		= FALSE;ibool	que_always_false	= FALSE;/* How a stored procedure containing COMMIT or ROLLBACK commandsis executed?The commit or rollback can be seen as a subprocedure call.The problem is that if there are several query threadscurrently running within the transaction, their action couldmess the commit or rollback operation. Or, at the least, theoperation would be difficult to visualize and keep in control.Therefore the query thread requesting a commit or a rollbacksends to the transaction a signal, which moves the transactionto TRX_QUE_SIGNALED state. All running query threads of thetransaction will eventually notice that the transaction is now inthis state and voluntarily suspend themselves. Only the lastquery thread which suspends itself will trigger handling ofthe signal.When the transaction starts to handle a rollback or commitsignal, it builds a query graph which, when executed, willroll back or commit the incomplete transaction. The transactionis moved to the TRX_QUE_ROLLING_BACK or TRX_QUE_COMMITTING state.If specified, the SQL cursors opened by the transaction are closed.When the execution of the graph completes, it is like returningfrom a subprocedure: the query thread which requested the operationstarts running again. *//**************************************************************************Moves a thread from another state to the QUE_THR_RUNNING state. Incrementsthe n_active_thrs counters of the query graph and transaction.***NOTE***: This is the only function in which such a transition is allowedto happen! */staticvoidque_thr_move_to_run_state(/*======================*/	que_thr_t*	thr);	/* in: an query thread *//***************************************************************************Adds a query graph to the session's list of graphs. */voidque_graph_publish(/*==============*/	que_t*	graph,	/* in: graph */	sess_t*	sess)	/* in: session */{#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	UT_LIST_ADD_LAST(graphs, sess->graphs, graph);}/***************************************************************************Creates a query graph fork node. */que_fork_t*que_fork_create(/*============*/					/* out, own: fork node */	que_t*		graph,		/* in: graph, if NULL then this					fork node is assumed to be the					graph root */	que_node_t*	parent,		/* in: parent node */	ulint		fork_type,	/* in: fork type */	mem_heap_t*	heap)		/* in: memory heap where created */{	que_fork_t*	fork;	ut_ad(heap);		fork = mem_heap_alloc(heap, sizeof(que_fork_t));	fork->common.type = QUE_NODE_FORK;	fork->n_active_thrs = 0;	fork->state = QUE_FORK_COMMAND_WAIT;	if (graph != NULL) {		fork->graph = graph;	} else {		fork->graph = fork;	}		fork->common.parent = parent;	fork->fork_type = fork_type;	fork->caller = NULL;	UT_LIST_INIT(fork->thrs);	fork->sym_tab = NULL;		fork->heap = heap;		return(fork);}/***************************************************************************Creates a query graph thread node. */que_thr_t*que_thr_create(/*===========*/				/* out, own: query thread node */	que_fork_t*	parent,	/* in: parent node, i.e., a fork node */	mem_heap_t*	heap)	/* in: memory heap where created */{	que_thr_t*	thr;		ut_ad(parent && heap);		thr = mem_heap_alloc(heap, sizeof(que_thr_t));	thr->common.type = QUE_NODE_THR;	thr->common.parent = parent;	thr->magic_n = QUE_THR_MAGIC_N;	thr->graph = parent->graph;	thr->state = QUE_THR_COMMAND_WAIT;	thr->is_active = FALSE;		thr->run_node = NULL;	thr->resource = 0;  thr->lock_state = QUE_THR_LOCK_NOLOCK;	UT_LIST_ADD_LAST(thrs, parent->thrs, thr);	return(thr);}/**************************************************************************Moves a suspended query thread to the QUE_THR_RUNNING state and may releasea single worker thread to execute it. This function should be used to endthe wait state of a query thread waiting for a lock or a stored procedurecompletion. */voidque_thr_end_wait(/*=============*/	que_thr_t*	thr,		/* in: query thread in the					QUE_THR_LOCK_WAIT,					or QUE_THR_PROCEDURE_WAIT, or					QUE_THR_SIG_REPLY_WAIT state */	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; if NULL is passed					as the parameter, it is ignored */{	ibool	was_active;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	ut_ad(thr);	ut_ad((thr->state == QUE_THR_LOCK_WAIT)	      || (thr->state == QUE_THR_PROCEDURE_WAIT)	      || (thr->state == QUE_THR_SIG_REPLY_WAIT));	ut_ad(thr->run_node);	thr->prev_node = thr->run_node;	was_active = thr->is_active;		que_thr_move_to_run_state(thr);	if (was_active) {		return;	}		if (next_thr && *next_thr == NULL) {		*next_thr = thr;	} else {		ut_a(0);		srv_que_task_enqueue_low(thr);	}}	/**************************************************************************Same as que_thr_end_wait, but no parameter next_thr available. */voidque_thr_end_wait_no_next_thr(/*=========================*/	que_thr_t*	thr)	/* in: query thread in the QUE_THR_LOCK_WAIT,				or QUE_THR_PROCEDURE_WAIT, or				QUE_THR_SIG_REPLY_WAIT state */{	ibool	was_active;	ut_a(thr->state == QUE_THR_LOCK_WAIT);	/* In MySQL this is the						only possible state here */#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	ut_ad(thr);	ut_ad((thr->state == QUE_THR_LOCK_WAIT)	      || (thr->state == QUE_THR_PROCEDURE_WAIT)	      || (thr->state == QUE_THR_SIG_REPLY_WAIT));	was_active = thr->is_active;		que_thr_move_to_run_state(thr);	if (was_active) {		return;	}	/* In MySQL we let the OS thread (not just the query thread) to wait	for the lock to be released: */		srv_release_mysql_thread_if_suspended(thr);	/* srv_que_task_enqueue_low(thr); */}/**************************************************************************Inits a query thread for a command. */UNIV_INLINEvoidque_thr_init_command(/*=================*/	que_thr_t*	thr)	/* in: query thread */{	thr->run_node = thr;	thr->prev_node = thr->common.parent;	que_thr_move_to_run_state(thr);}/**************************************************************************Starts execution of a command in a query fork. Picks a query thread whichis not in the QUE_THR_RUNNING state and moves it to that state. If nonecan be chosen, a situation which may arise in parallelized fetches, NULLis returned. */que_thr_t*que_fork_start_command(/*===================*/				/* out: a query thread of the graph moved to				QUE_THR_RUNNING state, or NULL; the query				thread should be executed by que_run_threads				by the caller */	que_fork_t* 	fork)	/* in: a query fork */{	que_thr_t*	thr;	fork->state = QUE_FORK_ACTIVE;		fork->last_sel_node = NULL;	/* Choose the query thread to run: usually there is just one thread,	but in a parallelized select, which necessarily is non-scrollable,	there may be several to choose from */	/*---------------------------------------------------------------	First we try to find a query thread in the QUE_THR_COMMAND_WAIT state */		thr = UT_LIST_GET_FIRST(fork->thrs);	while (thr != NULL) {		if (thr->state == QUE_THR_COMMAND_WAIT) {			/* We have to send the initial message to query thread			to start it */			que_thr_init_command(thr);			return(thr);		}		ut_ad(thr->state != QUE_THR_LOCK_WAIT);				thr = UT_LIST_GET_NEXT(thrs, thr);	}	/*----------------------------------------------------------------	Then we try to find a query thread in the QUE_THR_SUSPENDED state */	thr = UT_LIST_GET_FIRST(fork->thrs);	while (thr != NULL) {		if (thr->state == QUE_THR_SUSPENDED) {			/* In this case the execution of the thread was			suspended: no initial message is needed because			execution can continue from where it was left */			que_thr_move_to_run_state(thr);			return(thr);		}		thr = UT_LIST_GET_NEXT(thrs, thr);	}	/*-----------------------------------------------------------------	Then we try to find a query thread in the QUE_THR_COMPLETED state */		thr = UT_LIST_GET_FIRST(fork->thrs);	while (thr != NULL) {		if (thr->state == QUE_THR_COMPLETED) {			que_thr_init_command(thr);			return(thr);		}		thr = UT_LIST_GET_NEXT(thrs, thr);	}	/* Else we return NULL */	return(NULL);}/**************************************************************************After signal handling is finished, returns control to a query graph errorhandling routine. (Currently, just returns the control to the root of thegraph so that the graph can communicate an error message to the client.) */voidque_fork_error_handle(/*==================*/	trx_t*	trx __attribute__((unused)),	/* in: trx */	que_t*	fork)	/* in: query graph which was run before signal			handling started, NULL not allowed */{	que_thr_t*	thr;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	ut_ad(trx->sess->state == SESS_ERROR);	ut_ad(UT_LIST_GET_LEN(trx->reply_signals) == 0);	ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);	thr = UT_LIST_GET_FIRST(fork->thrs);	while (thr != NULL) {		ut_ad(!thr->is_active);		ut_ad(thr->state != QUE_THR_SIG_REPLY_WAIT);		ut_ad(thr->state != QUE_THR_LOCK_WAIT);				thr->run_node = thr;		thr->prev_node = thr->child;		thr->state = QUE_THR_COMPLETED;				thr = UT_LIST_GET_NEXT(thrs, thr);	}	thr = UT_LIST_GET_FIRST(fork->thrs);		que_thr_move_to_run_state(thr);	ut_a(0);	srv_que_task_enqueue_low(thr);}/********************************************************************Tests if all the query threads in the same fork have a given state. */UNIV_INLINEiboolque_fork_all_thrs_in_state(/*=======================*/				/* out: TRUE if all the query threads in the				same fork were in the given state */	que_fork_t*	fork,	/* in: query fork */	ulint		state)	/* in: state */{	que_thr_t*	thr_node;	thr_node = UT_LIST_GET_FIRST(fork->thrs);	while (thr_node != NULL) {		if (thr_node->state != state) {			return(FALSE);		}		thr_node = UT_LIST_GET_NEXT(thrs, thr_node);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -