コード例 #1
0
ファイル: que0que.c プロジェクト: isleon/Jaxer
void
que_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); */
}
コード例 #2
0
ファイル: que0que.c プロジェクト: isleon/Jaxer
/**************************************************************************
Inits a query thread for a command. */
UNIV_INLINE
void
que_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);
}
コード例 #3
0
ファイル: que0que.c プロジェクト: isleon/Jaxer
void
que_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);
	}
}	
コード例 #4
0
ファイル: que0que.c プロジェクト: isleon/Jaxer
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);
}
コード例 #5
0
ファイル: api0misc.c プロジェクト: toffaletti/turtle
enum db_err
ib_trx_lock_table_with_retry(
/*=========================*/
	trx_t*		trx,		/*!< in/out: transaction */
	dict_table_t*	table,		/*!< in: table to lock */
	enum lock_mode	mode)		/*!< in: LOCK_X or LOCK_S */
{
	que_thr_t*	thr;
	enum db_err	err;
	mem_heap_t*	heap;
	sel_node_t*	node;

	ut_ad(trx->client_thread_id == os_thread_get_curr_id());

	heap = mem_heap_create(512);

	trx->op_info = "setting table lock";

	node = sel_node_create(heap);
	thr = pars_complete_graph_for_exec(node, trx, heap);
	thr->graph->state = QUE_FORK_ACTIVE;

	/* We use the select query graph as the dummy graph needed
	in the lock module call */

	thr = que_fork_get_first_thr(que_node_get_parent(thr));
	que_thr_move_to_run_state(thr);

run_again:
	thr->run_node = thr;
	thr->prev_node = thr->common.parent;

	err = lock_table(0, table, mode, thr);

	trx->error_state = err;

	if (UNIV_LIKELY(err == DB_SUCCESS)) {
		que_thr_stop_for_client_no_error(thr, trx);
	} else {
		que_thr_stop_client(thr);

		if (err != DB_QUE_THR_SUSPENDED) {
			ibool	was_lock_wait;

			was_lock_wait = ib_handle_errors(&err, trx, thr, NULL);

			if (was_lock_wait) {
				goto run_again;
			}
		} else {
			que_thr_t*	run_thr;
			que_node_t*	parent;

			parent = que_node_get_parent(thr);
			run_thr = que_fork_start_command(parent);

			ut_a(run_thr == thr);

			/* There was a lock wait but the thread was not
			in a ready to run or running state. */
			trx->error_state = DB_LOCK_WAIT;

			goto run_again;
		}
	}

	que_graph_free(thr->graph);
	trx->op_info = "";

	return(err);
}
コード例 #6
0
ファイル: que0que.c プロジェクト: pombredanne/mysql-1
/**********************************************************************//**
Starts execution of a command in a query fork. Picks a query thread which
is not in the QUE_THR_RUNNING state and moves it to that state. If none
can be chosen, a situation which may arise in parallelized fetches, NULL
is returned.
@return 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 */
UNIV_INTERN
que_thr_t*
que_fork_start_command(
/*===================*/
	que_fork_t*	fork)	/*!< in: a query fork */
{
	que_thr_t*	thr;
	que_thr_t*	suspended_thr = NULL;
	que_thr_t*	completed_thr = NULL;

	fork->state = QUE_FORK_ACTIVE;

	fork->last_sel_node = NULL;

	suspended_thr = NULL;
	completed_thr = 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. Then we try to find a query thread in the QUE_THR_SUSPENDED
	state, finally we try to find a query thread in the QUE_THR_COMPLETED
	state */

	thr = UT_LIST_GET_FIRST(fork->thrs);

	/* We make a single pass over the thr list within which we note which
	threads are ready to run. */
	while (thr) {
		switch (thr->state) {
		case QUE_THR_COMMAND_WAIT:

			/* We have to send the initial message to query thread
			to start it */

			que_thr_init_command(thr);

			return(thr);

		case 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 */
			if (!suspended_thr) {
				suspended_thr = thr;
			}

			break;

		case QUE_THR_COMPLETED:
			if (!completed_thr) {
				completed_thr = thr;
			}

			break;

		case QUE_THR_LOCK_WAIT:
			ut_error;

		}

		thr = UT_LIST_GET_NEXT(thrs, thr);
	}

	if (suspended_thr) {

		thr = suspended_thr;
		que_thr_move_to_run_state(thr);

	} else if (completed_thr) {

		thr = completed_thr;
		que_thr_init_command(thr);
	}

	return(thr);
}