mariadb/storage/innobase/include/que0que.ic
Jan Lindström 2e814d4702 Merge InnoDB 5.7 from mysql-5.7.9.
Contains also

MDEV-10547: Test multi_update_innodb fails with InnoDB 5.7

	The failure happened because 5.7 has changed the signature of
	the bool handler::primary_key_is_clustered() const
	virtual function ("const" was added). InnoDB was using the old
	signature which caused the function not to be used.

MDEV-10550: Parallel replication lock waits/deadlock handling does not work with InnoDB 5.7

	Fixed mutexing problem on lock_trx_handle_wait. Note that
	rpl_parallel and rpl_optimistic_parallel tests still
	fail.

MDEV-10156 : Group commit tests fail on 10.2 InnoDB (branch bb-10.2-jan)
  Reason: incorrect merge

MDEV-10550: Parallel replication can't sync with master in InnoDB 5.7 (branch bb-10.2-jan)
  Reason: incorrect merge
2016-09-02 13:22:28 +03:00

308 lines
7.4 KiB
Text

/*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/**************************************************//**
@file include/que0que.ic
Query graph
Created 5/27/1996 Heikki Tuuri
*******************************************************/
#include "usr0sess.h"
/***********************************************************************//**
Gets the trx of a query thread. */
UNIV_INLINE
trx_t*
thr_get_trx(
/*========*/
que_thr_t* thr) /*!< in: query thread */
{
ut_ad(thr);
return(thr->graph->trx);
}
/*******************************************************************//**
Determines if this thread is rolling back an incomplete transaction
in crash recovery.
@return TRUE if thr is rolling back an incomplete transaction in crash
recovery */
UNIV_INLINE
ibool
thr_is_recv(
/*========*/
const que_thr_t* thr) /*!< in: query thread */
{
return(trx_is_recv(thr->graph->trx));
}
/***********************************************************************//**
Gets the first thr in a fork. */
UNIV_INLINE
que_thr_t*
que_fork_get_first_thr(
/*===================*/
que_fork_t* fork) /*!< in: query fork */
{
return(UT_LIST_GET_FIRST(fork->thrs));
}
/***********************************************************************//**
Gets the child node of the first thr in a fork. */
UNIV_INLINE
que_node_t*
que_fork_get_child(
/*===============*/
que_fork_t* fork) /*!< in: query fork */
{
que_thr_t* thr;
thr = UT_LIST_GET_FIRST(fork->thrs);
return(thr->child);
}
/***********************************************************************//**
Gets the type of a graph node. */
UNIV_INLINE
ulint
que_node_get_type(
/*==============*/
const que_node_t* node) /*!< in: graph node */
{
return(reinterpret_cast<const que_common_t*>(node)->type);
}
/***********************************************************************//**
Gets pointer to the value dfield of a graph node. */
UNIV_INLINE
dfield_t*
que_node_get_val(
/*=============*/
que_node_t* node) /*!< in: graph node */
{
ut_ad(node);
return(&(((que_common_t*) node)->val));
}
/***********************************************************************//**
Gets the value buffer size of a graph node.
@return val buffer size, not defined if val.data == NULL in node */
UNIV_INLINE
ulint
que_node_get_val_buf_size(
/*======================*/
que_node_t* node) /*!< in: graph node */
{
ut_ad(node);
return(((que_common_t*) node)->val_buf_size);
}
/***********************************************************************//**
Sets the value buffer size of a graph node. */
UNIV_INLINE
void
que_node_set_val_buf_size(
/*======================*/
que_node_t* node, /*!< in: graph node */
ulint size) /*!< in: size */
{
ut_ad(node);
((que_common_t*) node)->val_buf_size = size;
}
/***********************************************************************//**
Sets the parent of a graph node. */
UNIV_INLINE
void
que_node_set_parent(
/*================*/
que_node_t* node, /*!< in: graph node */
que_node_t* parent) /*!< in: parent */
{
ut_ad(node);
((que_common_t*) node)->parent = parent;
}
/***********************************************************************//**
Gets pointer to the value data type field of a graph node. */
UNIV_INLINE
dtype_t*
que_node_get_data_type(
/*===================*/
que_node_t* node) /*!< in: graph node */
{
ut_ad(node);
return(dfield_get_type(&((que_common_t*) node)->val));
}
/*********************************************************************//**
Catenates a query graph node to a list of them, possible empty list.
@return one-way list of nodes */
UNIV_INLINE
que_node_t*
que_node_list_add_last(
/*===================*/
que_node_t* node_list, /*!< in: node list, or NULL */
que_node_t* node) /*!< in: node */
{
que_common_t* cnode;
que_common_t* cnode2;
cnode = (que_common_t*) node;
cnode->brother = NULL;
if (node_list == NULL) {
return(node);
}
cnode2 = (que_common_t*) node_list;
while (cnode2->brother != NULL) {
cnode2 = (que_common_t*) cnode2->brother;
}
cnode2->brother = node;
return(node_list);
}
/*************************************************************************
Removes a query graph node from the list.*/
UNIV_INLINE
que_node_t*
que_node_list_get_last(
/*===================*/
/* out: last node in list.*/
que_node_t* node_list) /* in: node list */
{
que_common_t* node;
ut_a(node_list != NULL);
node = (que_common_t*) node_list;
/* We need the last element */
while (node->brother != NULL) {
node = (que_common_t*) node->brother;
}
return(node);
}
/*********************************************************************//**
Gets the next list node in a list of query graph nodes.
@return next node in a list of nodes */
UNIV_INLINE
que_node_t*
que_node_get_next(
/*==============*/
que_node_t* node) /*!< in: node in a list */
{
return(((que_common_t*) node)->brother);
}
/*********************************************************************//**
Gets a query graph node list length.
@return length, for NULL list 0 */
UNIV_INLINE
ulint
que_node_list_get_len(
/*==================*/
que_node_t* node_list) /*!< in: node list, or NULL */
{
const que_common_t* cnode;
ulint len;
cnode = (const que_common_t*) node_list;
len = 0;
while (cnode != NULL) {
len++;
cnode = (const que_common_t*) cnode->brother;
}
return(len);
}
/*********************************************************************//**
Gets the parent node of a query graph node.
@return parent node or NULL */
UNIV_INLINE
que_node_t*
que_node_get_parent(
/*================*/
que_node_t* node) /*!< in: node */
{
return(((que_common_t*) node)->parent);
}
/**********************************************************************//**
Checks if graph, trx, or session is in a state where the query thread should
be stopped.
@return TRUE if should be stopped; NOTE that if the peek is made
without reserving the trx mutex, then another peek with the mutex
reserved is necessary before deciding the actual stopping */
UNIV_INLINE
ibool
que_thr_peek_stop(
/*==============*/
que_thr_t* thr) /*!< in: query thread */
{
trx_t* trx;
que_t* graph;
graph = thr->graph;
trx = graph->trx;
if (graph->state != QUE_FORK_ACTIVE
|| trx->lock.que_state == TRX_QUE_LOCK_WAIT
|| (trx->lock.que_state != TRX_QUE_ROLLING_BACK
&& trx->lock.que_state != TRX_QUE_RUNNING)) {
return(TRUE);
}
return(FALSE);
}
/***********************************************************************//**
Returns TRUE if the query graph is for a SELECT statement.
@return TRUE if a select */
UNIV_INLINE
ibool
que_graph_is_select(
/*================*/
que_t* graph) /*!< in: graph */
{
if (graph->fork_type == QUE_FORK_SELECT_SCROLL
|| graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) {
return(TRUE);
}
return(FALSE);
}