summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <marko@hundin.mysql.fi>2005-04-20 17:39:05 +0300
committerunknown <marko@hundin.mysql.fi>2005-04-20 17:39:05 +0300
commitea5c2a148a6b704265324a2adcd7ae779a0df0b0 (patch)
tree385dcdcccffb58642b6b6a5b9d7a9415e6622429
parentdfa485b47dd768304a5324f619af3da374c6165d (diff)
downloadmariadb-git-ea5c2a148a6b704265324a2adcd7ae779a0df0b0.tar.gz
InnoDB: Make CHECK TABLE killable. (Bug #9730)
innobase/btr/btr0btr.c: Enclose btr_print_size() and btr_print_tree() in #ifdef UNIV_BTR_PRINT Add trx_t* parameter to btr_validate_tree() and btr_validate_level(). btr_validate_level(): Call trx_is_interrupted() on each page. innobase/ibuf/ibuf0ibuf.c: Add trx_t* parameter to btr_validate_tree(). innobase/include/btr0btr.h: Enclose btr_print_size() and btr_print_tree() in #ifdef UNIV_BTR_PRINT Add trx_t* parameter to btr_validate_tree(). innobase/include/trx0trx.h: Declare trx_is_interrupted(). innobase/row/row0mysql.c: row_scan_and_check_index(): Check trx_is_interrupted() every 1,000 scanned rows. row_check_table_for_mysql(): Check trx_is_interrupted() for each index after btr_validate_tree(). sql/ha_innodb.cc: Define trx_is_interrupted().
-rw-r--r--innobase/btr/btr0btr.c19
-rw-r--r--innobase/ibuf/ibuf0ibuf.c4
-rw-r--r--innobase/include/btr0btr.h5
-rw-r--r--innobase/include/trx0trx.h13
-rw-r--r--innobase/row/row0mysql.c17
-rw-r--r--sql/ha_innodb.cc17
6 files changed, 66 insertions, 9 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index 1744fc36f4d..fe6220b860d 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri
#include "rem0cmp.h"
#include "lock0lock.h"
#include "ibuf0ibuf.h"
+#include "trx0trx.h"
/*
Latching strategy of the InnoDB B-tree
@@ -2274,6 +2275,7 @@ btr_discard_page(
ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
}
+#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
@@ -2407,8 +2409,9 @@ btr_print_tree(
mtr_commit(&mtr);
- btr_validate_tree(tree);
+ btr_validate_tree(tree, NULL);
}
+#endif /* UNIV_BTR_PRINT */
/****************************************************************
Checks that the node pointer to a page is appropriate. */
@@ -2649,6 +2652,7 @@ btr_validate_level(
/*===============*/
/* out: TRUE if ok */
dict_tree_t* tree, /* in: index tree */
+ trx_t* trx, /* in: transaction or NULL */
ulint level) /* in: level number */
{
ulint space;
@@ -2696,6 +2700,11 @@ btr_validate_level(
/* Now we are on the desired level. Loop through the pages on that
level. */
loop:
+ if (trx_is_interrupted(trx)) {
+ mtr_commit(&mtr);
+ mem_heap_free(heap);
+ return(ret);
+ }
mem_heap_empty(heap);
offsets = offsets2 = NULL;
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
@@ -2941,7 +2950,8 @@ ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
- dict_tree_t* tree) /* in: tree */
+ dict_tree_t* tree, /* in: tree */
+ trx_t* trx) /* in: transaction or NULL */
{
mtr_t mtr;
page_t* root;
@@ -2954,9 +2964,8 @@ btr_validate_tree(
root = btr_root_get(tree, &mtr);
n = btr_page_get_level(root, &mtr);
- for (i = 0; i <= n; i++) {
-
- if (!btr_validate_level(tree, n - i)) {
+ for (i = 0; i <= n && !trx_is_interrupted(trx); i++) {
+ if (!btr_validate_level(tree, trx, n - i)) {
mtr_commit(&mtr);
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index caa2ac013d7..c72bb2b1b65 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -2969,7 +2969,9 @@ ibuf_delete_rec(
btr_pcur_commit_specify_mtr(pcur, mtr);
fputs("InnoDB: Validating insert buffer tree:\n", stderr);
- ut_a(btr_validate_tree(ibuf_data->index->tree));
+ if (!btr_validate_tree(ibuf_data->index->tree, NULL)) {
+ ut_error;
+ }
fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr);
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index 0b19e64d4e0..23116d24288 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -398,6 +398,7 @@ btr_page_free_low(
page_t* page, /* in: page to be freed, x-latched */
ulint level, /* in: page level */
mtr_t* mtr); /* in: mtr */
+#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
@@ -414,6 +415,7 @@ btr_print_tree(
dict_tree_t* tree, /* in: tree */
ulint width); /* in: print this many entries from start
and end */
+#endif /* UNIV_BTR_PRINT */
/****************************************************************
Checks the size and number of fields in a record based on the definition of
the index. */
@@ -434,7 +436,8 @@ ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
- dict_tree_t* tree); /* in: tree */
+ dict_tree_t* tree, /* in: tree */
+ trx_t* trx); /* in: transaction or NULL */
#define BTR_N_LEAF_PAGES 1
#define BTR_TOTAL_SIZE 2
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index d46613c3a68..6ca9c778aeb 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -312,6 +312,19 @@ trx_print(
FILE* f, /* in: output stream */
trx_t* trx); /* in: transaction */
+#ifndef UNIV_HOTBACKUP
+/**************************************************************************
+Determines if the currently running transaction has been interrupted. */
+
+ibool
+trx_is_interrupted(
+/*===============*/
+ /* out: TRUE if interrupted */
+ trx_t* trx); /* in: transaction */
+#else /* !UNIV_HOTBACKUP */
+#define trx_is_interrupted(trx) FALSE
+#endif /* !UNIV_HOTBACKUP */
+
/* Signal to a transaction */
struct trx_sig_struct{
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 7f78a5b723b..a201368f3d5 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -3880,6 +3880,7 @@ row_scan_and_check_index(
int cmp;
ibool contains_null;
ulint i;
+ ulint cnt;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -3902,11 +3903,19 @@ row_scan_and_check_index(
dtuple_set_n_fields(prebuilt->search_tuple, 0);
prebuilt->select_lock_type = LOCK_NONE;
+ cnt = 1000;
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
loop:
+ /* Check thd->killed every 1,000 scanned rows */
+ if (--cnt == 0) {
+ if (trx_is_interrupted(prebuilt->trx)) {
+ goto func_exit;
+ }
+ cnt = 1000;
+ }
if (ret != DB_SUCCESS) {
-
+ func_exit:
mem_free(buf);
mem_heap_free(heap);
@@ -4033,7 +4042,7 @@ row_check_table_for_mysql(
ut_print_name(stderr, index->name);
putc('\n', stderr); */
- if (!btr_validate_tree(index->tree)) {
+ if (!btr_validate_tree(index->tree, prebuilt->trx)) {
ret = DB_ERROR;
} else {
if (!row_scan_and_check_index(prebuilt,
@@ -4041,6 +4050,10 @@ row_check_table_for_mysql(
ret = DB_ERROR;
}
+ if (trx_is_interrupted(prebuilt->trx)) {
+ break;
+ }
+
/* fprintf(stderr, "%lu entries in index %s\n", n_rows,
index->name); */
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index a26c706bb08..4834dd24fa8 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -997,6 +997,23 @@ mysql_get_identifier_quote_char(
}
/**************************************************************************
+Determines if the currently running transaction has been interrupted. */
+extern "C"
+ibool
+trx_is_interrupted(
+/*===============*/
+ /* out: TRUE if interrupted */
+ trx_t* trx) /* in: transaction */
+{
+ fprintf(stderr,
+ "trx_is_interrupted: %p %p %d\n",
+ trx, trx ? trx->mysql_thd : 0,
+ trx && trx->mysql_thd ? ((THD*) trx->mysql_thd)->killed : -1);
+
+ return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed);
+}
+
+/**************************************************************************
Obtain a pointer to the MySQL THD object, as in current_thd(). This
definition must match the one in sql/ha_innodb.cc! */
extern "C"