WL#3138: Maria - fast "SELECT COUNT(*) FROM t;" and "CHECKSUM TABLE t"
Added argument to maria_end_bulk_insert() to know if the table will be deleted after the operation Fixed wrong call to strmake Don't call bulk insert in case of inserting only one row (speed optimization as starting/stopping bulk insert Allow storing year 2155 in year field When running with purify/valgrind avoid copying structures over themself Added hook 'trnnam_end_trans_hook' that is called when transaction ends Added trn->used_tables that is used to an entry for all tables used by transaction Fixed that ndb doesn't crash on duplicate key error when start_bulk_insert/end_bulk_insert are not called include/maria.h: Added argument to maria_end_bulk_insert() to know if the table will be deleted after the operation include/my_tree.h: Added macro 'reset_free_element()' to be able to ignore calls to the external free function. Is used to optimize end-bulk-insert in case of failures, in which case we don't want write the remaining keys in the tree mysql-test/install_test_db.sh: Upgrade to new mysql_install_db options mysql-test/r/maria-mvcc.result: New tests mysql-test/r/maria.result: New tests mysql-test/suite/ndb/r/ndb_auto_increment.result: Fixed error message now when bulk insert is not always called mysql-test/suite/ndb/t/ndb_auto_increment.test: Fixed error message now when bulk insert is not always called mysql-test/t/maria-mvcc.test: Added testing of versioning of count(*) mysql-test/t/maria-page-checksum.test: Added comment mysql-test/t/maria.test: More tests mysys/hash.c: Code style change sql/field.cc: Allow storing year 2155 in year field sql/ha_ndbcluster.cc: Added new argument to end_bulk_insert() to signal if the bulk insert should ignored sql/ha_ndbcluster.h: Added new argument to end_bulk_insert() to signal if the bulk insert should ignored sql/ha_partition.cc: Added new argument to end_bulk_insert() to signal if the bulk insert should ignored sql/ha_partition.h: Added new argument to end_bulk_insert() to signal if the bulk insert should ignored sql/handler.cc: Don't call get_dup_key() if there is no table object. This can happen if the handler generates a duplicate key error on commit sql/handler.h: Added new argument to end_bulk_insert() to signal if the bulk insert should ignored (ie, the table will be deleted) sql/item.cc: Style fix Removed compiler warning sql/log_event.cc: Added new argument to ha_end_bulk_insert() sql/log_event_old.cc: Added new argument to ha_end_bulk_insert() sql/mysqld.cc: Removed compiler warning sql/protocol.cc: Added DBUG sql/sql_class.cc: Added DBUG Fixed wrong call to strmake sql/sql_insert.cc: Don't call bulk insert in case of inserting only one row (speed optimization as starting/stopping bulk insert involves a lot of if's) Added new argument to ha_end_bulk_insert() sql/sql_load.cc: Added new argument to ha_end_bulk_insert() sql/sql_parse.cc: Style fixes Avoid goto in common senario sql/sql_select.cc: When running with purify/valgrind avoid copying structures over themself. This is not a real bug in itself, but it's a waste of cycles and causes valgrind warnings sql/sql_select.h: Avoid copying structures over themself. This is not a real bug in itself, but it's a waste of cycles and causes valgrind warnings sql/sql_table.cc: Call HA_EXTRA_PREPARE_FOR_DROP if table created by ALTER TABLE is going to be dropped Added new argument to ha_end_bulk_insert() storage/archive/ha_archive.cc: Added new argument to end_bulk_insert() storage/archive/ha_archive.h: Added new argument to end_bulk_insert() storage/federated/ha_federated.cc: Added new argument to end_bulk_insert() storage/federated/ha_federated.h: Added new argument to end_bulk_insert() storage/maria/Makefile.am: Added ma_state.c and ma_state.h storage/maria/ha_maria.cc: Versioning of count(*) and checksum - share->state.state is now assumed to be correct, not handler->state - Call _ma_setup_live_state() in external lock to get count(*)/checksum versioning. In case of not versioned and not concurrent insertable table, file->s->state.state contains the correct state information Other things: - file->s -> share - Added DBUG_ASSERT() for unlikely case - Optimized end_bulk_insert() to not write anything if table is going to be deleted (as in failed alter table) - Indentation changes in external_lock becasue of removed 'goto' caused a big conflict even if very little was changed storage/maria/ha_maria.h: New argument to end_bulk_insert() storage/maria/ma_blockrec.c: Update for versioning of count(*) and checksum Keep share->state.state.data_file_length up to date (not info->state->data_file_length) Moved _ma_block_xxxx_status() and maria_versioning() functions to ma_state.c storage/maria/ma_check.c: Update and use share->state.state instead of info->state info->s to share Update info->state at end of repair Call _ma_reset_state() to update share->state_history at end of repair storage/maria/ma_checkpoint.c: Call _ma_remove_not_visible_states() on checkpoint to clean up not visible state history from tables storage/maria/ma_close.c: Remember state history for running transaction even if table is closed storage/maria/ma_commit.c: Ensure we always call trnman_commit_trn() even if other calls fails. If we don't do that, the translog and state structures will not be freed storage/maria/ma_delete.c: Versioning of count(*) and checksum: - Always update info->state->checksum and info->state->records storage/maria/ma_delete_all.c: Versioning of count(*) and checksum: - Ensure that share->state.state is updated, as here is where we store the primary information storage/maria/ma_dynrec.c: Use lock_key_trees instead of concurrent_insert to check if trees should be locked. This allows us to lock trees both for concurrent_insert and for index versioning. storage/maria/ma_extra.c: Versioning of count(*) and checksum: - Use share->state.state instead of info->state - share->concurrent_insert -> share->non_transactional_concurrent_insert - Don't update share->state.state from info->state if transactional table Optimization: - Don't flush io_cache or bitmap if we are using FLUSH_IGNORE_CHANGED storage/maria/ma_info.c: Get most state information from current state storage/maria/ma_init.c: Add hash table and free function to store states for closed tables Install hook for transaction commit/rollback to update history state storage/maria/ma_key_recover.c: Versioning of count(*) and checksum: - Use share->state.state instead of info->state storage/maria/ma_locking.c: Versioning of count(*) and checksum: - Call virtual functions (if exists) to restore/update status - Move _ma_xxx_status() functions to ma_state.c info->s -> share storage/maria/ma_open.c: Versioning of count(*) and checksum: - For not transactional tables, set info->state to point to new allocated state structure. - Initialize new info->state_start variable that points to state at start of transaction - Copy old history states from hash table (maria_stored_states) first time the table is opened - Split flag share->concurrent_insert to non_transactional_concurrent_insert & lock_key_tree - For now, only enable versioning of tables without keys (to be fixed in soon!) - Added new virtual function to restore status in maria_lock_database) More DBUG storage/maria/ma_page.c: Versioning of count(*) and checksum: - Use share->state.state instead of info->state - Modify share->state.state.key_file_length under share->intern_lock storage/maria/ma_range.c: Versioning of count(*) and checksum: - Lock trees based on share->lock_key_trees info->s -> share storage/maria/ma_recovery.c: Versioning of count(*) and checksum: - Use share->state.state instead of info->state - Update state information on close and when reenabling logging storage/maria/ma_rkey.c: Versioning of count(*) and checksum: - Lock trees based on share->lock_key_trees storage/maria/ma_rnext.c: Versioning of count(*) and checksum: - Lock trees based on share->lock_key_trees storage/maria/ma_rnext_same.c: Versioning of count(*) and checksum: - Lock trees based on share->lock_key_trees - Only skip rows based on file length if non_transactional_concurrent_insert is set storage/maria/ma_rprev.c: Versioning of count(*) and checksum: - Lock trees based on share->lock_key_trees storage/maria/ma_rsame.c: Versioning of count(*) and checksum: - Lock trees based on share->lock_key_trees storage/maria/ma_sort.c: Use share->state.state instead of info->state Fixed indentation storage/maria/ma_static.c: Added maria_stored_state storage/maria/ma_update.c: Versioning of count(*) and checksum: - Always update info->state->checksum and info->state->records - Remove optimization for index file update as it doesn't work for transactional tables storage/maria/ma_write.c: Versioning of count(*) and checksum: - Always update info->state->checksum and info->state->records storage/maria/maria_def.h: Move MARIA_STATUS_INFO to ma_state.h Changes to MARIA_SHARE: - Added state_history to store count(*)/checksum states - Added in_trans as counter if table is used by running transactions - Split concurrent_insert into lock_key_trees and on_transactional_concurrent_insert. - Added virtual function lock_restore_status Changes to MARIA_HA: - save_state -> state_save - Added state_start to store state at start of transaction storage/maria/maria_pack.c: Versioning of count(*) and checksum: - Use share->state.state instead of info->state Indentation fixes storage/maria/trnman.c: Added hook 'trnnam_end_trans_hook' that is called when transaction ends Added trn->used_tables that is used to an entry for all tables used by transaction More DBUG Changed return type of trnman_end_trn() to my_bool Added trnman_get_min_trid() to get minimum trid in use. Added trnman_exists_active_transactions() to check if there exist a running transaction started between two commit id storage/maria/trnman.h: Added 'used_tables' Moved all pointers into same groups to get better memory alignment storage/maria/trnman_public.h: Added prototypes for new functions and variables Chagned return type of trnman_end_trn() to my_bool storage/myisam/ha_myisam.cc: Added argument to end_bulk_insert() if operation should be aborted storage/myisam/ha_myisam.h: Added argument to end_bulk_insert() if operation should be aborted storage/maria/ma_state.c: Functions to handle state of count(*) and checksum storage/maria/ma_state.h: Structures and declarations to handle state of count(*) and checksum
This commit is contained in:
parent
126c1228f5
commit
5099033c26
@ -427,7 +427,7 @@ my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, ulonglong key_map,
|
|||||||
|
|
||||||
int maria_init_bulk_insert(MARIA_HA *info, ulong cache_size, ha_rows rows);
|
int maria_init_bulk_insert(MARIA_HA *info, ulong cache_size, ha_rows rows);
|
||||||
void maria_flush_bulk_insert(MARIA_HA *info, uint inx);
|
void maria_flush_bulk_insert(MARIA_HA *info, uint inx);
|
||||||
void maria_end_bulk_insert(MARIA_HA *info);
|
void maria_end_bulk_insert(MARIA_HA *info, my_bool table_will_be_deleted);
|
||||||
int maria_assign_to_pagecache(MARIA_HA *info, ulonglong key_map,
|
int maria_assign_to_pagecache(MARIA_HA *info, ulonglong key_map,
|
||||||
PAGECACHE *key_cache);
|
PAGECACHE *key_cache);
|
||||||
void maria_change_pagecache(PAGECACHE *old_key_cache,
|
void maria_change_pagecache(PAGECACHE *old_key_cache,
|
||||||
|
@ -66,8 +66,8 @@ void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit,
|
|||||||
tree_element_free free_element, void *custom_arg);
|
tree_element_free free_element, void *custom_arg);
|
||||||
void delete_tree(TREE*);
|
void delete_tree(TREE*);
|
||||||
void reset_tree(TREE*);
|
void reset_tree(TREE*);
|
||||||
/* similar to delete tree, except we do not my_free() blocks in mem_root
|
|
||||||
*/
|
/* similar to delete tree, except we do not my_free() blocks in mem_root */
|
||||||
#define is_tree_inited(tree) ((tree)->root != 0)
|
#define is_tree_inited(tree) ((tree)->root != 0)
|
||||||
|
|
||||||
/* Functions on leafs */
|
/* Functions on leafs */
|
||||||
@ -86,6 +86,7 @@ void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
|
|||||||
int r_offs);
|
int r_offs);
|
||||||
ha_rows tree_record_pos(TREE *tree, const void *key,
|
ha_rows tree_record_pos(TREE *tree, const void *key,
|
||||||
enum ha_rkey_function search_flag, void *custom_arg);
|
enum ha_rkey_function search_flag, void *custom_arg);
|
||||||
|
#define reset_free_element(tree) (tree)->free= 0
|
||||||
|
|
||||||
#define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*))
|
#define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*))
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ basedir=.
|
|||||||
EXTRA_ARG="--windows"
|
EXTRA_ARG="--windows"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
INSTALL_CMD="$scriptdir/mysql_install_db --no-defaults $EXTRA_ARG --basedir=$basedir --datadir=mysql-test/$ldata --srcdir=."
|
INSTALL_CMD="$scriptdir/mysql_install_db --no-defaults $EXTRA_ARG --datadir=mysql-test/$ldata --srcdir=."
|
||||||
echo "running $INSTALL_CMD"
|
echo "running $INSTALL_CMD"
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
set global maria_page_checksum=1;
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
create table t1 (i int) engine=maria;
|
create table t1 (i int) engine=maria;
|
||||||
show create table t1;
|
show create table t1;
|
||||||
@ -13,9 +14,15 @@ select i from t1;
|
|||||||
i
|
i
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
/* should see nothing */
|
/* should see nothing */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
i
|
i
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
0
|
||||||
lock tables t1 write concurrent;
|
lock tables t1 write concurrent;
|
||||||
insert into t1 values (3);
|
insert into t1 values (3);
|
||||||
insert into t1 values (4);
|
insert into t1 values (4);
|
||||||
@ -24,6 +31,9 @@ select i from t1;
|
|||||||
i
|
i
|
||||||
3
|
3
|
||||||
4
|
4
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
unlock tables;
|
unlock tables;
|
||||||
lock tables t1 write concurrent;
|
lock tables t1 write concurrent;
|
||||||
insert into t1 values (5);
|
insert into t1 values (5);
|
||||||
@ -33,6 +43,18 @@ i
|
|||||||
3
|
3
|
||||||
4
|
4
|
||||||
5
|
5
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
3
|
||||||
|
lock tables t1 write concurrent;
|
||||||
|
/* should see 3, 4 */
|
||||||
|
select i from t1;
|
||||||
|
i
|
||||||
|
3
|
||||||
|
4
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
insert into t1 values (6);
|
insert into t1 values (6);
|
||||||
/* Should see 1, 2, 6 */
|
/* Should see 1, 2, 6 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
@ -40,6 +62,9 @@ i
|
|||||||
1
|
1
|
||||||
2
|
2
|
||||||
6
|
6
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
3
|
||||||
unlock tables;
|
unlock tables;
|
||||||
lock tables t1 write concurrent;
|
lock tables t1 write concurrent;
|
||||||
/* Should see 1, 2, 3, 4 and 6 */
|
/* Should see 1, 2, 3, 4 and 6 */
|
||||||
@ -50,12 +75,18 @@ i
|
|||||||
3
|
3
|
||||||
4
|
4
|
||||||
6
|
6
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
5
|
||||||
/* should see 3, 4, 5 */
|
/* should see 3, 4, 5 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
i
|
i
|
||||||
3
|
3
|
||||||
4
|
4
|
||||||
5
|
5
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
3
|
||||||
unlock tables;
|
unlock tables;
|
||||||
/* should see 1, 2, 3, 4, 5, 6 */
|
/* should see 1, 2, 3, 4, 5, 6 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
@ -66,6 +97,9 @@ i
|
|||||||
4
|
4
|
||||||
5
|
5
|
||||||
6
|
6
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
6
|
||||||
unlock tables;
|
unlock tables;
|
||||||
/* should see 1, 2, 3, 4, 5, 6 */
|
/* should see 1, 2, 3, 4, 5, 6 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
@ -76,4 +110,31 @@ i
|
|||||||
4
|
4
|
||||||
5
|
5
|
||||||
6
|
6
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
6
|
||||||
|
insert into t1 values (7);
|
||||||
|
/* should see 3, 4, 7 */
|
||||||
|
select i from t1;
|
||||||
|
i
|
||||||
|
3
|
||||||
|
4
|
||||||
|
7
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
3
|
||||||
|
unlock tables;
|
||||||
|
/* should see 1, 2, 3, 4, 5, 6, 7 */
|
||||||
|
select i from t1;
|
||||||
|
i
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
7
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -355,6 +355,9 @@ INSERT into t2 values (1,1,1), (2,2,2);
|
|||||||
optimize table t1;
|
optimize table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 optimize status OK
|
test.t1 optimize status OK
|
||||||
|
check table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
show index from t1;
|
show index from t1;
|
||||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||||
t1 1 b 1 b A 5 NULL NULL YES BTREE
|
t1 1 b 1 b A 5 NULL NULL YES BTREE
|
||||||
@ -2100,6 +2103,11 @@ test.t2 check status OK
|
|||||||
select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
|
select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
|
||||||
t1 t2 length(t3) length(t4) length(t5) length(t6) t7 t8
|
t1 t2 length(t3) length(t4) length(t5) length(t6) t7 t8
|
||||||
1 a 256 256 4096 4096
|
1 a 256 256 4096 4096
|
||||||
|
drop table t2;
|
||||||
|
create table t2 (primary key (auto)) engine=maria row_format=dynamic select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
|
||||||
|
check table t2;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t2 check status OK
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
CREATE TABLE t1 (seq int, s1 int, s2 blob);
|
CREATE TABLE t1 (seq int, s1 int, s2 blob);
|
||||||
insert into t1 values (1, 1, MD5(1));
|
insert into t1 values (1, 1, MD5(1));
|
||||||
@ -2242,6 +2250,12 @@ t
|
|||||||
9999-12-31 23:59:59
|
9999-12-31 23:59:59
|
||||||
2003-01-00 00:00:00
|
2003-01-00 00:00:00
|
||||||
2003-00-00 00:00:00
|
2003-00-00 00:00:00
|
||||||
|
optimize table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 optimize status OK
|
||||||
|
check table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
delete from t1 where t > 0;
|
delete from t1 where t > 0;
|
||||||
optimize table t1;
|
optimize table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
|
@ -416,7 +416,7 @@ a
|
|||||||
insert into t1 values (35);
|
insert into t1 values (35);
|
||||||
insert into t1 values (NULL);
|
insert into t1 values (NULL);
|
||||||
insert into t1 values (NULL);
|
insert into t1 values (NULL);
|
||||||
ERROR 23000: Duplicate entry '35' for key 'PRIMARY'
|
Got one of the listed errors
|
||||||
select * from t1 order by a;
|
select * from t1 order by a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
|
@ -276,7 +276,7 @@ connection server1;
|
|||||||
insert into t1 values (35);
|
insert into t1 values (35);
|
||||||
insert into t1 values (NULL);
|
insert into t1 values (NULL);
|
||||||
connection server2;
|
connection server2;
|
||||||
--error ER_DUP_ENTRY
|
--error ER_DUP_ENTRY, ER_DUP_KEY
|
||||||
insert into t1 values (NULL);
|
insert into t1 values (NULL);
|
||||||
select * from t1 order by a;
|
select * from t1 order by a;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
-- source include/have_maria.inc
|
-- source include/have_maria.inc
|
||||||
|
set global maria_page_checksum=1;
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
@ -19,41 +20,68 @@ insert into t1 values (1);
|
|||||||
insert into t1 values (2);
|
insert into t1 values (2);
|
||||||
/* should see 1 and 2 */
|
/* should see 1 and 2 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
connect (con2,localhost,root,,);
|
connect (con2,localhost,root,,);
|
||||||
connection con2;
|
connection con2;
|
||||||
/* should see nothing */
|
/* should see nothing */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
lock tables t1 write concurrent;
|
lock tables t1 write concurrent;
|
||||||
insert into t1 values (3);
|
insert into t1 values (3);
|
||||||
insert into t1 values (4);
|
insert into t1 values (4);
|
||||||
/* should see 3 and 4 */
|
/* should see 3 and 4 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
lock tables t1 write concurrent;
|
lock tables t1 write concurrent;
|
||||||
insert into t1 values (5);
|
insert into t1 values (5);
|
||||||
/* should see 3, 4 and 5 */
|
/* should see 3, 4 and 5 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
|
connect (con3,localhost,root,,);
|
||||||
|
connection con3;
|
||||||
|
lock tables t1 write concurrent;
|
||||||
|
/* should see 3, 4 */
|
||||||
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
connection con1;
|
connection con1;
|
||||||
insert into t1 values (6);
|
insert into t1 values (6);
|
||||||
/* Should see 1, 2, 6 */
|
/* Should see 1, 2, 6 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
lock tables t1 write concurrent;
|
lock tables t1 write concurrent;
|
||||||
/* Should see 1, 2, 3, 4 and 6 */
|
/* Should see 1, 2, 3, 4 and 6 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
connection con2;
|
connection con2;
|
||||||
/* should see 3, 4, 5 */
|
/* should see 3, 4, 5 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
/* should see 1, 2, 3, 4, 5, 6 */
|
/* should see 1, 2, 3, 4, 5, 6 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
connection con1;
|
connection con1;
|
||||||
unlock tables;
|
unlock tables;
|
||||||
/* should see 1, 2, 3, 4, 5, 6 */
|
/* should see 1, 2, 3, 4, 5, 6 */
|
||||||
select i from t1;
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
|
connection con3;
|
||||||
|
insert into t1 values (7);
|
||||||
|
/* should see 3, 4, 7 */
|
||||||
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
unlock tables;
|
||||||
|
/* should see 1, 2, 3, 4, 5, 6, 7 */
|
||||||
|
select i from t1;
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
|
connection default;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
#
|
||||||
|
# This can't be run with --extern as we are acccessing the tables in the
|
||||||
|
# database directly
|
||||||
|
#
|
||||||
|
|
||||||
-- source include/have_maria.inc
|
-- source include/have_maria.inc
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Testing of potential probelms in Maria
|
# Testing of potential problems in Maria
|
||||||
# This code was initially taken from myisam.test
|
# This code was initially taken from myisam.test
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -377,6 +377,7 @@ INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,
|
|||||||
create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
|
create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
|
||||||
INSERT into t2 values (1,1,1), (2,2,2);
|
INSERT into t2 values (1,1,1), (2,2,2);
|
||||||
optimize table t1;
|
optimize table t1;
|
||||||
|
check table t1;
|
||||||
show index from t1;
|
show index from t1;
|
||||||
explain select * from t1,t2 where t1.a=t2.a;
|
explain select * from t1,t2 where t1.a=t2.a;
|
||||||
explain select * from t1,t2 force index(a) where t1.a=t2.a;
|
explain select * from t1,t2 force index(a) where t1.a=t2.a;
|
||||||
@ -1352,6 +1353,9 @@ insert into t1 values (10,1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','on
|
|||||||
create table t2 (primary key (auto)) engine=maria row_format=page select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
|
create table t2 (primary key (auto)) engine=maria row_format=page select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
|
||||||
check table t1,t2;
|
check table t1,t2;
|
||||||
select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
|
select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
|
||||||
|
drop table t2;
|
||||||
|
create table t2 (primary key (auto)) engine=maria row_format=dynamic select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
|
||||||
|
check table t2;
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
# Test UPDATE with small BLOB which fits on head page
|
# Test UPDATE with small BLOB which fits on head page
|
||||||
@ -1461,6 +1465,8 @@ drop table t1, t2, t3;
|
|||||||
create table t1 (t datetime) engine=maria;
|
create table t1 (t datetime) engine=maria;
|
||||||
insert into t1 values (101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030100000000),(20030000000000);
|
insert into t1 values (101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030100000000),(20030000000000);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
optimize table t1;
|
||||||
|
check table t1;
|
||||||
delete from t1 where t > 0;
|
delete from t1 where t > 0;
|
||||||
optimize table t1;
|
optimize table t1;
|
||||||
check table t1;
|
check table t1;
|
||||||
|
@ -318,7 +318,7 @@ my_bool my_hash_insert(HASH *info,const uchar *record)
|
|||||||
LINT_INIT(ptr_to_rec);
|
LINT_INIT(ptr_to_rec);
|
||||||
LINT_INIT(ptr_to_rec2);
|
LINT_INIT(ptr_to_rec2);
|
||||||
|
|
||||||
if (HASH_UNIQUE & info->flags)
|
if (info->flags & HASH_UNIQUE)
|
||||||
{
|
{
|
||||||
uchar *key= (uchar*) hash_key(info, record, &idx, 1);
|
uchar *key= (uchar*) hash_key(info, record, &idx, 1);
|
||||||
if (hash_search(info, key, idx))
|
if (hash_search(info, key, idx))
|
||||||
|
@ -5393,7 +5393,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
|
|||||||
|
|
||||||
int Field_year::store(double nr)
|
int Field_year::store(double nr)
|
||||||
{
|
{
|
||||||
if (nr < 0.0 || nr >= 2155.0)
|
if (nr < 0.0 || nr > 2155.0)
|
||||||
{
|
{
|
||||||
(void) Field_year::store((longlong) -1, FALSE);
|
(void) Field_year::store((longlong) -1, FALSE);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -4258,11 +4258,11 @@ void ha_ndbcluster::start_bulk_insert(ha_rows rows)
|
|||||||
/**
|
/**
|
||||||
End of an insert.
|
End of an insert.
|
||||||
*/
|
*/
|
||||||
int ha_ndbcluster::end_bulk_insert()
|
int ha_ndbcluster::end_bulk_insert(bool abort)
|
||||||
{
|
{
|
||||||
int error= 0;
|
int error= 0;
|
||||||
|
|
||||||
DBUG_ENTER("end_bulk_insert");
|
DBUG_ENTER("end_bulk_insert");
|
||||||
|
|
||||||
// Check if last inserts need to be flushed
|
// Check if last inserts need to be flushed
|
||||||
if (m_bulk_insert_not_flushed)
|
if (m_bulk_insert_not_flushed)
|
||||||
{
|
{
|
||||||
@ -4578,7 +4578,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
|
|||||||
Thd_ndb *thd_ndb= get_thd_ndb(thd);
|
Thd_ndb *thd_ndb= get_thd_ndb(thd);
|
||||||
Ndb *ndb= thd_ndb->ndb;
|
Ndb *ndb= thd_ndb->ndb;
|
||||||
|
|
||||||
DBUG_PRINT("enter", ("this: 0x%lx thd: 0x%lx thd_ndb: %lx "
|
DBUG_PRINT("enter", ("this: 0x%lx thd: 0x%lx thd_ndb: 0x%lx "
|
||||||
"thd_ndb->lock_count: %d",
|
"thd_ndb->lock_count: %d",
|
||||||
(long) this, (long) thd, (long) thd_ndb,
|
(long) this, (long) thd, (long) thd_ndb,
|
||||||
thd_ndb->lock_count));
|
thd_ndb->lock_count));
|
||||||
|
@ -328,7 +328,7 @@ class ha_ndbcluster: public handler
|
|||||||
double scan_time();
|
double scan_time();
|
||||||
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
|
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
|
||||||
void start_bulk_insert(ha_rows rows);
|
void start_bulk_insert(ha_rows rows);
|
||||||
int end_bulk_insert();
|
int end_bulk_insert(bool abort);
|
||||||
|
|
||||||
static Thd_ndb* seize_thd_ndb();
|
static Thd_ndb* seize_thd_ndb();
|
||||||
static void release_thd_ndb(Thd_ndb* thd_ndb);
|
static void release_thd_ndb(Thd_ndb* thd_ndb);
|
||||||
|
@ -2999,13 +2999,14 @@ void ha_partition::start_bulk_insert(ha_rows rows)
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
end_bulk_insert()
|
end_bulk_insert()
|
||||||
|
abort 1 if table will be deleted (error condition)
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
>0 Error code
|
>0 Error code
|
||||||
0 Success
|
0 Success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ha_partition::end_bulk_insert()
|
int ha_partition::end_bulk_insert(bool abort)
|
||||||
{
|
{
|
||||||
int error= 0;
|
int error= 0;
|
||||||
handler **file;
|
handler **file;
|
||||||
@ -3015,7 +3016,7 @@ int ha_partition::end_bulk_insert()
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
int tmp;
|
int tmp;
|
||||||
if ((tmp= (*file)->ha_end_bulk_insert()))
|
if ((tmp= (*file)->ha_end_bulk_insert(abort)))
|
||||||
error= tmp;
|
error= tmp;
|
||||||
} while (*(++file));
|
} while (*(++file));
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
|
@ -315,7 +315,7 @@ public:
|
|||||||
virtual int delete_row(const uchar * buf);
|
virtual int delete_row(const uchar * buf);
|
||||||
virtual int delete_all_rows(void);
|
virtual int delete_all_rows(void);
|
||||||
virtual void start_bulk_insert(ha_rows rows);
|
virtual void start_bulk_insert(ha_rows rows);
|
||||||
virtual int end_bulk_insert();
|
virtual int end_bulk_insert(bool);
|
||||||
|
|
||||||
virtual bool is_fatal_error(int error, uint flags)
|
virtual bool is_fatal_error(int error, uint flags)
|
||||||
{
|
{
|
||||||
|
@ -2116,11 +2116,14 @@ void handler::print_error(int error, myf errflag)
|
|||||||
break;
|
break;
|
||||||
case HA_ERR_FOUND_DUPP_KEY:
|
case HA_ERR_FOUND_DUPP_KEY:
|
||||||
{
|
{
|
||||||
uint key_nr=get_dup_key(error);
|
if (table)
|
||||||
if ((int) key_nr >= 0)
|
|
||||||
{
|
{
|
||||||
print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
|
uint key_nr=get_dup_key(error);
|
||||||
DBUG_VOID_RETURN;
|
if ((int) key_nr >= 0)
|
||||||
|
{
|
||||||
|
print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
textno=ER_DUP_KEY;
|
textno=ER_DUP_KEY;
|
||||||
break;
|
break;
|
||||||
|
@ -1115,10 +1115,10 @@ public:
|
|||||||
estimation_rows_to_insert= rows;
|
estimation_rows_to_insert= rows;
|
||||||
start_bulk_insert(rows);
|
start_bulk_insert(rows);
|
||||||
}
|
}
|
||||||
int ha_end_bulk_insert()
|
int ha_end_bulk_insert(bool abort)
|
||||||
{
|
{
|
||||||
estimation_rows_to_insert= 0;
|
estimation_rows_to_insert= 0;
|
||||||
return end_bulk_insert();
|
return end_bulk_insert(abort);
|
||||||
}
|
}
|
||||||
int ha_bulk_update_row(const uchar *old_data, uchar *new_data,
|
int ha_bulk_update_row(const uchar *old_data, uchar *new_data,
|
||||||
uint *dup_key_found);
|
uint *dup_key_found);
|
||||||
@ -1736,7 +1736,7 @@ private:
|
|||||||
virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
|
virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
|
||||||
{ return HA_ADMIN_NOT_IMPLEMENTED; }
|
{ return HA_ADMIN_NOT_IMPLEMENTED; }
|
||||||
virtual void start_bulk_insert(ha_rows rows) {}
|
virtual void start_bulk_insert(ha_rows rows) {}
|
||||||
virtual int end_bulk_insert() { return 0; }
|
virtual int end_bulk_insert(bool abort) { return 0; }
|
||||||
virtual int index_read(uchar * buf, const uchar * key, uint key_len,
|
virtual int index_read(uchar * buf, const uchar * key, uint key_len,
|
||||||
enum ha_rkey_function find_flag)
|
enum ha_rkey_function find_flag)
|
||||||
{ return HA_ERR_WRONG_COMMAND; }
|
{ return HA_ERR_WRONG_COMMAND; }
|
||||||
|
14
sql/item.cc
14
sql/item.cc
@ -1440,7 +1440,9 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
|||||||
if (collation == &my_charset_bin)
|
if (collation == &my_charset_bin)
|
||||||
{
|
{
|
||||||
if (derivation <= dt.derivation)
|
if (derivation <= dt.derivation)
|
||||||
; // Do nothing
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set(dt);
|
set(dt);
|
||||||
@ -1452,13 +1454,11 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
|||||||
{
|
{
|
||||||
set(dt);
|
set(dt);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
; // Do nothing
|
|
||||||
}
|
}
|
||||||
else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
|
else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
|
||||||
left_is_superset(this, &dt))
|
left_is_superset(this, &dt))
|
||||||
{
|
{
|
||||||
// Do nothing
|
/* Do nothing */
|
||||||
}
|
}
|
||||||
else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
|
else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
|
||||||
left_is_superset(&dt, this))
|
left_is_superset(&dt, this))
|
||||||
@ -1469,7 +1469,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
|||||||
derivation < dt.derivation &&
|
derivation < dt.derivation &&
|
||||||
dt.derivation >= DERIVATION_SYSCONST)
|
dt.derivation >= DERIVATION_SYSCONST)
|
||||||
{
|
{
|
||||||
// Do nothing;
|
/* Do nothing */
|
||||||
}
|
}
|
||||||
else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
|
else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
|
||||||
dt.derivation < derivation &&
|
dt.derivation < derivation &&
|
||||||
@ -1486,7 +1486,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
|||||||
}
|
}
|
||||||
else if (derivation < dt.derivation)
|
else if (derivation < dt.derivation)
|
||||||
{
|
{
|
||||||
// Do nothing
|
/* Do nothing */
|
||||||
}
|
}
|
||||||
else if (dt.derivation < derivation)
|
else if (dt.derivation < derivation)
|
||||||
{
|
{
|
||||||
@ -1496,7 +1496,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
|||||||
{
|
{
|
||||||
if (collation == dt.collation)
|
if (collation == dt.collation)
|
||||||
{
|
{
|
||||||
// Do nothing
|
/* Do nothing */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7623,7 +7623,7 @@ Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability *
|
|||||||
ultimately. Still todo: fix
|
ultimately. Still todo: fix
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if ((local_error= m_table->file->ha_end_bulk_insert()))
|
if ((local_error= m_table->file->ha_end_bulk_insert(0)))
|
||||||
{
|
{
|
||||||
m_table->file->print_error(local_error, MYF(0));
|
m_table->file->print_error(local_error, MYF(0));
|
||||||
}
|
}
|
||||||
|
@ -962,7 +962,7 @@ int Write_rows_log_event_old::do_after_row_operations(TABLE *table, int error)
|
|||||||
fires bug#27077
|
fires bug#27077
|
||||||
todo: explain or fix
|
todo: explain or fix
|
||||||
*/
|
*/
|
||||||
if ((local_error= table->file->ha_end_bulk_insert()))
|
if ((local_error= table->file->ha_end_bulk_insert(0)))
|
||||||
{
|
{
|
||||||
table->file->print_error(local_error, MYF(0));
|
table->file->print_error(local_error, MYF(0));
|
||||||
}
|
}
|
||||||
@ -2633,7 +2633,7 @@ Write_rows_log_event_old::do_after_row_operations(const Slave_reporting_capabili
|
|||||||
fires bug#27077
|
fires bug#27077
|
||||||
todo: explain or fix
|
todo: explain or fix
|
||||||
*/
|
*/
|
||||||
if ((local_error= m_table->file->ha_end_bulk_insert()))
|
if ((local_error= m_table->file->ha_end_bulk_insert(0)))
|
||||||
{
|
{
|
||||||
m_table->file->print_error(local_error, MYF(0));
|
m_table->file->print_error(local_error, MYF(0));
|
||||||
}
|
}
|
||||||
|
@ -2669,7 +2669,7 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
to_error_log:
|
to_error_log:
|
||||||
if (!thd || MyFlags & ME_NOREFRESH)
|
if (!thd || (MyFlags & ME_NOREFRESH))
|
||||||
(*func)("%s: %s", my_progname_short, str); /* purecov: inspected */
|
(*func)("%s: %s", my_progname_short, str); /* purecov: inspected */
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
@ -385,6 +385,7 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
|
|||||||
|
|
||||||
void net_end_statement(THD *thd)
|
void net_end_statement(THD *thd)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("net_end_statement");
|
||||||
DBUG_ASSERT(! thd->main_da.is_sent);
|
DBUG_ASSERT(! thd->main_da.is_sent);
|
||||||
|
|
||||||
/* Can not be true, but do not take chances in production. */
|
/* Can not be true, but do not take chances in production. */
|
||||||
@ -421,6 +422,7 @@ void net_end_statement(THD *thd)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
thd->main_da.is_sent= TRUE;
|
thd->main_da.is_sent= TRUE;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,6 +367,7 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
|
|||||||
void
|
void
|
||||||
Diagnostics_area::reset_diagnostics_area()
|
Diagnostics_area::reset_diagnostics_area()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("reset_diagnostics_area");
|
||||||
#ifdef DBUG_OFF
|
#ifdef DBUG_OFF
|
||||||
can_overwrite_status= FALSE;
|
can_overwrite_status= FALSE;
|
||||||
/** Don't take chances in production */
|
/** Don't take chances in production */
|
||||||
@ -380,6 +381,7 @@ Diagnostics_area::reset_diagnostics_area()
|
|||||||
is_sent= FALSE;
|
is_sent= FALSE;
|
||||||
/** Tiny reset in debug mode to see garbage right away */
|
/** Tiny reset in debug mode to see garbage right away */
|
||||||
m_status= DA_EMPTY;
|
m_status= DA_EMPTY;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -393,6 +395,7 @@ Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
|
|||||||
ulonglong last_insert_id_arg,
|
ulonglong last_insert_id_arg,
|
||||||
const char *message_arg)
|
const char *message_arg)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("set_ok_status");
|
||||||
DBUG_ASSERT(! is_set());
|
DBUG_ASSERT(! is_set());
|
||||||
/* Refuse to overwrite an error with an OK packet. */
|
/* Refuse to overwrite an error with an OK packet. */
|
||||||
if (is_error())
|
if (is_error())
|
||||||
@ -407,6 +410,7 @@ Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
|
|||||||
else
|
else
|
||||||
m_message[0]= '\0';
|
m_message[0]= '\0';
|
||||||
m_status= DA_OK;
|
m_status= DA_OK;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -417,8 +421,8 @@ Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
|
|||||||
void
|
void
|
||||||
Diagnostics_area::set_eof_status(THD *thd)
|
Diagnostics_area::set_eof_status(THD *thd)
|
||||||
{
|
{
|
||||||
/** Only allowed to report eof if has not yet reported an error */
|
DBUG_ENTER("set_eof_status");
|
||||||
|
/* Only allowed to report eof if has not yet reported an error */
|
||||||
DBUG_ASSERT(! is_set());
|
DBUG_ASSERT(! is_set());
|
||||||
/* Refuse to overwrite an error with an EOF packet. */
|
/* Refuse to overwrite an error with an EOF packet. */
|
||||||
if (is_error())
|
if (is_error())
|
||||||
@ -433,6 +437,7 @@ Diagnostics_area::set_eof_status(THD *thd)
|
|||||||
m_total_warn_count= thd->spcont ? 0 : thd->total_warn_count;
|
m_total_warn_count= thd->spcont ? 0 : thd->total_warn_count;
|
||||||
|
|
||||||
m_status= DA_EOF;
|
m_status= DA_EOF;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -443,6 +448,7 @@ void
|
|||||||
Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
|
Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
|
||||||
const char *message_arg)
|
const char *message_arg)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("set_error_status");
|
||||||
/*
|
/*
|
||||||
Only allowed to report error if has not yet reported a success
|
Only allowed to report error if has not yet reported a success
|
||||||
The only exception is when we flush the message to the client,
|
The only exception is when we flush the message to the client,
|
||||||
@ -451,9 +457,10 @@ Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
|
|||||||
DBUG_ASSERT(! is_set() || can_overwrite_status);
|
DBUG_ASSERT(! is_set() || can_overwrite_status);
|
||||||
|
|
||||||
m_sql_errno= sql_errno_arg;
|
m_sql_errno= sql_errno_arg;
|
||||||
strmake(m_message, message_arg, sizeof(m_message));
|
strmake(m_message, message_arg, sizeof(m_message)-1);
|
||||||
|
|
||||||
m_status= DA_ERROR;
|
m_status= DA_ERROR;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -555,6 +555,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
bool transactional_table, joins_freed= FALSE;
|
bool transactional_table, joins_freed= FALSE;
|
||||||
bool changed;
|
bool changed;
|
||||||
bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED);
|
bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED);
|
||||||
|
bool using_bulk_insert= 0;
|
||||||
uint value_count;
|
uint value_count;
|
||||||
ulong counter = 1;
|
ulong counter = 1;
|
||||||
ulonglong id;
|
ulonglong id;
|
||||||
@ -716,8 +717,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
values_list.elements, and - if nothing else - to initialize
|
values_list.elements, and - if nothing else - to initialize
|
||||||
the code to make the call of end_bulk_insert() below safe.
|
the code to make the call of end_bulk_insert() below safe.
|
||||||
*/
|
*/
|
||||||
if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode)
|
if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode &&
|
||||||
|
values_list.elements > 1)
|
||||||
|
{
|
||||||
|
using_bulk_insert= 1;
|
||||||
table->file->ha_start_bulk_insert(values_list.elements);
|
table->file->ha_start_bulk_insert(values_list.elements);
|
||||||
|
}
|
||||||
|
|
||||||
thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
|
thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
@ -831,7 +836,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
auto_inc values from the delayed_insert thread as they share TABLE.
|
auto_inc values from the delayed_insert thread as they share TABLE.
|
||||||
*/
|
*/
|
||||||
table->file->ha_release_auto_increment();
|
table->file->ha_release_auto_increment();
|
||||||
if (!thd->prelocked_mode && table->file->ha_end_bulk_insert() && !error)
|
if (using_bulk_insert && table->file->ha_end_bulk_insert(0) && !error)
|
||||||
{
|
{
|
||||||
table->file->print_error(my_errno,MYF(0));
|
table->file->print_error(my_errno,MYF(0));
|
||||||
error=1;
|
error=1;
|
||||||
@ -1167,7 +1172,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
bool res= 0;
|
bool res= 0;
|
||||||
table_map map= 0;
|
table_map map= 0;
|
||||||
DBUG_ENTER("mysql_prepare_insert");
|
DBUG_ENTER("mysql_prepare_insert");
|
||||||
DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
|
DBUG_PRINT("enter", ("table_list 0x%lx table 0x%lx view %d",
|
||||||
(ulong)table_list, (ulong)table,
|
(ulong)table_list, (ulong)table,
|
||||||
(int)insert_into_view));
|
(int)insert_into_view));
|
||||||
/* INSERT should have a SELECT or VALUES clause */
|
/* INSERT should have a SELECT or VALUES clause */
|
||||||
@ -3108,7 +3113,7 @@ bool select_insert::send_eof()
|
|||||||
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
|
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
|
||||||
trans_table, table->file->table_type()));
|
trans_table, table->file->table_type()));
|
||||||
|
|
||||||
error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0;
|
error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert(0) : 0;
|
||||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||||
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
||||||
|
|
||||||
@ -3195,7 +3200,7 @@ void select_insert::abort() {
|
|||||||
before.
|
before.
|
||||||
*/
|
*/
|
||||||
if (!thd->prelocked_mode)
|
if (!thd->prelocked_mode)
|
||||||
table->file->ha_end_bulk_insert();
|
table->file->ha_end_bulk_insert(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If at least one row has been inserted/modified and will stay in
|
If at least one row has been inserted/modified and will stay in
|
||||||
|
@ -391,7 +391,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
error= read_sep_field(thd, info, table_list, fields_vars,
|
error= read_sep_field(thd, info, table_list, fields_vars,
|
||||||
set_fields, set_values, read_info,
|
set_fields, set_values, read_info,
|
||||||
*enclosed, skip_lines, ignore);
|
*enclosed, skip_lines, ignore);
|
||||||
if (!thd->prelocked_mode && table->file->ha_end_bulk_insert() && !error)
|
if (!thd->prelocked_mode && table->file->ha_end_bulk_insert(0) && !error)
|
||||||
{
|
{
|
||||||
table->file->print_error(my_errno, MYF(0));
|
table->file->print_error(my_errno, MYF(0));
|
||||||
error= 1;
|
error= 1;
|
||||||
|
@ -2612,10 +2612,12 @@ end_with_restore_list:
|
|||||||
#endif /* HAVE_REPLICATION */
|
#endif /* HAVE_REPLICATION */
|
||||||
|
|
||||||
case SQLCOM_ALTER_TABLE:
|
case SQLCOM_ALTER_TABLE:
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
|
||||||
{
|
{
|
||||||
ulong priv=0;
|
ulong priv=0;
|
||||||
ulong priv_needed= ALTER_ACL;
|
ulong priv_needed= ALTER_ACL;
|
||||||
|
|
||||||
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
|
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
|
||||||
so we have to use a copy of this structure to make execution
|
so we have to use a copy of this structure to make execution
|
||||||
@ -2625,7 +2627,7 @@ end_with_restore_list:
|
|||||||
HA_CREATE_INFO create_info(lex->create_info);
|
HA_CREATE_INFO create_info(lex->create_info);
|
||||||
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||||
|
|
||||||
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
|
if (thd->is_fatal_error) /* OOM creating a copy of alter_info */
|
||||||
goto error;
|
goto error;
|
||||||
/*
|
/*
|
||||||
We also require DROP priv for ALTER TABLE ... DROP PARTITION, as well
|
We also require DROP priv for ALTER TABLE ... DROP PARTITION, as well
|
||||||
@ -4692,11 +4694,6 @@ create_sp_error:
|
|||||||
if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT))
|
if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT))
|
||||||
thd->row_count_func= -1;
|
thd->row_count_func= -1;
|
||||||
|
|
||||||
goto finish;
|
|
||||||
|
|
||||||
error:
|
|
||||||
res= TRUE;
|
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (need_start_waiting)
|
if (need_start_waiting)
|
||||||
{
|
{
|
||||||
@ -4707,6 +4704,11 @@ finish:
|
|||||||
start_waiting_global_read_lock(thd);
|
start_waiting_global_read_lock(thd);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(res || thd->is_error());
|
DBUG_RETURN(res || thd->is_error());
|
||||||
|
|
||||||
|
error:
|
||||||
|
thd_proc_info(thd, "query end");
|
||||||
|
res= TRUE;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7366,6 +7368,7 @@ bool parse_sql(THD *thd,
|
|||||||
Lex_input_stream *lip,
|
Lex_input_stream *lip,
|
||||||
Object_creation_ctx *creation_ctx)
|
Object_creation_ctx *creation_ctx)
|
||||||
{
|
{
|
||||||
|
bool mysql_parse_status;
|
||||||
DBUG_ASSERT(thd->m_lip == NULL);
|
DBUG_ASSERT(thd->m_lip == NULL);
|
||||||
|
|
||||||
/* Backup creation context. */
|
/* Backup creation context. */
|
||||||
@ -7381,7 +7384,7 @@ bool parse_sql(THD *thd,
|
|||||||
|
|
||||||
/* Parse the query. */
|
/* Parse the query. */
|
||||||
|
|
||||||
bool mysql_parse_status= MYSQLparse(thd) != 0;
|
mysql_parse_status= MYSQLparse(thd) != 0;
|
||||||
|
|
||||||
/* Check that if MYSQLparse() failed, thd->is_error() is set. */
|
/* Check that if MYSQLparse() failed, thd->is_error() is set. */
|
||||||
|
|
||||||
|
@ -1818,7 +1818,10 @@ JOIN::exec()
|
|||||||
curr_join->having= curr_join->tmp_having= 0; // Allready done
|
curr_join->having= curr_join->tmp_having= 0; // Allready done
|
||||||
|
|
||||||
/* Change sum_fields reference to calculated fields in tmp_table */
|
/* Change sum_fields reference to calculated fields in tmp_table */
|
||||||
curr_join->all_fields= *curr_all_fields;
|
#ifdef HAVE_purify
|
||||||
|
if (curr_join != this)
|
||||||
|
#endif
|
||||||
|
curr_join->all_fields= *curr_all_fields;
|
||||||
if (!items1)
|
if (!items1)
|
||||||
{
|
{
|
||||||
items1= items0 + all_fields.elements;
|
items1= items0 + all_fields.elements;
|
||||||
@ -1836,8 +1839,13 @@ JOIN::exec()
|
|||||||
fields_list.elements, all_fields))
|
fields_list.elements, all_fields))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
curr_join->tmp_all_fields1= tmp_all_fields1;
|
#ifdef HAVE_purify
|
||||||
curr_join->tmp_fields_list1= tmp_fields_list1;
|
if (curr_join != this)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
curr_join->tmp_all_fields1= tmp_all_fields1;
|
||||||
|
curr_join->tmp_fields_list1= tmp_fields_list1;
|
||||||
|
}
|
||||||
curr_join->items1= items1;
|
curr_join->items1= items1;
|
||||||
}
|
}
|
||||||
curr_all_fields= &tmp_all_fields1;
|
curr_all_fields= &tmp_all_fields1;
|
||||||
@ -2041,8 +2049,13 @@ JOIN::exec()
|
|||||||
tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field;
|
tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field;
|
||||||
tmp_table_param.save_copy_field_end=
|
tmp_table_param.save_copy_field_end=
|
||||||
curr_join->tmp_table_param.copy_field_end;
|
curr_join->tmp_table_param.copy_field_end;
|
||||||
curr_join->tmp_all_fields3= tmp_all_fields3;
|
#ifdef HAVE_purify
|
||||||
curr_join->tmp_fields_list3= tmp_fields_list3;
|
if (curr_join != this)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
curr_join->tmp_all_fields3= tmp_all_fields3;
|
||||||
|
curr_join->tmp_fields_list3= tmp_fields_list3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -459,7 +459,8 @@ public:
|
|||||||
group_optimized_away= 0;
|
group_optimized_away= 0;
|
||||||
|
|
||||||
all_fields= fields_arg;
|
all_fields= fields_arg;
|
||||||
fields_list= fields_arg;
|
if (&fields_list != &fields_arg) /* Avoid valgrind-warning */
|
||||||
|
fields_list= fields_arg;
|
||||||
bzero((char*) &keyuse,sizeof(keyuse));
|
bzero((char*) &keyuse,sizeof(keyuse));
|
||||||
tmp_table_param.init();
|
tmp_table_param.init();
|
||||||
tmp_table_param.end_write_records= HA_POS_ERROR;
|
tmp_table_param.end_write_records= HA_POS_ERROR;
|
||||||
|
@ -7112,7 +7112,9 @@ err:
|
|||||||
free_io_cache(from);
|
free_io_cache(from);
|
||||||
delete [] copy;
|
delete [] copy;
|
||||||
|
|
||||||
if (errpos >= 3 && to->file->ha_end_bulk_insert() && error <= 0)
|
if (error > 0)
|
||||||
|
to->file->extra(HA_EXTRA_PREPARE_FOR_DROP);
|
||||||
|
if (errpos >= 3 && to->file->ha_end_bulk_insert(error > 1) && error <= 0)
|
||||||
{
|
{
|
||||||
to->file->print_error(my_errno,MYF(0));
|
to->file->print_error(my_errno,MYF(0));
|
||||||
error=1;
|
error=1;
|
||||||
|
@ -1511,7 +1511,7 @@ void ha_archive::start_bulk_insert(ha_rows rows)
|
|||||||
Other side of start_bulk_insert, is end_bulk_insert. Here we turn off the bulk insert
|
Other side of start_bulk_insert, is end_bulk_insert. Here we turn off the bulk insert
|
||||||
flag, and set the share dirty so that the next select will call sync for us.
|
flag, and set the share dirty so that the next select will call sync for us.
|
||||||
*/
|
*/
|
||||||
int ha_archive::end_bulk_insert()
|
int ha_archive::end_bulk_insert(bool table_will_be_deleted)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("ha_archive::end_bulk_insert");
|
DBUG_ENTER("ha_archive::end_bulk_insert");
|
||||||
bulk_insert= FALSE;
|
bulk_insert= FALSE;
|
||||||
|
@ -134,7 +134,7 @@ public:
|
|||||||
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
|
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
|
||||||
int repair(THD* thd, HA_CHECK_OPT* check_opt);
|
int repair(THD* thd, HA_CHECK_OPT* check_opt);
|
||||||
void start_bulk_insert(ha_rows rows);
|
void start_bulk_insert(ha_rows rows);
|
||||||
int end_bulk_insert();
|
int end_bulk_insert(bool table_will_be_deleted);
|
||||||
enum row_type get_row_type() const
|
enum row_type get_row_type() const
|
||||||
{
|
{
|
||||||
return ROW_TYPE_COMPRESSED;
|
return ROW_TYPE_COMPRESSED;
|
||||||
|
@ -1961,12 +1961,12 @@ void ha_federated::start_bulk_insert(ha_rows rows)
|
|||||||
@retval != 0 Error occured at remote server. Also sets my_errno.
|
@retval != 0 Error occured at remote server. Also sets my_errno.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ha_federated::end_bulk_insert()
|
int ha_federated::end_bulk_insert(bool abort)
|
||||||
{
|
{
|
||||||
int error= 0;
|
int error= 0;
|
||||||
DBUG_ENTER("ha_federated::end_bulk_insert");
|
DBUG_ENTER("ha_federated::end_bulk_insert");
|
||||||
|
|
||||||
if (bulk_insert.str && bulk_insert.length)
|
if (!abort && bulk_insert.str && bulk_insert.length)
|
||||||
{
|
{
|
||||||
if (real_query(bulk_insert.str, bulk_insert.length))
|
if (real_query(bulk_insert.str, bulk_insert.length))
|
||||||
error= stash_remote_error();
|
error= stash_remote_error();
|
||||||
|
@ -205,7 +205,7 @@ public:
|
|||||||
int close(void); // required
|
int close(void); // required
|
||||||
|
|
||||||
void start_bulk_insert(ha_rows rows);
|
void start_bulk_insert(ha_rows rows);
|
||||||
int end_bulk_insert();
|
int end_bulk_insert(bool abort);
|
||||||
int write_row(uchar *buf);
|
int write_row(uchar *buf);
|
||||||
int update_row(const uchar *old_data, uchar *new_data);
|
int update_row(const uchar *old_data, uchar *new_data);
|
||||||
int delete_row(const uchar *buf);
|
int delete_row(const uchar *buf);
|
||||||
|
@ -71,9 +71,9 @@ noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h \
|
|||||||
ma_ft_eval.h trnman.h lockman.h tablockman.h \
|
ma_ft_eval.h trnman.h lockman.h tablockman.h \
|
||||||
ma_control_file.h ha_maria.h ma_blockrec.h \
|
ma_control_file.h ha_maria.h ma_blockrec.h \
|
||||||
ma_loghandler.h ma_loghandler_lsn.h ma_pagecache.h \
|
ma_loghandler.h ma_loghandler_lsn.h ma_pagecache.h \
|
||||||
ma_checkpoint.h ma_recovery.h ma_commit.h \
|
ma_checkpoint.h ma_recovery.h ma_commit.h ma_state.h \
|
||||||
trnman_public.h ma_check_standalone.h ma_key_recover.h \
|
trnman_public.h ma_check_standalone.h \
|
||||||
ma_recovery_util.h
|
ma_key_recover.h ma_recovery_util.h
|
||||||
ma_test1_DEPENDENCIES= $(LIBRARIES)
|
ma_test1_DEPENDENCIES= $(LIBRARIES)
|
||||||
ma_test1_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
|
ma_test1_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
|
||||||
$(top_builddir)/storage/myisam/libmyisam.a \
|
$(top_builddir)/storage/myisam/libmyisam.a \
|
||||||
@ -115,7 +115,7 @@ ma_sp_test_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
|
|||||||
libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
|
libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
|
||||||
ma_rnext.c ma_rnext_same.c \
|
ma_rnext.c ma_rnext_same.c \
|
||||||
ma_search.c ma_page.c ma_key_recover.c ma_key.c \
|
ma_search.c ma_page.c ma_key_recover.c ma_key.c \
|
||||||
ma_locking.c \
|
ma_locking.c ma_state.c \
|
||||||
ma_rrnd.c ma_scan.c ma_cache.c \
|
ma_rrnd.c ma_scan.c ma_cache.c \
|
||||||
ma_statrec.c ma_packrec.c ma_dynrec.c \
|
ma_statrec.c ma_packrec.c ma_dynrec.c \
|
||||||
ma_blockrec.c ma_bitmap.c \
|
ma_blockrec.c ma_bitmap.c \
|
||||||
@ -129,12 +129,13 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
|
|||||||
ma_keycache.c ma_preload.c ma_ft_parser.c \
|
ma_keycache.c ma_preload.c ma_ft_parser.c \
|
||||||
ma_ft_update.c ma_ft_boolean_search.c \
|
ma_ft_update.c ma_ft_boolean_search.c \
|
||||||
ma_ft_nlq_search.c ft_maria.c ma_sort.c \
|
ma_ft_nlq_search.c ft_maria.c ma_sort.c \
|
||||||
ha_maria.cc trnman.c lockman.c tablockman.c \
|
trnman.c lockman.c tablockman.c \
|
||||||
ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c \
|
ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c \
|
||||||
ma_sp_key.c ma_control_file.c ma_loghandler.c \
|
ma_sp_key.c ma_control_file.c ma_loghandler.c \
|
||||||
ma_pagecache.c ma_pagecaches.c \
|
ma_pagecache.c ma_pagecaches.c \
|
||||||
ma_checkpoint.c ma_recovery.c ma_commit.c \
|
ma_checkpoint.c ma_recovery.c ma_commit.c \
|
||||||
ma_pagecrc.c ma_recovery_util.c
|
ma_pagecrc.c ma_recovery_util.c \
|
||||||
|
ha_maria.cc
|
||||||
CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA?
|
CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA?
|
||||||
|
|
||||||
SUFFIXES = .sh
|
SUFFIXES = .sh
|
||||||
|
@ -1280,6 +1280,14 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize)
|
|||||||
DBUG_RETURN(HA_ADMIN_FAILED);
|
DBUG_RETURN(HA_ADMIN_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If transactions was not enabled for a transactional table then
|
||||||
|
file->s->status is not up to date. This is needed for repair_by_sort
|
||||||
|
to work
|
||||||
|
*/
|
||||||
|
if (share->base.born_transactional && !share->now_transactional)
|
||||||
|
_ma_copy_nontrans_state_information(file);
|
||||||
|
|
||||||
param.db_name= table->s->db.str;
|
param.db_name= table->s->db.str;
|
||||||
param.table_name= table->alias;
|
param.table_name= table->alias;
|
||||||
param.tmpfile_createflag= O_RDWR | O_TRUNC;
|
param.tmpfile_createflag= O_RDWR | O_TRUNC;
|
||||||
@ -1287,7 +1295,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize)
|
|||||||
param.thd= thd;
|
param.thd= thd;
|
||||||
param.tmpdir= &mysql_tmpdir_list;
|
param.tmpdir= &mysql_tmpdir_list;
|
||||||
param.out_flag= 0;
|
param.out_flag= 0;
|
||||||
strmov(fixed_name, file->s->open_file_name);
|
strmov(fixed_name, share->open_file_name);
|
||||||
|
|
||||||
// Don't lock tables if we have used LOCK TABLE
|
// Don't lock tables if we have used LOCK TABLE
|
||||||
if (!thd->locked_tables &&
|
if (!thd->locked_tables &&
|
||||||
@ -1298,7 +1306,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!do_optimize ||
|
if (!do_optimize ||
|
||||||
((file->s->data_file_type == BLOCK_RECORD) ?
|
((share->data_file_type == BLOCK_RECORD) ?
|
||||||
(share->state.changed & STATE_NOT_OPTIMIZED_ROWS) :
|
(share->state.changed & STATE_NOT_OPTIMIZED_ROWS) :
|
||||||
(file->state->del || share->state.split != file->state->records)) &&
|
(file->state->del || share->state.split != file->state->records)) &&
|
||||||
(!(param.testflag & T_QUICK) ||
|
(!(param.testflag & T_QUICK) ||
|
||||||
@ -1317,7 +1325,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize)
|
|||||||
statistics_done= 1;
|
statistics_done= 1;
|
||||||
/* TODO: Remove BLOCK_RECORD test when parallel works with blocks */
|
/* TODO: Remove BLOCK_RECORD test when parallel works with blocks */
|
||||||
if (THDVAR(thd,repair_threads) > 1 &&
|
if (THDVAR(thd,repair_threads) > 1 &&
|
||||||
file->s->data_file_type != BLOCK_RECORD)
|
share->data_file_type != BLOCK_RECORD)
|
||||||
{
|
{
|
||||||
char buf[40];
|
char buf[40];
|
||||||
/* TODO: respect maria_repair_threads variable */
|
/* TODO: respect maria_repair_threads variable */
|
||||||
@ -1379,18 +1387,17 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize)
|
|||||||
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
|
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
the following 'if', thought conceptually wrong,
|
repair updates share->state.state. Ensure that file->state is up to date
|
||||||
is a useful optimization nevertheless.
|
|
||||||
*/
|
*/
|
||||||
if (file->state != &file->s->state.state)
|
if (file->state != &share->state.state)
|
||||||
file->s->state.state= *file->state;
|
*file->state= share->state.state;
|
||||||
if (file->s->base.auto_key)
|
if (share->base.auto_key)
|
||||||
_ma_update_auto_increment_key(¶m, file, 1);
|
_ma_update_auto_increment_key(¶m, file, 1);
|
||||||
if (optimize_done)
|
if (optimize_done)
|
||||||
error= maria_update_state_info(¶m, file,
|
error= maria_update_state_info(¶m, file,
|
||||||
UPDATE_TIME | UPDATE_OPEN_COUNT |
|
UPDATE_TIME | UPDATE_OPEN_COUNT |
|
||||||
(local_testflag &
|
(local_testflag &
|
||||||
T_STATISTICS ? UPDATE_STAT : 0));
|
T_STATISTICS ? UPDATE_STAT : 0));
|
||||||
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
|
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
|
||||||
HA_STATUS_CONST);
|
HA_STATUS_CONST);
|
||||||
if (rows != file->state->records && !(param.testflag & T_VERY_SILENT))
|
if (rows != file->state->records && !(param.testflag & T_VERY_SILENT))
|
||||||
@ -1650,6 +1657,8 @@ int ha_maria::enable_indexes(uint mode)
|
|||||||
{
|
{
|
||||||
sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
|
sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
|
||||||
my_errno, param.db_name, param.table_name);
|
my_errno, param.db_name, param.table_name);
|
||||||
|
/* This should never fail normally */
|
||||||
|
DBUG_ASSERT(0);
|
||||||
/* Repairing by sort failed. Now try standard repair method. */
|
/* Repairing by sort failed. Now try standard repair method. */
|
||||||
param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
|
param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
|
||||||
error= (repair(thd, param, 0) != HA_ADMIN_OK);
|
error= (repair(thd, param, 0) != HA_ADMIN_OK);
|
||||||
@ -1790,14 +1799,14 @@ void ha_maria::start_bulk_insert(ha_rows rows)
|
|||||||
!= 0 Error
|
!= 0 Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ha_maria::end_bulk_insert()
|
int ha_maria::end_bulk_insert(bool table_will_be_deleted)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
DBUG_ENTER("ha_maria::end_bulk_insert");
|
DBUG_ENTER("ha_maria::end_bulk_insert");
|
||||||
maria_end_bulk_insert(file);
|
maria_end_bulk_insert(file, table_will_be_deleted);
|
||||||
if ((err= maria_extra(file, HA_EXTRA_NO_CACHE, 0)))
|
if ((err= maria_extra(file, HA_EXTRA_NO_CACHE, 0)))
|
||||||
goto end;
|
goto end;
|
||||||
if (can_enable_indexes)
|
if (can_enable_indexes && !table_will_be_deleted)
|
||||||
err= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
|
err= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
|
||||||
end:
|
end:
|
||||||
if (bulk_insert_single_undo != BULK_INSERT_NONE)
|
if (bulk_insert_single_undo != BULK_INSERT_NONE)
|
||||||
@ -2181,77 +2190,95 @@ int ha_maria::external_lock(THD *thd, int lock_type)
|
|||||||
external_lock(F_UNLCK) will happen and we can then allow the user to
|
external_lock(F_UNLCK) will happen and we can then allow the user to
|
||||||
create transactional temporary tables.
|
create transactional temporary tables.
|
||||||
*/
|
*/
|
||||||
if (!file->s->base.born_transactional)
|
if (file->s->base.born_transactional)
|
||||||
goto skip_transaction;
|
|
||||||
if (lock_type != F_UNLCK)
|
|
||||||
{
|
{
|
||||||
if (!trn) /* no transaction yet - open it now */
|
/* Transactional table */
|
||||||
|
if (lock_type != F_UNLCK)
|
||||||
{
|
{
|
||||||
trn= trnman_new_trn(& thd->mysys_var->mutex,
|
/* Start of new statement */
|
||||||
& thd->mysys_var->suspend,
|
if (!trn) /* no transaction yet - open it now */
|
||||||
thd->thread_stack + STACK_DIRECTION *
|
|
||||||
(my_thread_stack_size - STACK_MIN_SIZE));
|
|
||||||
if (unlikely(!trn))
|
|
||||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("THD_TRN set to 0x%lx", (ulong)trn));
|
|
||||||
THD_TRN= trn;
|
|
||||||
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
|
||||||
trans_register_ha(thd, TRUE, maria_hton);
|
|
||||||
}
|
|
||||||
file->trn= trn;
|
|
||||||
if (!trnman_increment_locked_tables(trn))
|
|
||||||
{
|
|
||||||
trans_register_ha(thd, FALSE, maria_hton);
|
|
||||||
trnman_new_statement(trn);
|
|
||||||
}
|
|
||||||
if (!thd->transaction.on)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
No need to log REDOs/UNDOs. If this is an internal temporary table
|
|
||||||
which will be renamed to a permanent table (like in ALTER TABLE),
|
|
||||||
the rename happens after unlocking so will be durable (and the table
|
|
||||||
will get its create_rename_lsn).
|
|
||||||
Note: if we wanted to enable users to have an old backup and apply
|
|
||||||
tons of archived logs to roll-forward, we could then not disable
|
|
||||||
REDOs/UNDOs in this case.
|
|
||||||
*/
|
|
||||||
DBUG_PRINT("info", ("Disabling logging for table"));
|
|
||||||
_ma_tmp_disable_logging_for_table(file, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
We always re-enable, don't rely on thd->transaction.on as it is
|
|
||||||
sometimes reset to true after unlocking (see mysql_truncate() for a
|
|
||||||
partitioned table based on Maria).
|
|
||||||
*/
|
|
||||||
if (_ma_reenable_logging_for_table(file, TRUE))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
/** @todo zero file->trn also in commit and rollback */
|
|
||||||
file->trn= NULL;
|
|
||||||
if (trn && trnman_has_locked_tables(trn))
|
|
||||||
{
|
|
||||||
if (!trnman_decrement_locked_tables(trn))
|
|
||||||
{
|
{
|
||||||
/* autocommit ? rollback a transaction */
|
trn= trnman_new_trn(& thd->mysys_var->mutex,
|
||||||
#ifdef MARIA_CANNOT_ROLLBACK
|
& thd->mysys_var->suspend,
|
||||||
if (ma_commit(trn))
|
thd->thread_stack + STACK_DIRECTION *
|
||||||
DBUG_RETURN(1);
|
(my_thread_stack_size - STACK_MIN_SIZE));
|
||||||
THD_TRN= 0;
|
if (unlikely(!trn))
|
||||||
#else
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||||
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
|
THD_TRN= trn;
|
||||||
{
|
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
||||||
trnman_rollback_trn(trn);
|
trans_register_ha(thd, TRUE, maria_hton);
|
||||||
DBUG_PRINT("info", ("THD_TRN set to 0x0"));
|
}
|
||||||
THD_TRN= 0;
|
file->trn= trn;
|
||||||
}
|
if (!trnman_increment_locked_tables(trn))
|
||||||
#endif
|
{
|
||||||
|
trans_register_ha(thd, FALSE, maria_hton);
|
||||||
|
trnman_new_statement(trn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->s->lock.get_status)
|
||||||
|
{
|
||||||
|
if (_ma_setup_live_state(file))
|
||||||
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Copy the current state. This may have been wrong if the same file
|
||||||
|
was used several times in the last statement. This should only
|
||||||
|
happen for temporary tables.
|
||||||
|
*/
|
||||||
|
*file->state= file->s->state.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thd->transaction.on)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
No need to log REDOs/UNDOs. If this is an internal temporary table
|
||||||
|
which will be renamed to a permanent table (like in ALTER TABLE),
|
||||||
|
the rename happens after unlocking so will be durable (and the table
|
||||||
|
will get its create_rename_lsn).
|
||||||
|
Note: if we wanted to enable users to have an old backup and apply
|
||||||
|
tons of archived logs to roll-forward, we could then not disable
|
||||||
|
REDOs/UNDOs in this case.
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("info", ("Disabling logging for table"));
|
||||||
|
_ma_tmp_disable_logging_for_table(file, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
skip_transaction:
|
{
|
||||||
|
/* End of transaction */
|
||||||
|
|
||||||
|
/*
|
||||||
|
We always re-enable, don't rely on thd->transaction.on as it is
|
||||||
|
sometimes reset to true after unlocking (see mysql_truncate() for a
|
||||||
|
partitioned table based on Maria).
|
||||||
|
*/
|
||||||
|
if (_ma_reenable_logging_for_table(file, TRUE))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
/** @todo zero file->trn also in commit and rollback */
|
||||||
|
file->trn= 0;
|
||||||
|
if (trn && trnman_has_locked_tables(trn))
|
||||||
|
{
|
||||||
|
if (!trnman_decrement_locked_tables(trn))
|
||||||
|
{
|
||||||
|
/* autocommit ? rollback a transaction */
|
||||||
|
#ifdef MARIA_CANNOT_ROLLBACK
|
||||||
|
if (ma_commit(trn))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
THD_TRN= 0;
|
||||||
|
#else
|
||||||
|
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
|
||||||
|
{
|
||||||
|
trnman_rollback_trn(trn);
|
||||||
|
DBUG_PRINT("info", ("THD_TRN set to 0x0"));
|
||||||
|
THD_TRN= 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* if transactional table */
|
||||||
DBUG_RETURN(maria_lock_database(file, !table->s->tmp_table ?
|
DBUG_RETURN(maria_lock_database(file, !table->s->tmp_table ?
|
||||||
lock_type : ((lock_type == F_UNLCK) ?
|
lock_type : ((lock_type == F_UNLCK) ?
|
||||||
F_UNLCK : F_EXTRA_LCK)));
|
F_UNLCK : F_EXTRA_LCK)));
|
||||||
@ -2849,7 +2876,7 @@ my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name,
|
|||||||
to know if the variable was changed, the actual new value doesn't matter
|
to know if the variable was changed, the actual new value doesn't matter
|
||||||
*/
|
*/
|
||||||
actual_data_file_length= file->s->state.state.data_file_length;
|
actual_data_file_length= file->s->state.state.data_file_length;
|
||||||
current_data_file_length= file->save_state.data_file_length;
|
current_data_file_length= file->state->data_file_length;
|
||||||
|
|
||||||
if (!file->s->now_transactional &&
|
if (!file->s->now_transactional &&
|
||||||
current_data_file_length != actual_data_file_length)
|
current_data_file_length != actual_data_file_length)
|
||||||
|
@ -122,7 +122,7 @@ public:
|
|||||||
int enable_indexes(uint mode);
|
int enable_indexes(uint mode);
|
||||||
int indexes_are_disabled(void);
|
int indexes_are_disabled(void);
|
||||||
void start_bulk_insert(ha_rows rows);
|
void start_bulk_insert(ha_rows rows);
|
||||||
int end_bulk_insert();
|
int end_bulk_insert(bool abort);
|
||||||
ha_rows records_in_range(uint inx, key_range * min_key, key_range * max_key);
|
ha_rows records_in_range(uint inx, key_range * min_key, key_range * max_key);
|
||||||
void update_create_info(HA_CREATE_INFO * create_info);
|
void update_create_info(HA_CREATE_INFO * create_info);
|
||||||
int create(const char *name, TABLE * form, HA_CREATE_INFO * create_info);
|
int create(const char *name, TABLE * form, HA_CREATE_INFO * create_info);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2007 Michael Widenius
|
/* Copyright (C) 2007-2008 Michael Widenius
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -1934,7 +1934,7 @@ static my_bool write_tail(MARIA_HA *info,
|
|||||||
|
|
||||||
/* Increase data file size, if extended */
|
/* Increase data file size, if extended */
|
||||||
position= (my_off_t) block->page * block_size;
|
position= (my_off_t) block->page * block_size;
|
||||||
if (info->state->data_file_length <= position)
|
if (share->state.state.data_file_length <= position)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We are modifying a state member before writing the UNDO; this is a WAL
|
We are modifying a state member before writing the UNDO; this is a WAL
|
||||||
@ -1942,7 +1942,7 @@ static my_bool write_tail(MARIA_HA *info,
|
|||||||
data_file_length after writing any log record (FILE_ID/REDO/UNDO) (see
|
data_file_length after writing any log record (FILE_ID/REDO/UNDO) (see
|
||||||
collect_tables()).
|
collect_tables()).
|
||||||
*/
|
*/
|
||||||
info->state->data_file_length= position + block_size;
|
_ma_set_share_data_file_length(share, position + block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block_is_read)
|
if (block_is_read)
|
||||||
@ -2020,8 +2020,8 @@ static my_bool write_full_pages(MARIA_HA *info,
|
|||||||
sub_blocks= block->sub_blocks;
|
sub_blocks= block->sub_blocks;
|
||||||
|
|
||||||
position= (my_off_t) (page + page_count) * block_size;
|
position= (my_off_t) (page + page_count) * block_size;
|
||||||
if (info->state->data_file_length < position)
|
if (share->state.state.data_file_length < position)
|
||||||
info->state->data_file_length= position;
|
_ma_set_share_data_file_length(share, position);
|
||||||
|
|
||||||
/* Increase data file size, if extended */
|
/* Increase data file size, if extended */
|
||||||
|
|
||||||
@ -2044,8 +2044,8 @@ static my_bool write_full_pages(MARIA_HA *info,
|
|||||||
(ulong) block->page, (ulong) block->page_count));
|
(ulong) block->page, (ulong) block->page_count));
|
||||||
|
|
||||||
position= (page + page_count + 1) * block_size;
|
position= (page + page_count + 1) * block_size;
|
||||||
if (info->state->data_file_length < position)
|
if (share->state.state.data_file_length < position)
|
||||||
info->state->data_file_length= position;
|
_ma_set_share_data_file_length(share, position);
|
||||||
}
|
}
|
||||||
lsn_store(buff, lsn);
|
lsn_store(buff, lsn);
|
||||||
buff[PAGE_TYPE_OFFSET]= (uchar) BLOB_PAGE;
|
buff[PAGE_TYPE_OFFSET]= (uchar) BLOB_PAGE;
|
||||||
@ -3003,8 +3003,8 @@ static my_bool write_block_record(MARIA_HA *info,
|
|||||||
|
|
||||||
/* Increase data file size, if extended */
|
/* Increase data file size, if extended */
|
||||||
position= (my_off_t) head_block->page * block_size;
|
position= (my_off_t) head_block->page * block_size;
|
||||||
if (info->state->data_file_length <= position)
|
if (share->state.state.data_file_length <= position)
|
||||||
info->state->data_file_length= position + block_size;
|
_ma_set_share_data_file_length(share, position + block_size);
|
||||||
|
|
||||||
if (head_block_is_read)
|
if (head_block_is_read)
|
||||||
{
|
{
|
||||||
@ -4318,7 +4318,8 @@ static uchar *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent,
|
|||||||
if (!buff)
|
if (!buff)
|
||||||
{
|
{
|
||||||
/* check if we tried to read over end of file (ie: bad data in record) */
|
/* check if we tried to read over end of file (ie: bad data in record) */
|
||||||
if ((extent->page + 1) * share->block_size > info->state->data_file_length)
|
if ((extent->page + 1) * share->block_size >
|
||||||
|
share->state.state.data_file_length)
|
||||||
goto crashed;
|
goto crashed;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -5223,7 +5224,7 @@ restart_bitmap_scan:
|
|||||||
/* Read next bitmap */
|
/* Read next bitmap */
|
||||||
info->scan.bitmap_page+= share->bitmap.pages_covered;
|
info->scan.bitmap_page+= share->bitmap.pages_covered;
|
||||||
filepos= (my_off_t) info->scan.bitmap_page * block_size;
|
filepos= (my_off_t) info->scan.bitmap_page * block_size;
|
||||||
if (unlikely(filepos >= info->state->data_file_length))
|
if (unlikely(filepos >= share->state.state.data_file_length))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Found end of file"));
|
DBUG_PRINT("info", ("Found end of file"));
|
||||||
DBUG_RETURN((my_errno= HA_ERR_END_OF_FILE));
|
DBUG_RETURN((my_errno= HA_ERR_END_OF_FILE));
|
||||||
@ -5798,7 +5799,6 @@ my_bool write_hook_for_undo(enum translog_record_type type
|
|||||||
if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0))
|
if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0))
|
||||||
trn->first_undo_lsn=
|
trn->first_undo_lsn=
|
||||||
trn->undo_lsn | LSN_WITH_FLAGS_TO_FLAGS(trn->first_undo_lsn);
|
trn->undo_lsn | LSN_WITH_FLAGS_TO_FLAGS(trn->first_undo_lsn);
|
||||||
DBUG_ASSERT(tbl_info->state == &tbl_info->s->state.state);
|
|
||||||
return 0;
|
return 0;
|
||||||
/*
|
/*
|
||||||
when we implement purging, we will specialize this hook: UNDO_PURGE
|
when we implement purging, we will specialize this hook: UNDO_PURGE
|
||||||
@ -5820,14 +5820,13 @@ my_bool write_hook_for_redo_delete_all(enum translog_record_type type
|
|||||||
__attribute__ ((unused)),
|
__attribute__ ((unused)),
|
||||||
LSN *lsn, void *hook_arg)
|
LSN *lsn, void *hook_arg)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(tbl_info->state == &tbl_info->s->state.state);
|
|
||||||
_ma_reset_status(tbl_info);
|
_ma_reset_status(tbl_info);
|
||||||
return write_hook_for_redo(type, trn, tbl_info, lsn, hook_arg);
|
return write_hook_for_redo(type, trn, tbl_info, lsn, hook_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Upates "records" and "checksum" and calls the generic UNDO hook
|
@brief Updates "records" and "checksum" and calls the generic UNDO hook
|
||||||
|
|
||||||
@return Operation status, always 0 (success)
|
@return Operation status, always 0 (success)
|
||||||
*/
|
*/
|
||||||
@ -5974,10 +5973,10 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
|
|||||||
STATE_NOT_MOVABLE);
|
STATE_NOT_MOVABLE);
|
||||||
|
|
||||||
end_of_page= (page + 1) * share->block_size;
|
end_of_page= (page + 1) * share->block_size;
|
||||||
if (end_of_page > info->state->data_file_length)
|
if (end_of_page > share->state.state.data_file_length)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Enlarging data file from %lu to %lu",
|
DBUG_PRINT("info", ("Enlarging data file from %lu to %lu",
|
||||||
(ulong) info->state->data_file_length,
|
(ulong) share->state.state.data_file_length,
|
||||||
(ulong) end_of_page));
|
(ulong) end_of_page));
|
||||||
/*
|
/*
|
||||||
New page at end of file. Note that the test above is also positive if
|
New page at end of file. Note that the test above is also positive if
|
||||||
@ -6109,7 +6108,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
|
|||||||
case we extended the file. We could not do it earlier: bitmap code tests
|
case we extended the file. We could not do it earlier: bitmap code tests
|
||||||
data_file_length to know if it has to create a new page or not.
|
data_file_length to know if it has to create a new page or not.
|
||||||
*/
|
*/
|
||||||
set_if_bigger(info->state->data_file_length, end_of_page);
|
set_if_bigger(share->state.state.data_file_length, end_of_page);
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
|
|
||||||
crashed_file:
|
crashed_file:
|
||||||
@ -6439,13 +6438,13 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (((page + 1) * share->block_size) >
|
if (((page + 1) * share->block_size) >
|
||||||
info->state->data_file_length)
|
share->state.state.data_file_length)
|
||||||
{
|
{
|
||||||
/* New page or half written page at end of file */
|
/* New page or half written page at end of file */
|
||||||
DBUG_PRINT("info", ("Enlarging data file from %lu to %lu",
|
DBUG_PRINT("info", ("Enlarging data file from %lu to %lu",
|
||||||
(ulong) info->state->data_file_length,
|
(ulong) share->state.state.data_file_length,
|
||||||
(ulong) ((page + 1 ) * share->block_size)));
|
(ulong) ((page + 1 ) * share->block_size)));
|
||||||
info->state->data_file_length= (page + 1) * share->block_size;
|
share->state.state.data_file_length= (page + 1) * share->block_size;
|
||||||
buff= info->keyread_buff;
|
buff= info->keyread_buff;
|
||||||
info->keyread_buff_used= 1;
|
info->keyread_buff_used= 1;
|
||||||
make_empty_page(info, buff, BLOB_PAGE, 0);
|
make_empty_page(info, buff, BLOB_PAGE, 0);
|
||||||
@ -7065,72 +7064,8 @@ maria_page_get_lsn(uchar *page,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
Lock handling for concurrent insert
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create a copy of the current status for the table
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
_ma_get_status()
|
|
||||||
param Pointer to Myisam handler
|
|
||||||
concurrent_insert Set to 1 if we are going to do concurrent inserts
|
|
||||||
(THR_WRITE_CONCURRENT_INSERT was used)
|
|
||||||
*/
|
|
||||||
|
|
||||||
void _ma_block_get_status(void* param, my_bool concurrent_insert)
|
|
||||||
{
|
|
||||||
MARIA_HA *info=(MARIA_HA*) param;
|
|
||||||
DBUG_ENTER("_ma_block_get_status");
|
|
||||||
DBUG_PRINT("info", ("concurrent_insert %d", concurrent_insert));
|
|
||||||
info->row_base_length= info->s->base_length;
|
|
||||||
info->row_flag= info->s->base.default_row_flag;
|
|
||||||
if (concurrent_insert)
|
|
||||||
{
|
|
||||||
info->row_flag|= ROW_FLAG_TRANSID;
|
|
||||||
info->row_base_length+= TRANSID_SIZE;
|
|
||||||
}
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _ma_block_update_status(void *param __attribute__((unused)))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _ma_block_restore_status(void *param __attribute__((unused)))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check if should allow concurrent inserts
|
@brief Enable reading of all rows, ignoring versioning
|
||||||
|
|
||||||
@return
|
|
||||||
@retval 0 ok to use concurrent inserts
|
|
||||||
@retval 1 not ok
|
|
||||||
*/
|
|
||||||
|
|
||||||
my_bool _ma_block_check_status(void *param __attribute__((unused)))
|
|
||||||
{
|
|
||||||
return (my_bool) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Enable/disable versioning
|
|
||||||
*/
|
|
||||||
|
|
||||||
void maria_versioning(MARIA_HA *info, my_bool versioning)
|
|
||||||
{
|
|
||||||
/* For now, this is a hack */
|
|
||||||
_ma_block_get_status((void*) info, versioning);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Enable reading of all rows, ignoring versioning
|
|
||||||
|
|
||||||
@note
|
@note
|
||||||
This is mainly useful in single user applications, like maria_pack,
|
This is mainly useful in single user applications, like maria_pack,
|
||||||
|
@ -201,7 +201,7 @@ int maria_chk_del(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
puts("- check record delete-chain");
|
puts("- check record delete-chain");
|
||||||
|
|
||||||
next_link=share->state.dellink;
|
next_link=share->state.dellink;
|
||||||
if (info->state->del == 0)
|
if (share->state.state.del == 0)
|
||||||
{
|
{
|
||||||
if (test_flag & T_VERBOSE)
|
if (test_flag & T_VERBOSE)
|
||||||
{
|
{
|
||||||
@ -213,13 +213,13 @@ int maria_chk_del(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
if (test_flag & T_VERBOSE)
|
if (test_flag & T_VERBOSE)
|
||||||
printf("Recordlinks: ");
|
printf("Recordlinks: ");
|
||||||
empty=0;
|
empty=0;
|
||||||
for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
|
for (i= share->state.state.del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
|
||||||
{
|
{
|
||||||
if (*_ma_killed_ptr(param))
|
if (*_ma_killed_ptr(param))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
if (test_flag & T_VERBOSE)
|
if (test_flag & T_VERBOSE)
|
||||||
printf(" %9s",llstr(next_link,buff));
|
printf(" %9s",llstr(next_link,buff));
|
||||||
if (next_link >= info->state->data_file_length)
|
if (next_link >= share->state.state.data_file_length)
|
||||||
goto wrong;
|
goto wrong;
|
||||||
if (my_pread(info->dfile.file, (uchar*) buff, delete_link_length,
|
if (my_pread(info->dfile.file, (uchar*) buff, delete_link_length,
|
||||||
next_link,MYF(MY_NABP)))
|
next_link,MYF(MY_NABP)))
|
||||||
@ -256,28 +256,28 @@ int maria_chk_del(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
empty+=share->base.pack_reclength;
|
empty+=share->base.pack_reclength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info->state->del && (test_flag & T_VERBOSE))
|
if (share->state.state.del && (test_flag & T_VERBOSE))
|
||||||
puts("\n");
|
puts("\n");
|
||||||
if (empty != info->state->empty)
|
if (empty != share->state.state.empty)
|
||||||
{
|
{
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Found %s deleted space in delete link chain. Should be %s",
|
"Found %s deleted space in delete link chain. Should be %s",
|
||||||
llstr(empty,buff2),
|
llstr(empty,buff2),
|
||||||
llstr(info->state->empty,buff));
|
llstr(share->state.state.empty,buff));
|
||||||
}
|
}
|
||||||
if (next_link != HA_OFFSET_ERROR)
|
if (next_link != HA_OFFSET_ERROR)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,
|
_ma_check_print_error(param,
|
||||||
"Found more than the expected %s deleted rows in delete link chain",
|
"Found more than the expected %s deleted rows in delete link chain",
|
||||||
llstr(info->state->del, buff));
|
llstr(share->state.state.del, buff));
|
||||||
goto wrong;
|
goto wrong;
|
||||||
}
|
}
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,
|
_ma_check_print_error(param,
|
||||||
"Found %s deleted rows in delete link chain. Should be %s",
|
"Found %s deleted rows in delete link chain. Should be %s",
|
||||||
llstr(info->state->del - i, buff2),
|
llstr(share->state.state.del - i, buff2),
|
||||||
llstr(info->state->del, buff));
|
llstr(share->state.state.del, buff));
|
||||||
goto wrong;
|
goto wrong;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,7 +307,7 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
if (next_link == HA_OFFSET_ERROR)
|
if (next_link == HA_OFFSET_ERROR)
|
||||||
DBUG_RETURN(0); /* Avoid printing empty line */
|
DBUG_RETURN(0); /* Avoid printing empty line */
|
||||||
|
|
||||||
records= (ha_rows) (info->state->key_file_length / block_size);
|
records= (ha_rows) (share->state.state.key_file_length / block_size);
|
||||||
while (next_link != HA_OFFSET_ERROR && records > 0)
|
while (next_link != HA_OFFSET_ERROR && records > 0)
|
||||||
{
|
{
|
||||||
if (*_ma_killed_ptr(param))
|
if (*_ma_killed_ptr(param))
|
||||||
@ -316,13 +316,13 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
printf("%16s",llstr(next_link,llbuff));
|
printf("%16s",llstr(next_link,llbuff));
|
||||||
|
|
||||||
/* Key blocks must lay within the key file length entirely. */
|
/* Key blocks must lay within the key file length entirely. */
|
||||||
if (next_link + block_size > info->state->key_file_length)
|
if (next_link + block_size > share->state.state.key_file_length)
|
||||||
{
|
{
|
||||||
/* purecov: begin tested */
|
/* purecov: begin tested */
|
||||||
_ma_check_print_error(param, "Invalid key block position: %s "
|
_ma_check_print_error(param, "Invalid key block position: %s "
|
||||||
"key block size: %u file_length: %s",
|
"key block size: %u file_length: %s",
|
||||||
llstr(next_link, llbuff), block_size,
|
llstr(next_link, llbuff), block_size,
|
||||||
llstr(info->state->key_file_length, llbuff2));
|
llstr(share->state.state.key_file_length, llbuff2));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
/* purecov: end */
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
@ -396,7 +396,7 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info)
|
|||||||
_ma_check_print_error(param, "Failed to flush data or index file");
|
_ma_check_print_error(param, "Failed to flush data or index file");
|
||||||
|
|
||||||
size= my_seek(share->kfile.file, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
|
size= my_seek(share->kfile.file, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
|
||||||
if ((skr=(my_off_t) info->state->key_file_length) != size)
|
if ((skr=(my_off_t) share->state.state.key_file_length) != size)
|
||||||
{
|
{
|
||||||
/* Don't give error if file generated by mariapack */
|
/* Don't give error if file generated by mariapack */
|
||||||
if (skr > size && maria_is_any_key_active(share->state.key_map))
|
if (skr > size && maria_is_any_key_active(share->state.key_map))
|
||||||
@ -413,26 +413,26 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info)
|
|||||||
}
|
}
|
||||||
if (!(param->testflag & T_VERY_SILENT) &&
|
if (!(param->testflag & T_VERY_SILENT) &&
|
||||||
! (share->options & HA_OPTION_COMPRESS_RECORD) &&
|
! (share->options & HA_OPTION_COMPRESS_RECORD) &&
|
||||||
ulonglong2double(info->state->key_file_length) >
|
ulonglong2double(share->state.state.key_file_length) >
|
||||||
ulonglong2double(share->base.margin_key_file_length)*0.9)
|
ulonglong2double(share->base.margin_key_file_length)*0.9)
|
||||||
_ma_check_print_warning(param,"Keyfile is almost full, %10s of %10s used",
|
_ma_check_print_warning(param,"Keyfile is almost full, %10s of %10s used",
|
||||||
llstr(info->state->key_file_length,buff),
|
llstr(share->state.state.key_file_length,buff),
|
||||||
llstr(share->base.max_key_file_length-1,buff));
|
llstr(share->base.max_key_file_length-1,buff));
|
||||||
|
|
||||||
size= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
|
size= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
|
||||||
skr=(my_off_t) info->state->data_file_length;
|
skr=(my_off_t) share->state.state.data_file_length;
|
||||||
if (share->options & HA_OPTION_COMPRESS_RECORD)
|
if (share->options & HA_OPTION_COMPRESS_RECORD)
|
||||||
skr+= MEMMAP_EXTRA_MARGIN;
|
skr+= MEMMAP_EXTRA_MARGIN;
|
||||||
#ifdef USE_RELOC
|
#ifdef USE_RELOC
|
||||||
if (info->data_file_type == STATIC_RECORD &&
|
if (share->data_file_type == STATIC_RECORD &&
|
||||||
skr < (my_off_t) share->base.reloc*share->base.min_pack_length)
|
skr < (my_off_t) share->base.reloc*share->base.min_pack_length)
|
||||||
skr=(my_off_t) share->base.reloc*share->base.min_pack_length;
|
skr=(my_off_t) share->base.reloc*share->base.min_pack_length;
|
||||||
#endif
|
#endif
|
||||||
if (skr != size)
|
if (skr != size)
|
||||||
{
|
{
|
||||||
info->state->data_file_length=size; /* Skip other errors */
|
|
||||||
if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
|
if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
|
||||||
{
|
{
|
||||||
|
share->state.state.data_file_length=size; /* Skip other errors */
|
||||||
error=1;
|
error=1;
|
||||||
_ma_check_print_error(param,"Size of datafile is: %-9s Should be: %s",
|
_ma_check_print_error(param,"Size of datafile is: %-9s Should be: %s",
|
||||||
llstr(size,buff), llstr(skr,buff2));
|
llstr(size,buff), llstr(skr,buff2));
|
||||||
@ -447,10 +447,10 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info)
|
|||||||
}
|
}
|
||||||
if (!(param->testflag & T_VERY_SILENT) &&
|
if (!(param->testflag & T_VERY_SILENT) &&
|
||||||
!(share->options & HA_OPTION_COMPRESS_RECORD) &&
|
!(share->options & HA_OPTION_COMPRESS_RECORD) &&
|
||||||
ulonglong2double(info->state->data_file_length) >
|
ulonglong2double(share->state.state.data_file_length) >
|
||||||
(ulonglong2double(share->base.max_data_file_length)*0.9))
|
(ulonglong2double(share->base.max_data_file_length)*0.9))
|
||||||
_ma_check_print_warning(param, "Datafile is almost full, %10s of %10s used",
|
_ma_check_print_warning(param, "Datafile is almost full, %10s of %10s used",
|
||||||
llstr(info->state->data_file_length,buff),
|
llstr(share->state.state.data_file_length,buff),
|
||||||
llstr(share->base.max_data_file_length-1,buff2));
|
llstr(share->base.max_data_file_length-1,buff2));
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
} /* maria_chk_size */
|
} /* maria_chk_size */
|
||||||
@ -488,8 +488,8 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
|
|||||||
init_checksum=param->record_checksum;
|
init_checksum=param->record_checksum;
|
||||||
old_record_checksum=0;
|
old_record_checksum=0;
|
||||||
if (share->data_file_type == STATIC_RECORD)
|
if (share->data_file_type == STATIC_RECORD)
|
||||||
old_record_checksum= (calc_checksum(info->state->records +
|
old_record_checksum= (calc_checksum(share->state.state.records +
|
||||||
info->state->del-1) *
|
share->state.state.del-1) *
|
||||||
share->base.pack_reclength);
|
share->base.pack_reclength);
|
||||||
rec_per_key_part= param->new_rec_per_key_part;
|
rec_per_key_part= param->new_rec_per_key_part;
|
||||||
for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
|
for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
|
||||||
@ -518,7 +518,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
|
|||||||
full_text_keys++;
|
full_text_keys++;
|
||||||
if (share->state.key_root[key] == HA_OFFSET_ERROR)
|
if (share->state.key_root[key] == HA_OFFSET_ERROR)
|
||||||
{
|
{
|
||||||
if (info->state->records != 0 && !(keyinfo->flag & HA_FULLTEXT))
|
if (share->state.state.records != 0 && !(keyinfo->flag & HA_FULLTEXT))
|
||||||
_ma_check_print_error(param, "Key tree %u is empty", key + 1);
|
_ma_check_print_error(param, "Key tree %u is empty", key + 1);
|
||||||
goto do_stat;
|
goto do_stat;
|
||||||
}
|
}
|
||||||
@ -542,10 +542,10 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
|
|||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
|
if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
|
||||||
{
|
{
|
||||||
if (keys != info->state->records)
|
if (keys != share->state.state.records)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Found %s keys of %s",llstr(keys,buff),
|
_ma_check_print_error(param,"Found %s keys of %s",llstr(keys,buff),
|
||||||
llstr(info->state->records,buff2));
|
llstr(share->state.state.records,buff2));
|
||||||
if (!(param->testflag & T_INFO))
|
if (!(param->testflag & T_INFO))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
result= -1;
|
result= -1;
|
||||||
@ -625,7 +625,7 @@ do_stat:
|
|||||||
maria_update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
|
maria_update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
|
||||||
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
|
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
|
||||||
param->notnull_count: NULL,
|
param->notnull_count: NULL,
|
||||||
(ulonglong)info->state->records);
|
(ulonglong)share->state.state.records);
|
||||||
}
|
}
|
||||||
if (param->testflag & T_INFO)
|
if (param->testflag & T_INFO)
|
||||||
{
|
{
|
||||||
@ -639,7 +639,7 @@ do_stat:
|
|||||||
else if (all_totaldata != 0L && maria_is_any_key_active(share->state.key_map))
|
else if (all_totaldata != 0L && maria_is_any_key_active(share->state.key_map))
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
if (param->key_file_blocks != info->state->key_file_length &&
|
if (param->key_file_blocks != share->state.state.key_file_length &&
|
||||||
share->state.key_map == ~(ulonglong) 0)
|
share->state.key_map == ~(ulonglong) 0)
|
||||||
_ma_check_print_warning(param, "Some data are unreferenced in keyfile");
|
_ma_check_print_warning(param, "Some data are unreferenced in keyfile");
|
||||||
if (found_keys != full_text_keys)
|
if (found_keys != full_text_keys)
|
||||||
@ -657,10 +657,11 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info,
|
|||||||
ha_checksum *key_checksum, uint level)
|
ha_checksum *key_checksum, uint level)
|
||||||
{
|
{
|
||||||
char llbuff[22],llbuff2[22];
|
char llbuff[22],llbuff2[22];
|
||||||
|
MARIA_SHARE *share= info->s;
|
||||||
DBUG_ENTER("chk_index_down");
|
DBUG_ENTER("chk_index_down");
|
||||||
|
|
||||||
/* Key blocks must lay within the key file length entirely. */
|
/* Key blocks must lay within the key file length entirely. */
|
||||||
if (page + keyinfo->block_length > info->state->key_file_length)
|
if (page + keyinfo->block_length > share->state.state.key_file_length)
|
||||||
{
|
{
|
||||||
/* purecov: begin tested */
|
/* purecov: begin tested */
|
||||||
/* Give it a chance to fit in the real file size. */
|
/* Give it a chance to fit in the real file size. */
|
||||||
@ -669,12 +670,13 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info,
|
|||||||
_ma_check_print_error(param, "Invalid key block position: %s "
|
_ma_check_print_error(param, "Invalid key block position: %s "
|
||||||
"key block size: %u file_length: %s",
|
"key block size: %u file_length: %s",
|
||||||
llstr(page, llbuff), keyinfo->block_length,
|
llstr(page, llbuff), keyinfo->block_length,
|
||||||
llstr(info->state->key_file_length, llbuff2));
|
llstr(share->state.state.key_file_length, llbuff2));
|
||||||
if (page + keyinfo->block_length > max_length)
|
if (page + keyinfo->block_length > max_length)
|
||||||
goto err;
|
goto err;
|
||||||
/* Fix the remembered key file length. */
|
/* Fix the remembered key file length. */
|
||||||
info->state->key_file_length= (max_length &
|
share->state.state.key_file_length= (max_length &
|
||||||
~ (my_off_t) (keyinfo->block_length - 1));
|
~ (my_off_t) (keyinfo->block_length -
|
||||||
|
1));
|
||||||
/* purecov: end */
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -941,7 +943,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
|
|||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
if (record >= info->state->data_file_length)
|
if (record >= share->state.state.data_file_length)
|
||||||
{
|
{
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
char llbuff2[22], llbuff3[22];
|
char llbuff2[22], llbuff3[22];
|
||||||
@ -949,7 +951,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
|
|||||||
_ma_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
|
_ma_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
|
||||||
DBUG_PRINT("test",("page: %s record: %s filelength: %s",
|
DBUG_PRINT("test",("page: %s record: %s filelength: %s",
|
||||||
llstr(page,llbuff),llstr(record,llbuff2),
|
llstr(page,llbuff),llstr(record,llbuff2),
|
||||||
llstr(info->state->data_file_length,llbuff3)));
|
llstr(share->state.state.data_file_length,llbuff3)));
|
||||||
DBUG_DUMP("key",(uchar*) key,key_length);
|
DBUG_DUMP("key",(uchar*) key,key_length);
|
||||||
DBUG_DUMP("new_in_page", old_keypos, (uint) (keypos-old_keypos));
|
DBUG_DUMP("new_in_page", old_keypos, (uint) (keypos-old_keypos));
|
||||||
goto err;
|
goto err;
|
||||||
@ -1126,7 +1128,7 @@ static int check_static_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||||||
char llbuff[22];
|
char llbuff[22];
|
||||||
|
|
||||||
pos= 0;
|
pos= 0;
|
||||||
while (pos < info->state->data_file_length)
|
while (pos < share->state.state.data_file_length)
|
||||||
{
|
{
|
||||||
if (*_ma_killed_ptr(param))
|
if (*_ma_killed_ptr(param))
|
||||||
return -1;
|
return -1;
|
||||||
@ -1173,7 +1175,7 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||||||
LINT_INIT(to);
|
LINT_INIT(to);
|
||||||
|
|
||||||
pos= 0;
|
pos= 0;
|
||||||
while (pos < info->state->data_file_length)
|
while (pos < share->state.state.data_file_length)
|
||||||
{
|
{
|
||||||
my_bool got_error= 0;
|
my_bool got_error= 0;
|
||||||
int flag;
|
int flag;
|
||||||
@ -1228,9 +1230,9 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
if ((block_info.next_filepos != HA_OFFSET_ERROR &&
|
if ((block_info.next_filepos != HA_OFFSET_ERROR &&
|
||||||
block_info.next_filepos >= info->state->data_file_length) ||
|
block_info.next_filepos >= share->state.state.data_file_length) ||
|
||||||
(block_info.prev_filepos != HA_OFFSET_ERROR &&
|
(block_info.prev_filepos != HA_OFFSET_ERROR &&
|
||||||
block_info.prev_filepos >= info->state->data_file_length))
|
block_info.prev_filepos >= share->state.state.data_file_length))
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Delete link points outside datafile at %s",
|
_ma_check_print_error(param,"Delete link points outside datafile at %s",
|
||||||
llstr(pos,llbuff));
|
llstr(pos,llbuff));
|
||||||
@ -1248,7 +1250,7 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||||||
llstr(start_block,llbuff));
|
llstr(start_block,llbuff));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
if (info->state->data_file_length < block_info.filepos+
|
if (share->state.state.data_file_length < block_info.filepos+
|
||||||
block_info.block_len)
|
block_info.block_len)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,
|
_ma_check_print_error(param,
|
||||||
@ -1322,7 +1324,7 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||||||
got_error=1;
|
got_error=1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (info->state->data_file_length < block_info.next_filepos)
|
if (share->state.state.data_file_length < block_info.next_filepos)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,
|
_ma_check_print_error(param,
|
||||||
"Found next-recordlink that points outside datafile at %s",
|
"Found next-recordlink that points outside datafile at %s",
|
||||||
@ -1391,7 +1393,7 @@ static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||||||
DBUG_ENTER("check_compressed_record");
|
DBUG_ENTER("check_compressed_record");
|
||||||
|
|
||||||
pos= share->pack.header_length; /* Skip header */
|
pos= share->pack.header_length; /* Skip header */
|
||||||
while (pos < info->state->data_file_length)
|
while (pos < share->state.state.data_file_length)
|
||||||
{
|
{
|
||||||
if (*_ma_killed_ptr(param))
|
if (*_ma_killed_ptr(param))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@ -1742,10 +1744,10 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
|||||||
full_page_count= tail_count= 0;
|
full_page_count= tail_count= 0;
|
||||||
param->full_page_count= param->tail_count= 0;
|
param->full_page_count= param->tail_count= 0;
|
||||||
param->used= param->link_used= 0;
|
param->used= param->link_used= 0;
|
||||||
param->splits= info->state->data_file_length / block_size;
|
param->splits= share->state.state.data_file_length / block_size;
|
||||||
|
|
||||||
for (pos= 0, page= 0;
|
for (pos= 0, page= 0;
|
||||||
pos < info->state->data_file_length;
|
pos < share->state.state.data_file_length;
|
||||||
pos+= block_size, page++)
|
pos+= block_size, page++)
|
||||||
{
|
{
|
||||||
uint row_count, real_row_count, empty_space, page_type, bitmap_pattern;
|
uint row_count, real_row_count, empty_space, page_type, bitmap_pattern;
|
||||||
@ -1985,12 +1987,12 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
|
|||||||
{
|
{
|
||||||
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
|
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
|
||||||
}
|
}
|
||||||
if (param->records != info->state->records)
|
if (param->records != share->state.state.records)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,
|
_ma_check_print_error(param,
|
||||||
"Record-count is not ok; found %-10s Should be: %s",
|
"Record-count is not ok; found %-10s Should be: %s",
|
||||||
llstr(param->records,llbuff),
|
llstr(param->records,llbuff),
|
||||||
llstr(info->state->records,llbuff2));
|
llstr(share->state.state.records,llbuff2));
|
||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
else if (param->record_checksum &&
|
else if (param->record_checksum &&
|
||||||
@ -2000,7 +2002,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
|
|||||||
"Key pointers and record positions doesn't match");
|
"Key pointers and record positions doesn't match");
|
||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
else if (param->glob_crc != info->state->checksum &&
|
else if (param->glob_crc != share->state.state.checksum &&
|
||||||
(share->options &
|
(share->options &
|
||||||
(HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
|
(HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
|
||||||
{
|
{
|
||||||
@ -2023,18 +2025,18 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param->del_length != info->state->empty)
|
if (param->del_length != share->state.state.empty)
|
||||||
{
|
{
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Found %s deleted space. Should be %s",
|
"Found %s deleted space. Should be %s",
|
||||||
llstr(param->del_length,llbuff2),
|
llstr(param->del_length,llbuff2),
|
||||||
llstr(info->state->empty,llbuff));
|
llstr(share->state.state.empty,llbuff));
|
||||||
}
|
}
|
||||||
/* Skip following checks for BLOCK RECORD as they don't make any sence */
|
/* Skip following checks for BLOCK RECORD as they don't make any sence */
|
||||||
if (share->data_file_type != BLOCK_RECORD)
|
if (share->data_file_type != BLOCK_RECORD)
|
||||||
{
|
{
|
||||||
if (param->used + param->empty + param->del_length !=
|
if (param->used + param->empty + param->del_length !=
|
||||||
info->state->data_file_length)
|
share->state.state.data_file_length)
|
||||||
{
|
{
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Found %s record data and %s unused data and %s deleted data",
|
"Found %s record data and %s unused data and %s deleted data",
|
||||||
@ -2045,14 +2047,14 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
|
|||||||
"Total %s Should be: %s",
|
"Total %s Should be: %s",
|
||||||
llstr((param->used+param->empty +
|
llstr((param->used+param->empty +
|
||||||
param->del_length), llbuff),
|
param->del_length), llbuff),
|
||||||
llstr(info->state->data_file_length,llbuff2));
|
llstr(share->state.state.data_file_length,llbuff2));
|
||||||
}
|
}
|
||||||
if (param->del_blocks != info->state->del)
|
if (param->del_blocks != share->state.state.del)
|
||||||
{
|
{
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Found %10s deleted blocks Should be: %s",
|
"Found %10s deleted blocks Should be: %s",
|
||||||
llstr(param->del_blocks,llbuff),
|
llstr(param->del_blocks,llbuff),
|
||||||
llstr(info->state->del,llbuff2));
|
llstr(share->state.state.del,llbuff2));
|
||||||
}
|
}
|
||||||
if (param->splits != share->state.split)
|
if (param->splits != share->state.split)
|
||||||
{
|
{
|
||||||
@ -2224,7 +2226,7 @@ static int initialize_variables_for_repair(HA_CHECK *param,
|
|||||||
sort_info->filelength= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
|
sort_info->filelength= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
|
||||||
if ((param->testflag & T_CREATE_MISSING_KEYS) ||
|
if ((param->testflag & T_CREATE_MISSING_KEYS) ||
|
||||||
sort_info->org_data_file_type == COMPRESSED_RECORD)
|
sort_info->org_data_file_type == COMPRESSED_RECORD)
|
||||||
sort_info->max_records= info->state->records;
|
sort_info->max_records= share->state.state.records;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ulong rec_length;
|
ulong rec_length;
|
||||||
@ -2354,7 +2356,7 @@ static int maria_drop_all_indexes(HA_CHECK *param, MARIA_HA *info,
|
|||||||
share->state.key_del= HA_OFFSET_ERROR;
|
share->state.key_del= HA_OFFSET_ERROR;
|
||||||
|
|
||||||
/* Reset index file length to end of index file header. */
|
/* Reset index file length to end of index file header. */
|
||||||
info->state->key_file_length= share->base.keystart;
|
share->state.state.key_file_length= share->base.keystart;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -2403,7 +2405,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
got_error= 1;
|
got_error= 1;
|
||||||
new_file= -1;
|
new_file= -1;
|
||||||
start_records= info->state->records;
|
start_records= share->state.state.records;
|
||||||
if (!(param->testflag & T_SILENT))
|
if (!(param->testflag & T_SILENT))
|
||||||
{
|
{
|
||||||
printf("- recovering (with keycache) MARIA-table '%s'\n",name);
|
printf("- recovering (with keycache) MARIA-table '%s'\n",name);
|
||||||
@ -2494,9 +2496,9 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
sort_param.master=1;
|
sort_param.master=1;
|
||||||
sort_info.max_records= ~(ha_rows) 0;
|
sort_info.max_records= ~(ha_rows) 0;
|
||||||
|
|
||||||
del=info->state->del;
|
del= share->state.state.del;
|
||||||
info->state->records=info->state->del=share->state.split=0;
|
share->state.state.records= share->state.state.del= share->state.split= 0;
|
||||||
info->state->empty=0;
|
share->state.state.empty= 0;
|
||||||
|
|
||||||
if (param->testflag & T_CREATE_MISSING_KEYS)
|
if (param->testflag & T_CREATE_MISSING_KEYS)
|
||||||
maria_set_all_keys_active(share->state.key_map, share->base.keys);
|
maria_set_all_keys_active(share->state.key_map, share->base.keys);
|
||||||
@ -2538,7 +2540,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
/* purecov: begin tested */
|
/* purecov: begin tested */
|
||||||
if (block_record)
|
if (block_record)
|
||||||
{
|
{
|
||||||
sort_info.new_info->state->records--;
|
sort_info.new_info->s->state.state.records--;
|
||||||
if ((*sort_info.new_info->s->write_record_abort)(sort_info.new_info))
|
if ((*sort_info.new_info->s->write_record_abort)(sort_info.new_info))
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Couldn't delete duplicate row");
|
_ma_check_print_error(param,"Couldn't delete duplicate row");
|
||||||
@ -2565,7 +2567,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
{
|
{
|
||||||
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
|
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
|
||||||
}
|
}
|
||||||
if (my_chsize(share->kfile.file, info->state->key_file_length, 0, MYF(0)))
|
if (my_chsize(share->kfile.file, share->state.state.key_file_length, 0, MYF(0)))
|
||||||
{
|
{
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Can't change size of indexfile, error: %d",
|
"Can't change size of indexfile, error: %d",
|
||||||
@ -2573,7 +2575,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rep_quick && del+sort_info.dupp != info->state->del)
|
if (rep_quick && del+sort_info.dupp != share->state.state.del)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
|
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
|
||||||
_ma_check_print_error(param,"Run recovery again without -q");
|
_ma_check_print_error(param,"Run recovery again without -q");
|
||||||
@ -2585,9 +2587,9 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
if (param->testflag & T_SAFE_REPAIR)
|
if (param->testflag & T_SAFE_REPAIR)
|
||||||
{
|
{
|
||||||
/* Don't repair if we loosed more than one row */
|
/* Don't repair if we loosed more than one row */
|
||||||
if (sort_info.new_info->state->records+1 < start_records)
|
if (sort_info.new_info->s->state.state.records+1 < start_records)
|
||||||
{
|
{
|
||||||
info->state->records=start_records;
|
share->state.state.records= start_records;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2606,7 +2608,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
if (!rep_quick)
|
if (!rep_quick)
|
||||||
{
|
{
|
||||||
sort_info.new_info->state->data_file_length= sort_param.filepos;
|
sort_info.new_info->s->state.state.data_file_length= sort_param.filepos;
|
||||||
if (sort_info.new_info != sort_info.info)
|
if (sort_info.new_info != sort_info.info)
|
||||||
{
|
{
|
||||||
MARIA_STATE_INFO save_state= sort_info.new_info->s->state;
|
MARIA_STATE_INFO save_state= sort_info.new_info->s->state;
|
||||||
@ -2638,15 +2640,15 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->state->data_file_length= sort_param.max_pos;
|
share->state.state.data_file_length= sort_param.max_pos;
|
||||||
}
|
}
|
||||||
if (param->testflag & T_CALC_CHECKSUM)
|
if (param->testflag & T_CALC_CHECKSUM)
|
||||||
info->state->checksum= param->glob_crc;
|
share->state.state.checksum= param->glob_crc;
|
||||||
|
|
||||||
if (!(param->testflag & T_SILENT))
|
if (!(param->testflag & T_SILENT))
|
||||||
{
|
{
|
||||||
if (start_records != info->state->records)
|
if (start_records != share->state.state.records)
|
||||||
printf("Data records: %s\n", llstr(info->state->records,llbuff));
|
printf("Data records: %s\n", llstr(share->state.state.records,llbuff));
|
||||||
}
|
}
|
||||||
if (sort_info.dupp)
|
if (sort_info.dupp)
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
@ -2656,11 +2658,12 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
got_error= 0;
|
got_error= 0;
|
||||||
/* If invoked by external program that uses thr_lock */
|
/* If invoked by external program that uses thr_lock */
|
||||||
if (&share->state.state != info->state)
|
if (&share->state.state != info->state)
|
||||||
memcpy(&share->state.state, info->state, sizeof(*info->state));
|
*info->state= *info->state_start= share->state.state;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (scan_inited)
|
if (scan_inited)
|
||||||
maria_scan_end(sort_info.info);
|
maria_scan_end(sort_info.info);
|
||||||
|
_ma_reset_state(info);
|
||||||
|
|
||||||
VOID(end_io_cache(¶m->read_cache));
|
VOID(end_io_cache(¶m->read_cache));
|
||||||
VOID(end_io_cache(&sort_info.new_info->rec_cache));
|
VOID(end_io_cache(&sort_info.new_info->rec_cache));
|
||||||
@ -2952,7 +2955,7 @@ int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, char *name)
|
|||||||
share->tot_locks= r_locks+w_locks;
|
share->tot_locks= r_locks+w_locks;
|
||||||
share->state= old_state; /* Restore old state */
|
share->state= old_state; /* Restore old state */
|
||||||
|
|
||||||
info->state->key_file_length=param->new_file_pos;
|
share->state.state.key_file_length=param->new_file_pos;
|
||||||
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
for (key=0 ; key < share->base.keys ; key++)
|
for (key=0 ; key < share->base.keys ; key++)
|
||||||
share->state.key_root[key]=index_pos[key];
|
share->state.key_root[key]=index_pos[key];
|
||||||
@ -3185,7 +3188,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info,
|
|||||||
|
|
||||||
/* Go through the record file */
|
/* Go through the record file */
|
||||||
for (page= 1, pos= block_size;
|
for (page= 1, pos= block_size;
|
||||||
pos < info->state->data_file_length;
|
pos < share->state.state.data_file_length;
|
||||||
pos+= block_size, page++)
|
pos+= block_size, page++)
|
||||||
{
|
{
|
||||||
uchar *buff;
|
uchar *buff;
|
||||||
@ -3416,7 +3419,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
got_error= 1;
|
got_error= 1;
|
||||||
new_file= -1;
|
new_file= -1;
|
||||||
start_records= info->state->records;
|
start_records= share->state.state.records;
|
||||||
if (!(param->testflag & T_SILENT))
|
if (!(param->testflag & T_SILENT))
|
||||||
{
|
{
|
||||||
printf("- recovering (with sort) MARIA-table '%s'\n",name);
|
printf("- recovering (with sort) MARIA-table '%s'\n",name);
|
||||||
@ -3517,7 +3520,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
sort_param.tmpdir=param->tmpdir;
|
sort_param.tmpdir=param->tmpdir;
|
||||||
sort_param.master =1;
|
sort_param.master =1;
|
||||||
|
|
||||||
del=info->state->del;
|
del=share->state.state.del;
|
||||||
|
|
||||||
rec_per_key_part= param->new_rec_per_key_part;
|
rec_per_key_part= param->new_rec_per_key_part;
|
||||||
for (sort_param.key=0 ; sort_param.key < share->base.keys ;
|
for (sort_param.key=0 ; sort_param.key < share->base.keys ;
|
||||||
@ -3559,8 +3562,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
if (keyseg[i].flag & HA_NULL_PART)
|
if (keyseg[i].flag & HA_NULL_PART)
|
||||||
sort_param.key_length++;
|
sort_param.key_length++;
|
||||||
}
|
}
|
||||||
info->state->records=info->state->del=share->state.split=0;
|
share->state.state.records=share->state.state.del=share->state.split=0;
|
||||||
info->state->empty=0;
|
share->state.state.empty=0;
|
||||||
|
|
||||||
if (sort_param.keyinfo->flag & HA_FULLTEXT)
|
if (sort_param.keyinfo->flag & HA_FULLTEXT)
|
||||||
{
|
{
|
||||||
@ -3638,15 +3641,14 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
free_root(&sort_param.wordroot, MYF(0));
|
free_root(&sort_param.wordroot, MYF(0));
|
||||||
|
|
||||||
/* Set for next loop */
|
/* Set for next loop */
|
||||||
sort_info.max_records= (ha_rows) sort_info.new_info->state->records;
|
sort_info.max_records= (ha_rows) sort_info.new_info->s->state.state.records;
|
||||||
|
|
||||||
if (param->testflag & T_STATISTICS)
|
if (param->testflag & T_STATISTICS)
|
||||||
maria_update_key_parts(sort_param.keyinfo, rec_per_key_part,
|
maria_update_key_parts(sort_param.keyinfo, rec_per_key_part,
|
||||||
sort_param.unique,
|
sort_param.unique,
|
||||||
(param->stats_method ==
|
(param->stats_method ==
|
||||||
MI_STATS_METHOD_IGNORE_NULLS ?
|
MI_STATS_METHOD_IGNORE_NULLS ?
|
||||||
sort_param.notnull : NULL),
|
sort_param.notnull : NULL),
|
||||||
(ulonglong) info->state->records);
|
(ulonglong) share->state.state.records);
|
||||||
maria_set_key_active(share->state.key_map, sort_param.key);
|
maria_set_key_active(share->state.key_map, sort_param.key);
|
||||||
DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
|
DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
|
||||||
|
|
||||||
@ -3667,17 +3669,17 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
if (param->testflag & T_SAFE_REPAIR)
|
if (param->testflag & T_SAFE_REPAIR)
|
||||||
{
|
{
|
||||||
/* Don't repair if we loosed more than one row */
|
/* Don't repair if we loosed more than one row */
|
||||||
if (info->state->records+1 < start_records)
|
if (share->state.state.records+1 < start_records)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,
|
_ma_check_print_error(param,
|
||||||
"Rows lost; Aborting because safe repair was "
|
"Rows lost; Aborting because safe repair was "
|
||||||
"requested");
|
"requested");
|
||||||
info->state->records=start_records;
|
share->state.state.records=start_records;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort_info.new_info->state->data_file_length= sort_param.filepos;
|
sort_info.new_info->s->state.state.data_file_length= sort_param.filepos;
|
||||||
if (sort_info.new_info != sort_info.info)
|
if (sort_info.new_info != sort_info.info)
|
||||||
{
|
{
|
||||||
MARIA_STATE_INFO save_state= sort_info.new_info->s->state;
|
MARIA_STATE_INFO save_state= sort_info.new_info->s->state;
|
||||||
@ -3716,11 +3718,11 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
org_header_length= share->pack.header_length;
|
org_header_length= share->pack.header_length;
|
||||||
sort_info.org_data_file_type= share->data_file_type;
|
sort_info.org_data_file_type= share->data_file_type;
|
||||||
sort_info.filelength= info->state->data_file_length;
|
sort_info.filelength= share->state.state.data_file_length;
|
||||||
sort_param.fix_datafile=0;
|
sort_param.fix_datafile=0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
info->state->data_file_length=sort_param.max_pos;
|
share->state.state.data_file_length=sort_param.max_pos;
|
||||||
|
|
||||||
param->read_cache.file= info->dfile.file; /* re-init read cache */
|
param->read_cache.file= info->dfile.file; /* re-init read cache */
|
||||||
reinit_io_cache(¶m->read_cache,READ_CACHE,share->pack.header_length,
|
reinit_io_cache(¶m->read_cache,READ_CACHE,share->pack.header_length,
|
||||||
@ -3732,7 +3734,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
|
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rep_quick && del+sort_info.dupp != info->state->del)
|
if (rep_quick && del+sort_info.dupp != share->state.state.del)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
|
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
|
||||||
_ma_check_print_error(param,"Run recovery again without -q");
|
_ma_check_print_error(param,"Run recovery again without -q");
|
||||||
@ -3744,7 +3746,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
if (rep_quick && (param->testflag & T_FORCE_UNIQUENESS))
|
if (rep_quick && (param->testflag & T_FORCE_UNIQUENESS))
|
||||||
{
|
{
|
||||||
my_off_t skr= (info->state->data_file_length +
|
my_off_t skr= (share->state.state.data_file_length +
|
||||||
(sort_info.org_data_file_type == COMPRESSED_RECORD) ?
|
(sort_info.org_data_file_type == COMPRESSED_RECORD) ?
|
||||||
MEMMAP_EXTRA_MARGIN : 0);
|
MEMMAP_EXTRA_MARGIN : 0);
|
||||||
#ifdef USE_RELOC
|
#ifdef USE_RELOC
|
||||||
@ -3760,30 +3762,31 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (param->testflag & T_CALC_CHECKSUM)
|
if (param->testflag & T_CALC_CHECKSUM)
|
||||||
info->state->checksum=param->glob_crc;
|
share->state.state.checksum=param->glob_crc;
|
||||||
|
|
||||||
if (my_chsize(share->kfile.file, info->state->key_file_length, 0, MYF(0)))
|
if (my_chsize(share->kfile.file, share->state.state.key_file_length, 0, MYF(0)))
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Can't change size of indexfile, error: %d",
|
"Can't change size of indexfile, error: %d",
|
||||||
my_errno);
|
my_errno);
|
||||||
|
|
||||||
if (!(param->testflag & T_SILENT))
|
if (!(param->testflag & T_SILENT))
|
||||||
{
|
{
|
||||||
if (start_records != info->state->records)
|
if (start_records != share->state.state.records)
|
||||||
printf("Data records: %s\n", llstr(info->state->records,llbuff));
|
printf("Data records: %s\n", llstr(share->state.state.records,llbuff));
|
||||||
}
|
}
|
||||||
if (sort_info.dupp)
|
if (sort_info.dupp)
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"%s records have been removed",
|
"%s records have been removed",
|
||||||
llstr(sort_info.dupp,llbuff));
|
llstr(sort_info.dupp,llbuff));
|
||||||
got_error=0;
|
got_error=0;
|
||||||
|
/* If invoked by external program that uses thr_lock */
|
||||||
if (&share->state.state != info->state)
|
if (&share->state.state != info->state)
|
||||||
memcpy(&share->state.state, info->state, sizeof(*info->state));
|
*info->state= *info->state_start= share->state.state;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (scan_inited)
|
if (scan_inited)
|
||||||
maria_scan_end(sort_info.info);
|
maria_scan_end(sort_info.info);
|
||||||
|
_ma_reset_state(info);
|
||||||
|
|
||||||
VOID(end_io_cache(&sort_info.new_info->rec_cache));
|
VOID(end_io_cache(&sort_info.new_info->rec_cache));
|
||||||
VOID(end_io_cache(¶m->read_cache));
|
VOID(end_io_cache(¶m->read_cache));
|
||||||
@ -3909,7 +3912,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
got_error= 1;
|
got_error= 1;
|
||||||
new_file= -1;
|
new_file= -1;
|
||||||
start_records= info->state->records;
|
start_records= share->state.state.records;
|
||||||
if (!(param->testflag & T_SILENT))
|
if (!(param->testflag & T_SILENT))
|
||||||
{
|
{
|
||||||
printf("- parallel recovering (with sort) MARIA-table '%s'\n",name);
|
printf("- parallel recovering (with sort) MARIA-table '%s'\n",name);
|
||||||
@ -4014,7 +4017,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
+1 below is required hack for parallel repair mode.
|
+1 below is required hack for parallel repair mode.
|
||||||
The info->state->records value, that is compared later
|
The share->state.state.records value, that is compared later
|
||||||
to sort_info.max_records and cannot exceed it, is
|
to sort_info.max_records and cannot exceed it, is
|
||||||
increased in sort_key_write. In maria_repair_by_sort, sort_key_write
|
increased in sort_key_write. In maria_repair_by_sort, sort_key_write
|
||||||
is called after sort_key_read, where the comparison is performed,
|
is called after sort_key_read, where the comparison is performed,
|
||||||
@ -4026,7 +4029,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
*/
|
*/
|
||||||
sort_info.max_records++;
|
sort_info.max_records++;
|
||||||
|
|
||||||
del=info->state->del;
|
del=share->state.state.del;
|
||||||
|
|
||||||
if (!(sort_param=(MARIA_SORT_PARAM *)
|
if (!(sort_param=(MARIA_SORT_PARAM *)
|
||||||
my_malloc((uint) share->base.keys *
|
my_malloc((uint) share->base.keys *
|
||||||
@ -4038,8 +4041,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
}
|
}
|
||||||
total_key_length=0;
|
total_key_length=0;
|
||||||
rec_per_key_part= param->new_rec_per_key_part;
|
rec_per_key_part= param->new_rec_per_key_part;
|
||||||
info->state->records=info->state->del=share->state.split=0;
|
share->state.state.records=share->state.state.del=share->state.split=0;
|
||||||
info->state->empty=0;
|
share->state.state.empty=0;
|
||||||
|
|
||||||
for (i=key=0, istep=1 ; key < share->base.keys ;
|
for (i=key=0, istep=1 ; key < share->base.keys ;
|
||||||
rec_per_key_part+=sort_param[i].keyinfo->keysegs, i+=istep, key++)
|
rec_per_key_part+=sort_param[i].keyinfo->keysegs, i+=istep, key++)
|
||||||
@ -4213,16 +4216,16 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
if (param->testflag & T_SAFE_REPAIR)
|
if (param->testflag & T_SAFE_REPAIR)
|
||||||
{
|
{
|
||||||
/* Don't repair if we loosed more than one row */
|
/* Don't repair if we loosed more than one row */
|
||||||
if (info->state->records+1 < start_records)
|
if (share->state.state.records+1 < start_records)
|
||||||
{
|
{
|
||||||
info->state->records=start_records;
|
share->state.state.records=start_records;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
share->state.state.data_file_length= info->state->data_file_length=
|
share->state.state.data_file_length= share->state.state.data_file_length=
|
||||||
sort_param->filepos;
|
sort_param->filepos;
|
||||||
/* Only whole records */
|
/* Only whole records */
|
||||||
share->state.version=(ulong) time((time_t*) 0);
|
share->state.version= (ulong) time((time_t*) 0);
|
||||||
/*
|
/*
|
||||||
Exchange the data file descriptor of the table, so that we use the
|
Exchange the data file descriptor of the table, so that we use the
|
||||||
new file from now on.
|
new file from now on.
|
||||||
@ -4232,9 +4235,9 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
share->pack.header_length=(ulong) new_header_length;
|
share->pack.header_length=(ulong) new_header_length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
info->state->data_file_length=sort_param->max_pos;
|
share->state.state.data_file_length=sort_param->max_pos;
|
||||||
|
|
||||||
if (rep_quick && del+sort_info.dupp != info->state->del)
|
if (rep_quick && del+sort_info.dupp != share->state.state.del)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
|
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
|
||||||
_ma_check_print_error(param,"Run recovery again without -q");
|
_ma_check_print_error(param,"Run recovery again without -q");
|
||||||
@ -4245,7 +4248,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
|
|
||||||
if (rep_quick && (param->testflag & T_FORCE_UNIQUENESS))
|
if (rep_quick && (param->testflag & T_FORCE_UNIQUENESS))
|
||||||
{
|
{
|
||||||
my_off_t skr= (info->state->data_file_length +
|
my_off_t skr= (share->state.state.data_file_length +
|
||||||
(sort_info.org_data_file_type == COMPRESSED_RECORD) ?
|
(sort_info.org_data_file_type == COMPRESSED_RECORD) ?
|
||||||
MEMMAP_EXTRA_MARGIN : 0);
|
MEMMAP_EXTRA_MARGIN : 0);
|
||||||
#ifdef USE_RELOC
|
#ifdef USE_RELOC
|
||||||
@ -4260,28 +4263,30 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
|||||||
my_errno);
|
my_errno);
|
||||||
}
|
}
|
||||||
if (param->testflag & T_CALC_CHECKSUM)
|
if (param->testflag & T_CALC_CHECKSUM)
|
||||||
info->state->checksum=param->glob_crc;
|
share->state.state.checksum=param->glob_crc;
|
||||||
|
|
||||||
if (my_chsize(share->kfile.file, info->state->key_file_length, 0, MYF(0)))
|
if (my_chsize(share->kfile.file, share->state.state.key_file_length, 0, MYF(0)))
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Can't change size of indexfile, error: %d",
|
"Can't change size of indexfile, error: %d",
|
||||||
my_errno);
|
my_errno);
|
||||||
|
|
||||||
if (!(param->testflag & T_SILENT))
|
if (!(param->testflag & T_SILENT))
|
||||||
{
|
{
|
||||||
if (start_records != info->state->records)
|
if (start_records != share->state.state.records)
|
||||||
printf("Data records: %s\n", llstr(info->state->records,llbuff));
|
printf("Data records: %s\n", llstr(share->state.state.records,llbuff));
|
||||||
}
|
}
|
||||||
if (sort_info.dupp)
|
if (sort_info.dupp)
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"%s records have been removed",
|
"%s records have been removed",
|
||||||
llstr(sort_info.dupp,llbuff));
|
llstr(sort_info.dupp,llbuff));
|
||||||
got_error=0;
|
got_error=0;
|
||||||
|
/* If invoked by external program that uses thr_lock */
|
||||||
if (&share->state.state != info->state)
|
if (&share->state.state != info->state)
|
||||||
memcpy(&share->state.state, info->state, sizeof(*info->state));
|
*info->state= *info->state_start= share->state.state;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
_ma_reset_state(info);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Destroy the write cache. The master thread did already detach from
|
Destroy the write cache. The master thread did already detach from
|
||||||
the share by remove_io_thread() or it was not yet started (if the
|
the share by remove_io_thread() or it was not yet started (if the
|
||||||
@ -4360,7 +4365,7 @@ static int sort_key_read(MARIA_SORT_PARAM *sort_param, uchar *key)
|
|||||||
|
|
||||||
if ((error=sort_get_next_record(sort_param)))
|
if ((error=sort_get_next_record(sort_param)))
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
if (info->state->records == sort_info->max_records)
|
if (info->s->state.state.records == sort_info->max_records)
|
||||||
{
|
{
|
||||||
_ma_check_print_error(sort_info->param,
|
_ma_check_print_error(sort_info->param,
|
||||||
"Key %d - Found too many records; Can't continue",
|
"Key %d - Found too many records; Can't continue",
|
||||||
@ -4504,7 +4509,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
Scan on clean table.
|
Scan on clean table.
|
||||||
It requires a reliable data_file_length so we set it.
|
It requires a reliable data_file_length so we set it.
|
||||||
*/
|
*/
|
||||||
info->state->data_file_length= sort_info->filelength;
|
share->state.state.data_file_length= sort_info->filelength;
|
||||||
info->cur_row.trid= 0;
|
info->cur_row.trid= 0;
|
||||||
flag= _ma_scan_block_record(info, sort_param->record,
|
flag= _ma_scan_block_record(info, sort_param->record,
|
||||||
info->cur_row.nextpos, 1);
|
info->cur_row.nextpos, 1);
|
||||||
@ -4542,7 +4547,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
}
|
}
|
||||||
if (flag == HA_ERR_END_OF_FILE)
|
if (flag == HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
sort_param->max_pos= info->state->data_file_length;
|
sort_param->max_pos= share->state.state.data_file_length;
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
/* Retry only if wrong record, not if disk error */
|
/* Retry only if wrong record, not if disk error */
|
||||||
@ -4580,8 +4585,8 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
}
|
}
|
||||||
if (!sort_param->fix_datafile && sort_param->master)
|
if (!sort_param->fix_datafile && sort_param->master)
|
||||||
{
|
{
|
||||||
info->state->del++;
|
share->state.state.del++;
|
||||||
info->state->empty+=share->base.pack_reclength;
|
share->state.state.empty+=share->base.pack_reclength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case DYNAMIC_RECORD:
|
case DYNAMIC_RECORD:
|
||||||
@ -4685,9 +4690,9 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
{
|
{
|
||||||
if ((block_info.next_filepos != HA_OFFSET_ERROR &&
|
if ((block_info.next_filepos != HA_OFFSET_ERROR &&
|
||||||
block_info.next_filepos >=
|
block_info.next_filepos >=
|
||||||
info->state->data_file_length) ||
|
share->state.state.data_file_length) ||
|
||||||
(block_info.prev_filepos != HA_OFFSET_ERROR &&
|
(block_info.prev_filepos != HA_OFFSET_ERROR &&
|
||||||
block_info.prev_filepos >= info->state->data_file_length))
|
block_info.prev_filepos >= share->state.state.data_file_length))
|
||||||
{
|
{
|
||||||
if (!searching)
|
if (!searching)
|
||||||
_ma_check_print_info(param,
|
_ma_check_print_info(param,
|
||||||
@ -4735,8 +4740,8 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
if (!sort_param->fix_datafile && sort_param->master &&
|
if (!sort_param->fix_datafile && sort_param->master &&
|
||||||
(b_type & BLOCK_DELETED))
|
(b_type & BLOCK_DELETED))
|
||||||
{
|
{
|
||||||
info->state->empty+=block_info.block_len;
|
share->state.state.empty+=block_info.block_len;
|
||||||
info->state->del++;
|
share->state.state.del++;
|
||||||
share->state.split++;
|
share->state.split++;
|
||||||
}
|
}
|
||||||
if (found_record)
|
if (found_record)
|
||||||
@ -5010,7 +5015,7 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
HA_OFFSET_ERROR)
|
HA_OFFSET_ERROR)
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
/* Pointer to end of file */
|
/* Pointer to end of file */
|
||||||
sort_param->filepos= info->state->data_file_length;
|
sort_param->filepos= share->state.state.data_file_length;
|
||||||
break;
|
break;
|
||||||
case STATIC_RECORD:
|
case STATIC_RECORD:
|
||||||
if (my_b_write(&info->rec_cache,sort_param->record,
|
if (my_b_write(&info->rec_cache,sort_param->record,
|
||||||
@ -5089,12 +5094,12 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
}
|
}
|
||||||
if (sort_param->master)
|
if (sort_param->master)
|
||||||
{
|
{
|
||||||
info->state->records++;
|
share->state.state.records++;
|
||||||
if ((param->testflag & T_WRITE_LOOP) &&
|
if ((param->testflag & T_WRITE_LOOP) &&
|
||||||
(info->state->records % WRITE_COUNT) == 0)
|
(share->state.state.records % WRITE_COUNT) == 0)
|
||||||
{
|
{
|
||||||
char llbuff[22];
|
char llbuff[22];
|
||||||
printf("%s\r", llstr(info->state->records,llbuff));
|
printf("%s\r", llstr(share->state.state.records,llbuff));
|
||||||
VOID(fflush(stdout));
|
VOID(fflush(stdout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5392,7 +5397,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
|
|||||||
_ma_store_page_used(share, anc_buff, key_block->last_length);
|
_ma_store_page_used(share, anc_buff, key_block->last_length);
|
||||||
bzero(anc_buff+key_block->last_length,
|
bzero(anc_buff+key_block->last_length,
|
||||||
keyinfo->block_length- key_block->last_length);
|
keyinfo->block_length- key_block->last_length);
|
||||||
key_file_length=info->state->key_file_length;
|
key_file_length=share->state.state.key_file_length;
|
||||||
if ((filepos= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR)
|
if ((filepos= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR)
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
_ma_fast_unlock_key_del(info);
|
_ma_fast_unlock_key_del(info);
|
||||||
@ -5491,7 +5496,7 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
_ma_check_print_error(param,"Got error %d when deleting record",
|
_ma_check_print_error(param,"Got error %d when deleting record",
|
||||||
my_errno);
|
my_errno);
|
||||||
row_info->dfile.file= old_file; /* restore actual value */
|
row_info->dfile.file= old_file; /* restore actual value */
|
||||||
row_info->state->records--;
|
row_info->s->state.state.records--;
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
} /* sort_delete_record */
|
} /* sort_delete_record */
|
||||||
|
|
||||||
@ -5518,7 +5523,7 @@ int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param)
|
|||||||
length= _ma_get_page_used(info->s, key_block->buff);
|
length= _ma_get_page_used(info->s, key_block->buff);
|
||||||
if (nod_flag)
|
if (nod_flag)
|
||||||
_ma_kpointer(info,key_block->end_pos,filepos);
|
_ma_kpointer(info,key_block->end_pos,filepos);
|
||||||
key_file_length=info->state->key_file_length;
|
key_file_length= info->s->state.state.key_file_length;
|
||||||
bzero(key_block->buff+length, keyinfo->block_length-length);
|
bzero(key_block->buff+length, keyinfo->block_length-length);
|
||||||
if ((filepos= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
|
if ((filepos= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
|
||||||
HA_OFFSET_ERROR)
|
HA_OFFSET_ERROR)
|
||||||
@ -5753,16 +5758,16 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
|
|||||||
/* We are modifing */
|
/* We are modifing */
|
||||||
(*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
|
(*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
|
||||||
VOID(_ma_readinfo(*org_info,F_WRLCK,0));
|
VOID(_ma_readinfo(*org_info,F_WRLCK,0));
|
||||||
(*org_info)->state->records=info.state->records;
|
(*org_info)->s->state.state.records= info.state->records;
|
||||||
if (share.state.create_time)
|
if (share.state.create_time)
|
||||||
(*org_info)->s->state.create_time=share.state.create_time;
|
(*org_info)->s->state.create_time=share.state.create_time;
|
||||||
(*org_info)->s->state.unique=(*org_info)->this_unique=
|
(*org_info)->s->state.unique= (*org_info)->this_unique= share.state.unique;
|
||||||
share.state.unique;
|
(*org_info)->s->state.state.checksum= info.state->checksum;
|
||||||
(*org_info)->state->checksum=info.state->checksum;
|
(*org_info)->s->state.state.del= info.state->del;
|
||||||
(*org_info)->state->del=info.state->del;
|
(*org_info)->s->state.dellink= share.state.dellink;
|
||||||
(*org_info)->s->state.dellink=share.state.dellink;
|
(*org_info)->s->state.state.empty= info.state->empty;
|
||||||
(*org_info)->state->empty=info.state->empty;
|
(*org_info)->s->state.state.data_file_length= info.state->data_file_length;
|
||||||
(*org_info)->state->data_file_length=info.state->data_file_length;
|
*(*org_info)->state= (*org_info)->s->state.state;
|
||||||
if (maria_update_state_info(param,*org_info,UPDATE_TIME | UPDATE_STAT |
|
if (maria_update_state_info(param,*org_info,UPDATE_TIME | UPDATE_STAT |
|
||||||
UPDATE_OPEN_COUNT))
|
UPDATE_OPEN_COUNT))
|
||||||
goto end;
|
goto end;
|
||||||
@ -5813,9 +5818,9 @@ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update)
|
|||||||
if (update & UPDATE_STAT)
|
if (update & UPDATE_STAT)
|
||||||
{
|
{
|
||||||
uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
|
uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
|
||||||
share->state.records_at_analyze= info->state->records;
|
share->state.records_at_analyze= share->state.state.records;
|
||||||
share->state.changed&= ~STATE_NOT_ANALYZED;
|
share->state.changed&= ~STATE_NOT_ANALYZED;
|
||||||
if (info->state->records)
|
if (share->state.state.records)
|
||||||
{
|
{
|
||||||
for (i=0; i<key_parts; i++)
|
for (i=0; i<key_parts; i++)
|
||||||
{
|
{
|
||||||
@ -5830,16 +5835,8 @@ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update)
|
|||||||
{
|
{
|
||||||
share->state.check_time= (long) time((time_t*) 0);
|
share->state.check_time= (long) time((time_t*) 0);
|
||||||
if (!share->state.create_time)
|
if (!share->state.create_time)
|
||||||
share->state.create_time=share->state.check_time;
|
share->state.create_time= share->state.check_time;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
When tables are locked we haven't synched the share state and the
|
|
||||||
real state for a while so we better do it here before synching
|
|
||||||
the share state to disk. Only when table is write locked is it
|
|
||||||
necessary to perform this synch.
|
|
||||||
*/
|
|
||||||
if (info->lock_type == F_WRLCK)
|
|
||||||
share->state.state= *info->state;
|
|
||||||
if (_ma_state_info_write(share, 1|2))
|
if (_ma_state_info_write(share, 1|2))
|
||||||
goto err;
|
goto err;
|
||||||
share->changed=0;
|
share->changed=0;
|
||||||
@ -6064,7 +6061,7 @@ void maria_disable_non_unique_index(MARIA_HA *info, ha_rows rows)
|
|||||||
MARIA_KEYDEF *key=share->keyinfo;
|
MARIA_KEYDEF *key=share->keyinfo;
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
DBUG_ASSERT(info->state->records == 0 &&
|
DBUG_ASSERT(share->state.state.records == 0 &&
|
||||||
(!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES));
|
(!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES));
|
||||||
for (i=0 ; i < share->base.keys ; i++,key++)
|
for (i=0 ; i < share->base.keys ; i++,key++)
|
||||||
{
|
{
|
||||||
@ -6148,7 +6145,7 @@ static my_bool create_new_data_handle(MARIA_SORT_PARAM *param, File new_file)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
/* Take into account any bitmap page created above: */
|
/* Take into account any bitmap page created above: */
|
||||||
param->filepos= new_info->state->data_file_length;
|
param->filepos= new_info->s->state.state.data_file_length;
|
||||||
|
|
||||||
/* Use new virtual functions for key generation */
|
/* Use new virtual functions for key generation */
|
||||||
info->s->keypos_to_recpos= new_info->s->keypos_to_recpos;
|
info->s->keypos_to_recpos= new_info->s->keypos_to_recpos;
|
||||||
|
@ -1053,6 +1053,14 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon)
|
|||||||
}
|
}
|
||||||
DBUG_ASSERT(share->pagecache == maria_pagecache);
|
DBUG_ASSERT(share->pagecache == maria_pagecache);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Clean up any unused states.
|
||||||
|
TODO: Only do this call if there has been # (10?) ended transactions
|
||||||
|
since last call.
|
||||||
|
*/
|
||||||
|
share->state_history= _ma_remove_not_visible_states(share->state_history,
|
||||||
|
0, 0);
|
||||||
|
|
||||||
if (share->in_checkpoint & MARIA_CHECKPOINT_SHOULD_FREE_ME)
|
if (share->in_checkpoint & MARIA_CHECKPOINT_SHOULD_FREE_ME)
|
||||||
{
|
{
|
||||||
/* maria_close() left us to free the share */
|
/* maria_close() left us to free the share */
|
||||||
|
@ -128,6 +128,27 @@ int maria_close(register MARIA_HA *info)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
share_can_be_freed= TRUE;
|
share_can_be_freed= TRUE;
|
||||||
|
|
||||||
|
/* Remember share->history for future opens */
|
||||||
|
share->state_history= _ma_remove_not_visible_states(share->state_history,
|
||||||
|
1, 0);
|
||||||
|
if (share->state_history)
|
||||||
|
{
|
||||||
|
MARIA_STATE_HISTORY_CLOSED *history;
|
||||||
|
/*
|
||||||
|
Here we ignore the unlikely case that we don't have memory to
|
||||||
|
store the case. In the worst case what happens is that any transaction
|
||||||
|
that tries to access this table will get a wrong status information.
|
||||||
|
*/
|
||||||
|
if ((history= (MARIA_STATE_HISTORY_CLOSED *)
|
||||||
|
my_malloc(sizeof(*history), MYF(MY_WME))))
|
||||||
|
{
|
||||||
|
history->create_rename_lsn= share->state.create_rename_lsn;
|
||||||
|
history->state_history= share->state_history;
|
||||||
|
if (my_hash_insert(&maria_stored_state, (uchar*) history))
|
||||||
|
my_free(history, MYF(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&THR_LOCK_maria);
|
pthread_mutex_unlock(&THR_LOCK_maria);
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
@ -49,6 +49,8 @@ int ma_commit(TRN *trn)
|
|||||||
if crash happens between the two, trn will be rolled back which is an
|
if crash happens between the two, trn will be rolled back which is an
|
||||||
issue (transaction's updates were made visible to other transactions).
|
issue (transaction's updates were made visible to other transactions).
|
||||||
So we need to go the first way.
|
So we need to go the first way.
|
||||||
|
|
||||||
|
Note that we have to use | here to ensure that all calls are made.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -56,11 +58,13 @@ int ma_commit(TRN *trn)
|
|||||||
needed only when we support XA.
|
needed only when we support XA.
|
||||||
*/
|
*/
|
||||||
res= (translog_write_record(&commit_lsn, LOGREC_COMMIT,
|
res= (translog_write_record(&commit_lsn, LOGREC_COMMIT,
|
||||||
trn, NULL, 0,
|
trn, NULL, 0,
|
||||||
sizeof(log_array)/sizeof(log_array[0]),
|
sizeof(log_array)/sizeof(log_array[0]),
|
||||||
log_array, NULL, NULL) ||
|
log_array, NULL, NULL) |
|
||||||
translog_flush(commit_lsn) ||
|
translog_flush(commit_lsn) |
|
||||||
trnman_commit_trn(trn));
|
trnman_commit_trn(trn));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note: if trnman_commit_trn() fails above, we have already
|
Note: if trnman_commit_trn() fails above, we have already
|
||||||
written the COMMIT record, so Checkpoint and Recovery will see the
|
written the COMMIT record, so Checkpoint and Recovery will see the
|
||||||
@ -96,7 +100,6 @@ int maria_commit(MARIA_HA *info)
|
|||||||
@retval # Error code.
|
@retval # Error code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int maria_begin(MARIA_HA *info)
|
int maria_begin(MARIA_HA *info)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("maria_begin");
|
DBUG_ENTER("maria_begin");
|
||||||
@ -116,3 +119,4 @@ int maria_begin(MARIA_HA *info)
|
|||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,11 +111,8 @@ int maria_delete(MARIA_HA *info,const uchar *record)
|
|||||||
if ((*share->delete_record)(info, record))
|
if ((*share->delete_record)(info, record))
|
||||||
goto err; /* Remove record from database */
|
goto err; /* Remove record from database */
|
||||||
|
|
||||||
if (!share->now_transactional)
|
info->state->checksum-= info->cur_row.checksum;
|
||||||
{
|
info->state->records--;
|
||||||
info->state->checksum-= info->cur_row.checksum;
|
|
||||||
info->state->records--;
|
|
||||||
}
|
|
||||||
info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED;
|
info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED;
|
||||||
share->state.changed|= (STATE_NOT_OPTIMIZED_ROWS | STATE_NOT_MOVABLE |
|
share->state.changed|= (STATE_NOT_OPTIMIZED_ROWS | STATE_NOT_MOVABLE |
|
||||||
STATE_NOT_ZEROFILLED);
|
STATE_NOT_ZEROFILLED);
|
||||||
|
@ -91,13 +91,12 @@ int maria_delete_all_rows(MARIA_HA *info)
|
|||||||
if (_ma_flush_table_files(info, MARIA_FLUSH_DATA|MARIA_FLUSH_INDEX,
|
if (_ma_flush_table_files(info, MARIA_FLUSH_DATA|MARIA_FLUSH_INDEX,
|
||||||
FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED) ||
|
FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED) ||
|
||||||
my_chsize(info->dfile.file, 0, 0, MYF(MY_WME)) ||
|
my_chsize(info->dfile.file, 0, 0, MYF(MY_WME)) ||
|
||||||
my_chsize(share->kfile.file, share->base.keystart, 0, MYF(MY_WME)) )
|
my_chsize(share->kfile.file, share->base.keystart, 0, MYF(MY_WME)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (_ma_initialize_data_file(share, info->dfile.file))
|
if (_ma_initialize_data_file(share, info->dfile.file))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
||||||
if (log_record)
|
if (log_record)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -156,14 +155,17 @@ void _ma_reset_status(MARIA_HA *info)
|
|||||||
MARIA_STATE_INFO *state= &share->state;
|
MARIA_STATE_INFO *state= &share->state;
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
info->state->records= info->state->del= state->split= 0;
|
state->split= 0;
|
||||||
|
state->state.records= state->state.del= 0;
|
||||||
state->changed= 0; /* File is optimized */
|
state->changed= 0; /* File is optimized */
|
||||||
state->dellink= HA_OFFSET_ERROR;
|
state->dellink= HA_OFFSET_ERROR;
|
||||||
state->sortkey= (ushort) ~0;
|
state->sortkey= (ushort) ~0;
|
||||||
info->state->key_file_length= share->base.keystart;
|
state->state.key_file_length= share->base.keystart;
|
||||||
info->state->data_file_length= 0;
|
state->state.data_file_length= 0;
|
||||||
info->state->empty= info->state->key_empty= 0;
|
state->state.empty= state->state.key_empty= 0;
|
||||||
info->state->checksum= 0;
|
state->state.checksum= 0;
|
||||||
|
|
||||||
|
*info->state= state->state;
|
||||||
|
|
||||||
/* Drop the delete key chain. */
|
/* Drop the delete key chain. */
|
||||||
state->key_del= HA_OFFSET_ERROR;
|
state->key_del= HA_OFFSET_ERROR;
|
||||||
|
@ -136,7 +136,7 @@ size_t _ma_mmap_pread(MARIA_HA *info, uchar *Buffer,
|
|||||||
size_t Count, my_off_t offset, myf MyFlags)
|
size_t Count, my_off_t offset, myf MyFlags)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("maria_read with mmap %d\n", info->dfile.file));
|
DBUG_PRINT("info", ("maria_read with mmap %d\n", info->dfile.file));
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_rdlock(&info->s->mmap_lock);
|
rw_rdlock(&info->s->mmap_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -149,13 +149,13 @@ size_t _ma_mmap_pread(MARIA_HA *info, uchar *Buffer,
|
|||||||
if (info->s->mmaped_length >= offset + Count)
|
if (info->s->mmaped_length >= offset + Count)
|
||||||
{
|
{
|
||||||
memcpy(Buffer, info->s->file_map + offset, Count);
|
memcpy(Buffer, info->s->file_map + offset, Count);
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_unlock(&info->s->mmap_lock);
|
rw_unlock(&info->s->mmap_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_unlock(&info->s->mmap_lock);
|
rw_unlock(&info->s->mmap_lock);
|
||||||
return my_pread(info->dfile.file, Buffer, Count, offset, MyFlags);
|
return my_pread(info->dfile.file, Buffer, Count, offset, MyFlags);
|
||||||
}
|
}
|
||||||
@ -191,7 +191,7 @@ size_t _ma_mmap_pwrite(MARIA_HA *info, const uchar *Buffer,
|
|||||||
size_t Count, my_off_t offset, myf MyFlags)
|
size_t Count, my_off_t offset, myf MyFlags)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("maria_write with mmap %d\n", info->dfile.file));
|
DBUG_PRINT("info", ("maria_write with mmap %d\n", info->dfile.file));
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_rdlock(&info->s->mmap_lock);
|
rw_rdlock(&info->s->mmap_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -204,14 +204,14 @@ size_t _ma_mmap_pwrite(MARIA_HA *info, const uchar *Buffer,
|
|||||||
if (info->s->mmaped_length >= offset + Count)
|
if (info->s->mmaped_length >= offset + Count)
|
||||||
{
|
{
|
||||||
memcpy(info->s->file_map + offset, Buffer, Count);
|
memcpy(info->s->file_map + offset, Buffer, Count);
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_unlock(&info->s->mmap_lock);
|
rw_unlock(&info->s->mmap_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->s->nonmmaped_inserts++;
|
info->s->nonmmaped_inserts++;
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_unlock(&info->s->mmap_lock);
|
rw_unlock(&info->s->mmap_lock);
|
||||||
return my_pwrite(info->dfile.file, Buffer, Count, offset, MyFlags);
|
return my_pwrite(info->dfile.file, Buffer, Count, offset, MyFlags);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
|
|||||||
cache_size= (extra_arg ? *(ulong*) extra_arg :
|
cache_size= (extra_arg ? *(ulong*) extra_arg :
|
||||||
my_default_record_cache_size);
|
my_default_record_cache_size);
|
||||||
if (!(init_io_cache(&info->rec_cache, info->dfile.file,
|
if (!(init_io_cache(&info->rec_cache, info->dfile.file,
|
||||||
(uint) min(info->state->data_file_length+1,
|
(uint) min(share->state.state.data_file_length+1,
|
||||||
cache_size),
|
cache_size),
|
||||||
READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
|
READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
|
||||||
MYF(share->write_flag & MY_WAIT_IF_FULL))))
|
MYF(share->write_flag & MY_WAIT_IF_FULL))))
|
||||||
@ -113,7 +113,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
|
|||||||
info->opt_flag|= READ_CACHE_USED;
|
info->opt_flag|= READ_CACHE_USED;
|
||||||
info->update&= ~HA_STATE_ROW_CHANGED;
|
info->update&= ~HA_STATE_ROW_CHANGED;
|
||||||
}
|
}
|
||||||
if (share->concurrent_insert)
|
if (share->non_transactional_concurrent_insert)
|
||||||
info->rec_cache.end_of_file= info->state->data_file_length;
|
info->rec_cache.end_of_file= info->state->data_file_length;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -124,7 +124,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
|
|||||||
(pbool) (info->lock_type != F_UNLCK),
|
(pbool) (info->lock_type != F_UNLCK),
|
||||||
(pbool) test(info->update & HA_STATE_ROW_CHANGED));
|
(pbool) test(info->update & HA_STATE_ROW_CHANGED));
|
||||||
info->update&= ~HA_STATE_ROW_CHANGED;
|
info->update&= ~HA_STATE_ROW_CHANGED;
|
||||||
if (share->concurrent_insert)
|
if (share->non_transactional_concurrent_insert)
|
||||||
info->rec_cache.end_of_file= info->state->data_file_length;
|
info->rec_cache.end_of_file= info->state->data_file_length;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -143,7 +143,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
|
|||||||
(READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
|
(READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
|
||||||
!share->state.header.uniques)
|
!share->state.header.uniques)
|
||||||
if (!(init_io_cache(&info->rec_cache, info->dfile.file, cache_size,
|
if (!(init_io_cache(&info->rec_cache, info->dfile.file, cache_size,
|
||||||
WRITE_CACHE,info->state->data_file_length,
|
WRITE_CACHE,share->state.state.data_file_length,
|
||||||
(pbool) (info->lock_type != F_UNLCK),
|
(pbool) (info->lock_type != F_UNLCK),
|
||||||
MYF(share->write_flag & MY_WAIT_IF_FULL))))
|
MYF(share->write_flag & MY_WAIT_IF_FULL))))
|
||||||
{
|
{
|
||||||
@ -258,7 +258,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
|
|||||||
share->state.open_count++;
|
share->state.open_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
share->state.state= *info->state;
|
if (!share->now_transactional)
|
||||||
|
share->state.state= *info->state;
|
||||||
/*
|
/*
|
||||||
That state write to disk must be done, even for transactional tables;
|
That state write to disk must be done, even for transactional tables;
|
||||||
indeed the table's share is going to be lost (there was a
|
indeed the table's share is going to be lost (there was a
|
||||||
@ -546,27 +547,36 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
|
|||||||
enum flush_type flush_type_for_data,
|
enum flush_type flush_type_for_data,
|
||||||
enum flush_type flush_type_for_index)
|
enum flush_type flush_type_for_index)
|
||||||
{
|
{
|
||||||
|
int error= 0;
|
||||||
MARIA_SHARE *share= info->s;
|
MARIA_SHARE *share= info->s;
|
||||||
/* flush data file first because it's more critical */
|
/* flush data file first because it's more critical */
|
||||||
if (flush_data_or_index & MARIA_FLUSH_DATA)
|
if (flush_data_or_index & MARIA_FLUSH_DATA)
|
||||||
{
|
{
|
||||||
if ((info->opt_flag & WRITE_CACHE_USED) &&
|
if ((info->opt_flag & WRITE_CACHE_USED) &&
|
||||||
|
flush_type_for_data != FLUSH_IGNORE_CHANGED &&
|
||||||
flush_io_cache(&info->rec_cache))
|
flush_io_cache(&info->rec_cache))
|
||||||
goto err;
|
error= 1;
|
||||||
if (share->data_file_type == BLOCK_RECORD)
|
if (share->data_file_type == BLOCK_RECORD)
|
||||||
{
|
{
|
||||||
if(_ma_bitmap_flush(share) ||
|
if (flush_type_for_data != FLUSH_IGNORE_CHANGED)
|
||||||
flush_pagecache_blocks(share->pagecache, &info->dfile,
|
{
|
||||||
flush_type_for_data))
|
if (_ma_bitmap_flush(share))
|
||||||
goto err;
|
error= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
info->s->bitmap.changed= 0;
|
||||||
|
if (flush_pagecache_blocks(share->pagecache, &info->dfile,
|
||||||
|
flush_type_for_data))
|
||||||
|
error= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((flush_data_or_index & MARIA_FLUSH_INDEX) &&
|
if ((flush_data_or_index & MARIA_FLUSH_INDEX) &&
|
||||||
flush_pagecache_blocks(share->pagecache, &share->kfile,
|
flush_pagecache_blocks(share->pagecache, &share->kfile,
|
||||||
flush_type_for_index))
|
flush_type_for_index))
|
||||||
goto err;
|
error= 1;
|
||||||
return 0;
|
if (!error)
|
||||||
err:
|
return 0;
|
||||||
|
|
||||||
maria_print_error(info->s, HA_ERR_CRASHED);
|
maria_print_error(info->s, HA_ERR_CRASHED);
|
||||||
maria_mark_crashed(info);
|
maria_mark_crashed(info);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -50,15 +50,15 @@ int maria_status(MARIA_HA *info, register MARIA_INFO *x, uint flag)
|
|||||||
if (flag & HA_STATUS_VARIABLE)
|
if (flag & HA_STATUS_VARIABLE)
|
||||||
{
|
{
|
||||||
x->records = info->state->records;
|
x->records = info->state->records;
|
||||||
x->deleted = info->state->del;
|
x->deleted = share->state.state.del;
|
||||||
x->delete_length = info->state->empty;
|
x->delete_length = share->state.state.empty;
|
||||||
x->data_file_length =info->state->data_file_length;
|
x->data_file_length = share->state.state.data_file_length;
|
||||||
x->index_file_length=info->state->key_file_length;
|
x->index_file_length= share->state.state.key_file_length;
|
||||||
|
|
||||||
x->keys = share->state.header.keys;
|
x->keys = share->state.header.keys;
|
||||||
x->check_time = share->state.check_time;
|
x->check_time = share->state.check_time;
|
||||||
x->mean_reclength = x->records ?
|
x->mean_reclength = x->records ?
|
||||||
(ulong) ((x->data_file_length - x->delete_length) /x ->records) :
|
(ulong) ((x->data_file_length - x->delete_length) /x->records) :
|
||||||
(ulong) share->min_pack_length;
|
(ulong) share->min_pack_length;
|
||||||
}
|
}
|
||||||
if (flag & HA_STATUS_ERRKEY)
|
if (flag & HA_STATUS_ERRKEY)
|
||||||
|
@ -20,6 +20,25 @@
|
|||||||
#include "ma_blockrec.h"
|
#include "ma_blockrec.h"
|
||||||
#include "trnman_public.h"
|
#include "trnman_public.h"
|
||||||
#include "ma_checkpoint.h"
|
#include "ma_checkpoint.h"
|
||||||
|
#include <hash.h>
|
||||||
|
|
||||||
|
void history_state_free(MARIA_STATE_HISTORY_CLOSED *closed_history)
|
||||||
|
{
|
||||||
|
MARIA_STATE_HISTORY *history, *next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Free all active history
|
||||||
|
In case of maria_open() this list should be empty as the history is moved
|
||||||
|
to handler->share.
|
||||||
|
*/
|
||||||
|
for (history= closed_history->state_history; history ; history= next)
|
||||||
|
{
|
||||||
|
next= history->next;
|
||||||
|
my_free(history, MYF(0));
|
||||||
|
}
|
||||||
|
my_free(closed_history, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialize maria
|
Initialize maria
|
||||||
@ -42,8 +61,11 @@ int maria_init(void)
|
|||||||
maria_inited= TRUE;
|
maria_inited= TRUE;
|
||||||
pthread_mutex_init(&THR_LOCK_maria,MY_MUTEX_INIT_SLOW);
|
pthread_mutex_init(&THR_LOCK_maria,MY_MUTEX_INIT_SLOW);
|
||||||
_ma_init_block_record_data();
|
_ma_init_block_record_data();
|
||||||
|
trnman_end_trans_hook= _ma_trnman_end_trans_hook;
|
||||||
my_handler_error_register();
|
my_handler_error_register();
|
||||||
}
|
}
|
||||||
|
hash_init(&maria_stored_state, &my_charset_bin, 32,
|
||||||
|
0, sizeof(LSN), 0, (hash_free_key) history_state_free, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,5 +95,6 @@ void maria_end(void)
|
|||||||
end_pagecache(maria_pagecache, TRUE);
|
end_pagecache(maria_pagecache, TRUE);
|
||||||
ma_control_file_end();
|
ma_control_file_end();
|
||||||
pthread_mutex_destroy(&THR_LOCK_maria);
|
pthread_mutex_destroy(&THR_LOCK_maria);
|
||||||
|
hash_free(&maria_stored_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,9 +626,9 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn,
|
|||||||
cmp_translog_addr(lsn, share->state.is_of_horizon) >= 0)
|
cmp_translog_addr(lsn, share->state.is_of_horizon) >= 0)
|
||||||
share->state.key_root[key_nr]= file_size - share->block_size;
|
share->state.key_root[key_nr]= file_size - share->block_size;
|
||||||
|
|
||||||
if (file_size > info->state->key_file_length)
|
if (file_size > share->state.state.key_file_length)
|
||||||
{
|
{
|
||||||
info->state->key_file_length= file_size;
|
share->state.state.key_file_length= file_size;
|
||||||
buff= info->keyread_buff;
|
buff= info->keyread_buff;
|
||||||
info->keyread_buff_used= 1;
|
info->keyread_buff_used= 1;
|
||||||
unlock_method= PAGECACHE_LOCK_WRITE;
|
unlock_method= PAGECACHE_LOCK_WRITE;
|
||||||
@ -1138,7 +1138,7 @@ void _ma_unlock_key_del(MARIA_HA *info)
|
|||||||
MARIA_SHARE *share= info->s;
|
MARIA_SHARE *share= info->s;
|
||||||
pthread_mutex_lock(&share->intern_lock);
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
share->used_key_del= 0;
|
share->used_key_del= 0;
|
||||||
share->state.key_del= info->s->current_key_del;
|
share->state.key_del= share->current_key_del;
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
pthread_cond_signal(&share->intern_cond);
|
pthread_cond_signal(&share->intern_cond);
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,9 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
locking of isam-tables.
|
Locking of Maria-tables.
|
||||||
reads info from a isam-table. Must be first request before doing any furter
|
Must be first request before doing any furter calls to any Maria function.
|
||||||
calls to any isamfunktion. Is used to allow many process use the same
|
Is used to allow many process use the same non transactional Maria table
|
||||||
isamdatabase.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ma_ftdefs.h"
|
#include "ma_ftdefs.h"
|
||||||
@ -57,12 +56,14 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
|
|||||||
if (info->lock_type == F_RDLCK)
|
if (info->lock_type == F_RDLCK)
|
||||||
{
|
{
|
||||||
count= --share->r_locks;
|
count= --share->r_locks;
|
||||||
_ma_restore_status(info);
|
if (share->lock_restore_status)
|
||||||
|
(*share->lock_restore_status)(info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
count= --share->w_locks;
|
count= --share->w_locks;
|
||||||
_ma_update_status(info);
|
if (share->lock.update_status)
|
||||||
|
(*share->lock.update_status)(info);
|
||||||
}
|
}
|
||||||
--share->tot_locks;
|
--share->tot_locks;
|
||||||
if (info->lock_type == F_WRLCK && !share->w_locks)
|
if (info->lock_type == F_WRLCK && !share->w_locks)
|
||||||
@ -91,16 +92,16 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
|
|||||||
if (share->changed && !share->w_locks)
|
if (share->changed && !share->w_locks)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
if ((info->s->mmaped_length !=
|
if ((share->mmaped_length !=
|
||||||
info->s->state.state.data_file_length) &&
|
share->state.state.data_file_length) &&
|
||||||
(info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
|
(share->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
|
||||||
{
|
{
|
||||||
if (info->s->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_wrlock(&info->s->mmap_lock);
|
rw_wrlock(&share->mmap_lock);
|
||||||
_ma_remap_file(info, info->s->state.state.data_file_length);
|
_ma_remap_file(info, share->state.state.data_file_length);
|
||||||
info->s->nonmmaped_inserts= 0;
|
share->nonmmaped_inserts= 0;
|
||||||
if (info->s->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_unlock(&info->s->mmap_lock);
|
rw_unlock(&share->mmap_lock);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef EXTERNAL_LOCKING
|
#ifdef EXTERNAL_LOCKING
|
||||||
@ -212,7 +213,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
|
|||||||
VOID(_ma_test_if_changed(info));
|
VOID(_ma_test_if_changed(info));
|
||||||
|
|
||||||
info->lock_type=lock_type;
|
info->lock_type=lock_type;
|
||||||
info->invalidator=info->s->invalidator;
|
info->invalidator=share->invalidator;
|
||||||
share->w_locks++;
|
share->w_locks++;
|
||||||
share->tot_locks++;
|
share->tot_locks++;
|
||||||
break;
|
break;
|
||||||
@ -241,128 +242,6 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
|
|||||||
} /* maria_lock_database */
|
} /* maria_lock_database */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
The following functions are called by thr_lock() in threaded applications
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create a copy of the current status for the table
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
_ma_get_status()
|
|
||||||
param Pointer to Myisam handler
|
|
||||||
concurrent_insert Set to 1 if we are going to do concurrent inserts
|
|
||||||
(THR_WRITE_CONCURRENT_INSERT was used)
|
|
||||||
*/
|
|
||||||
|
|
||||||
void _ma_get_status(void* param, my_bool concurrent_insert)
|
|
||||||
{
|
|
||||||
MARIA_HA *info=(MARIA_HA*) param;
|
|
||||||
DBUG_ENTER("_ma_get_status");
|
|
||||||
DBUG_PRINT("info",("key_file: %ld data_file: %ld concurrent_insert: %d",
|
|
||||||
(long) info->s->state.state.key_file_length,
|
|
||||||
(long) info->s->state.state.data_file_length,
|
|
||||||
concurrent_insert));
|
|
||||||
#ifndef DBUG_OFF
|
|
||||||
if (info->state->key_file_length > info->s->state.state.key_file_length ||
|
|
||||||
info->state->data_file_length > info->s->state.state.data_file_length)
|
|
||||||
DBUG_PRINT("warning",("old info: key_file: %ld data_file: %ld",
|
|
||||||
(long) info->state->key_file_length,
|
|
||||||
(long) info->state->data_file_length));
|
|
||||||
#endif
|
|
||||||
info->save_state=info->s->state.state;
|
|
||||||
info->state= &info->save_state;
|
|
||||||
info->append_insert_at_end= concurrent_insert;
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _ma_update_status(void* param)
|
|
||||||
{
|
|
||||||
MARIA_HA *info=(MARIA_HA*) param;
|
|
||||||
/*
|
|
||||||
Because someone may have closed the table we point at, we only
|
|
||||||
update the state if its our own state. This isn't a problem as
|
|
||||||
we are always pointing at our own lock or at a read lock.
|
|
||||||
(This is enforced by thr_multi_lock.c)
|
|
||||||
*/
|
|
||||||
if (info->state == &info->save_state)
|
|
||||||
{
|
|
||||||
MARIA_SHARE *share= info->s;
|
|
||||||
#ifndef DBUG_OFF
|
|
||||||
DBUG_PRINT("info",("updating status: key_file: %ld data_file: %ld",
|
|
||||||
(long) info->state->key_file_length,
|
|
||||||
(long) info->state->data_file_length));
|
|
||||||
if (info->state->key_file_length < share->state.state.key_file_length ||
|
|
||||||
info->state->data_file_length < share->state.state.data_file_length)
|
|
||||||
DBUG_PRINT("warning",("old info: key_file: %ld data_file: %ld",
|
|
||||||
(long) share->state.state.key_file_length,
|
|
||||||
(long) share->state.state.data_file_length));
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
we are going to modify the state without lock's log, this would break
|
|
||||||
recovery if done with a transactional table.
|
|
||||||
*/
|
|
||||||
DBUG_ASSERT(!info->s->base.born_transactional);
|
|
||||||
share->state.state= *info->state;
|
|
||||||
info->state= &share->state.state;
|
|
||||||
}
|
|
||||||
info->append_insert_at_end= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _ma_restore_status(void *param)
|
|
||||||
{
|
|
||||||
MARIA_HA *info= (MARIA_HA*) param;
|
|
||||||
info->state= &info->s->state.state;
|
|
||||||
info->append_insert_at_end= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _ma_copy_status(void* to,void *from)
|
|
||||||
{
|
|
||||||
((MARIA_HA*) to)->state= &((MARIA_HA*) from)->save_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if should allow concurrent inserts
|
|
||||||
|
|
||||||
IMPLEMENTATION
|
|
||||||
Allow concurrent inserts if we don't have a hole in the table or
|
|
||||||
if there is no active write lock and there is active read locks and
|
|
||||||
maria_concurrent_insert == 2. In this last case the new
|
|
||||||
row('s) are inserted at end of file instead of filling up the hole.
|
|
||||||
|
|
||||||
The last case is to allow one to inserts into a heavily read-used table
|
|
||||||
even if there is holes.
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
If there is a an rtree indexes in the table, concurrent inserts are
|
|
||||||
disabled in maria_open()
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
0 ok to use concurrent inserts
|
|
||||||
1 not ok
|
|
||||||
*/
|
|
||||||
|
|
||||||
my_bool _ma_check_status(void *param)
|
|
||||||
{
|
|
||||||
MARIA_HA *info=(MARIA_HA*) param;
|
|
||||||
/*
|
|
||||||
The test for w_locks == 1 is here because this thread has already done an
|
|
||||||
external lock (in other words: w_locks == 1 means no other threads has
|
|
||||||
a write lock)
|
|
||||||
*/
|
|
||||||
DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u",
|
|
||||||
(long) info->s->state.dellink, (uint) info->s->r_locks,
|
|
||||||
(uint) info->s->w_locks));
|
|
||||||
return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
|
|
||||||
(maria_concurrent_insert == 2 && info->s->r_locks &&
|
|
||||||
info->s->w_locks == 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** functions to read / write the state
|
** functions to read / write the state
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -389,7 +268,7 @@ int _ma_readinfo(register MARIA_HA *info __attribute__ ((unused)),
|
|||||||
}
|
}
|
||||||
if (check_keybuffer)
|
if (check_keybuffer)
|
||||||
VOID(_ma_test_if_changed(info));
|
VOID(_ma_test_if_changed(info));
|
||||||
info->invalidator=info->s->invalidator;
|
info->invalidator=share->invalidator;
|
||||||
}
|
}
|
||||||
else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
|
else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
|
||||||
{
|
{
|
||||||
|
@ -91,6 +91,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
|
|||||||
int save_errno;
|
int save_errno;
|
||||||
uint errpos;
|
uint errpos;
|
||||||
MARIA_HA info,*m_info;
|
MARIA_HA info,*m_info;
|
||||||
|
MARIA_STATUS_INFO *state_dummy;
|
||||||
my_bitmap_map *changed_fields_bitmap;
|
my_bitmap_map *changed_fields_bitmap;
|
||||||
DBUG_ENTER("maria_clone_internal");
|
DBUG_ENTER("maria_clone_internal");
|
||||||
|
|
||||||
@ -120,6 +121,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
|
|||||||
share->have_rtree ? 1024 : 0,
|
share->have_rtree ? 1024 : 0,
|
||||||
&changed_fields_bitmap,
|
&changed_fields_bitmap,
|
||||||
bitmap_buffer_size(share->base.fields),
|
bitmap_buffer_size(share->base.fields),
|
||||||
|
&state_dummy, sizeof(*state_dummy),
|
||||||
NullS))
|
NullS))
|
||||||
goto err;
|
goto err;
|
||||||
errpos= 6;
|
errpos= 6;
|
||||||
@ -176,9 +178,18 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
|
|||||||
maria_delay_key_write)
|
maria_delay_key_write)
|
||||||
share->delay_key_write=1;
|
share->delay_key_write=1;
|
||||||
|
|
||||||
info.state= &share->state.state; /* Change global values by default */
|
|
||||||
if (!share->base.born_transactional) /* For transactional ones ... */
|
if (!share->base.born_transactional) /* For transactional ones ... */
|
||||||
|
{
|
||||||
info.trn= &dummy_transaction_object; /* ... force crash if no trn given */
|
info.trn= &dummy_transaction_object; /* ... force crash if no trn given */
|
||||||
|
info.state= &share->state.state; /* Change global values by default */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.state= state_dummy;
|
||||||
|
*info.state= share->state.state; /* Initial values */
|
||||||
|
}
|
||||||
|
info.state_start= info.state; /* Initial values */
|
||||||
|
|
||||||
pthread_mutex_unlock(&share->intern_lock);
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
|
||||||
/* Allocate buffer for one record */
|
/* Allocate buffer for one record */
|
||||||
@ -759,7 +770,31 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||||||
_ma_setup_functions(share);
|
_ma_setup_functions(share);
|
||||||
if ((*share->once_init)(share, info.dfile.file))
|
if ((*share->once_init)(share, info.dfile.file))
|
||||||
goto err;
|
goto err;
|
||||||
|
if (share->now_transactional)
|
||||||
|
{
|
||||||
|
/* Setup initial state that is visible for all */
|
||||||
|
MARIA_STATE_HISTORY_CLOSED *history;
|
||||||
|
if ((history= (MARIA_STATE_HISTORY_CLOSED *)
|
||||||
|
hash_search(&maria_stored_state,
|
||||||
|
(uchar*) &share->state.create_rename_lsn, 0)))
|
||||||
|
{
|
||||||
|
/* Move history from hash to share */
|
||||||
|
share->state_history=
|
||||||
|
_ma_remove_not_visible_states(history->state_history, 0, 0);
|
||||||
|
history->state_history= 0;
|
||||||
|
(void) hash_delete(&maria_stored_state, (uchar*) history);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Table is not part of any active transaction; Create new history */
|
||||||
|
if (!(share->state_history= (MARIA_STATE_HISTORY *)
|
||||||
|
my_malloc(sizeof(*share->state_history), MYF(MY_WME))))
|
||||||
|
goto err;
|
||||||
|
share->state_history->trid= 0; /* Visibly by all */
|
||||||
|
share->state_history->state= share->state.state;
|
||||||
|
share->state_history->next= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
thr_lock_init(&share->lock);
|
thr_lock_init(&share->lock);
|
||||||
VOID(pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST));
|
VOID(pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST));
|
||||||
@ -774,22 +809,24 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||||||
}
|
}
|
||||||
else if (maria_concurrent_insert)
|
else if (maria_concurrent_insert)
|
||||||
{
|
{
|
||||||
share->concurrent_insert=
|
share->non_transactional_concurrent_insert=
|
||||||
((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
|
((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
|
||||||
HA_OPTION_COMPRESS_RECORD |
|
HA_OPTION_COMPRESS_RECORD |
|
||||||
HA_OPTION_TEMP_COMPRESS_RECORD)) ||
|
HA_OPTION_TEMP_COMPRESS_RECORD)) ||
|
||||||
(open_flags & HA_OPEN_TMP_TABLE) ||
|
(open_flags & HA_OPEN_TMP_TABLE) ||
|
||||||
(share->data_file_type == BLOCK_RECORD &&
|
share->data_file_type == BLOCK_RECORD ||
|
||||||
!share->now_transactional) ||
|
|
||||||
share->have_rtree) ? 0 : 1;
|
share->have_rtree) ? 0 : 1;
|
||||||
if (share->concurrent_insert)
|
if (share->non_transactional_concurrent_insert ||
|
||||||
|
(!share->temporary && share->now_transactional && !share->base.keys))
|
||||||
{
|
{
|
||||||
|
share->lock_key_trees= 1;
|
||||||
if (share->data_file_type == BLOCK_RECORD)
|
if (share->data_file_type == BLOCK_RECORD)
|
||||||
{
|
{
|
||||||
share->lock.get_status= _ma_block_get_status;
|
share->lock.get_status= _ma_block_get_status;
|
||||||
share->lock.update_status= _ma_block_update_status;
|
share->lock.update_status= _ma_block_update_status;
|
||||||
share->lock.check_status= _ma_block_check_status;
|
share->lock.check_status= _ma_block_check_status;
|
||||||
share->lock.allow_multiple_concurrent_insert= 1;
|
share->lock.allow_multiple_concurrent_insert= 1;
|
||||||
|
share->lock_restore_status= 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -798,6 +835,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||||||
share->lock.update_status= _ma_update_status;
|
share->lock.update_status= _ma_update_status;
|
||||||
share->lock.restore_status=_ma_restore_status;
|
share->lock.restore_status=_ma_restore_status;
|
||||||
share->lock.check_status= _ma_check_status;
|
share->lock.check_status= _ma_check_status;
|
||||||
|
share->lock_restore_status= _ma_restore_status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1705,17 +1743,21 @@ int maria_enable_indexes(MARIA_HA *info)
|
|||||||
{
|
{
|
||||||
int error= 0;
|
int error= 0;
|
||||||
MARIA_SHARE *share= info->s;
|
MARIA_SHARE *share= info->s;
|
||||||
|
DBUG_ENTER("maria_enable_indexes");
|
||||||
|
|
||||||
if ((share->state.state.data_file_length !=
|
if ((share->state.state.data_file_length !=
|
||||||
(share->data_file_type == BLOCK_RECORD ? share->block_size : 0)) ||
|
(share->data_file_type == BLOCK_RECORD ? share->block_size : 0)) ||
|
||||||
(share->state.state.key_file_length != share->base.keystart))
|
(share->state.state.key_file_length != share->base.keystart))
|
||||||
{
|
{
|
||||||
|
DBUG_PRINT("error", ("data_file_length: %lu key_file_length: %lu",
|
||||||
|
(ulong) share->state.state.data_file_length,
|
||||||
|
(ulong) share->state.state.key_file_length));
|
||||||
maria_print_error(info->s, HA_ERR_CRASHED);
|
maria_print_error(info->s, HA_ERR_CRASHED);
|
||||||
error= HA_ERR_CRASHED;
|
error= HA_ERR_CRASHED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
maria_set_all_keys_active(share->state.key_map, share->base.keys);
|
maria_set_all_keys_active(share->state.key_map, share->base.keys);
|
||||||
return error;
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,13 +101,13 @@ int _ma_write_keypage(register MARIA_HA *info,
|
|||||||
uint page_length, nod;
|
uint page_length, nod;
|
||||||
_ma_get_used_and_nod(share, buff, page_length, nod);
|
_ma_get_used_and_nod(share, buff, page_length, nod);
|
||||||
if (pos < share->base.keystart ||
|
if (pos < share->base.keystart ||
|
||||||
pos+block_size > info->state->key_file_length ||
|
pos+block_size > share->state.state.key_file_length ||
|
||||||
(pos & (maria_block_size-1)))
|
(pos & (maria_block_size-1)))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error",("Trying to write inside key status region: "
|
DBUG_PRINT("error",("Trying to write inside key status region: "
|
||||||
"key_start: %lu length: %lu page: %lu",
|
"key_start: %lu length: %lu page: %lu",
|
||||||
(long) share->base.keystart,
|
(long) share->base.keystart,
|
||||||
(long) info->state->key_file_length,
|
(long) share->state.state.key_file_length,
|
||||||
(long) pos));
|
(long) pos));
|
||||||
my_errno=EINVAL;
|
my_errno=EINVAL;
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
@ -299,14 +299,18 @@ my_off_t _ma_new(register MARIA_HA *info, int level,
|
|||||||
|
|
||||||
if (_ma_lock_key_del(info, 1))
|
if (_ma_lock_key_del(info, 1))
|
||||||
{
|
{
|
||||||
if (info->state->key_file_length >=
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
share->base.max_key_file_length - block_size)
|
pos= share->state.state.key_file_length;
|
||||||
|
if (pos >= share->base.max_key_file_length - block_size)
|
||||||
{
|
{
|
||||||
my_errno=HA_ERR_INDEX_FILE_FULL;
|
my_errno=HA_ERR_INDEX_FILE_FULL;
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
DBUG_RETURN(HA_OFFSET_ERROR);
|
DBUG_RETURN(HA_OFFSET_ERROR);
|
||||||
}
|
}
|
||||||
pos= info->state->key_file_length;
|
share->state.state.key_file_length+= block_size;
|
||||||
info->state->key_file_length+= block_size;
|
/* Following is for not transactional tables */
|
||||||
|
info->state->key_file_length= share->state.state.key_file_length;
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
(*page_link)->changed= 0;
|
(*page_link)->changed= 0;
|
||||||
(*page_link)->write_lock= PAGECACHE_LOCK_WRITE;
|
(*page_link)->write_lock= PAGECACHE_LOCK_WRITE;
|
||||||
}
|
}
|
||||||
@ -337,7 +341,7 @@ my_off_t _ma_new(register MARIA_HA *info, int level,
|
|||||||
(current_key_del != 0) &&
|
(current_key_del != 0) &&
|
||||||
((current_key_del == HA_OFFSET_ERROR) ||
|
((current_key_del == HA_OFFSET_ERROR) ||
|
||||||
(current_key_del <=
|
(current_key_del <=
|
||||||
(info->state->key_file_length - block_size))));
|
(share->state.state.key_file_length - block_size))));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
|
|||||||
key_range *max_key)
|
key_range *max_key)
|
||||||
{
|
{
|
||||||
ha_rows start_pos,end_pos,res;
|
ha_rows start_pos,end_pos,res;
|
||||||
|
MARIA_SHARE *share= info->s;
|
||||||
DBUG_ENTER("maria_records_in_range");
|
DBUG_ENTER("maria_records_in_range");
|
||||||
|
|
||||||
if ((inx = _ma_check_index(info,inx)) < 0)
|
if ((inx = _ma_check_index(info,inx)) < 0)
|
||||||
@ -56,10 +57,10 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
|
|||||||
if (fast_ma_readinfo(info))
|
if (fast_ma_readinfo(info))
|
||||||
DBUG_RETURN(HA_POS_ERROR);
|
DBUG_RETURN(HA_POS_ERROR);
|
||||||
info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
|
||||||
if (info->s->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_rdlock(&info->s->key_root_lock[inx]);
|
rw_rdlock(&share->key_root_lock[inx]);
|
||||||
|
|
||||||
switch(info->s->keyinfo[inx].key_alg){
|
switch(share->keyinfo[inx].key_alg){
|
||||||
#ifdef HAVE_RTREE_KEYS
|
#ifdef HAVE_RTREE_KEYS
|
||||||
case HA_KEY_ALG_RTREE:
|
case HA_KEY_ALG_RTREE:
|
||||||
{
|
{
|
||||||
@ -81,7 +82,7 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
|
|||||||
res= HA_POS_ERROR;
|
res= HA_POS_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
key_buff= info->lastkey+info->s->base.max_key_length;
|
key_buff= info->lastkey+share->base.max_key_length;
|
||||||
start_key_len= _ma_pack_key(info,inx, key_buff,
|
start_key_len= _ma_pack_key(info,inx, key_buff,
|
||||||
min_key->key, min_key->keypart_map,
|
min_key->key, min_key->keypart_map,
|
||||||
(HA_KEYSEG**) 0);
|
(HA_KEYSEG**) 0);
|
||||||
@ -107,8 +108,8 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
|
|||||||
res=HA_POS_ERROR;
|
res=HA_POS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->s->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_unlock(&info->s->key_root_lock[inx]);
|
rw_unlock(&share->key_root_lock[inx]);
|
||||||
fast_ma_writeinfo(info);
|
fast_ma_writeinfo(info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2726,6 +2726,13 @@ static void prepare_table_for_close(MARIA_HA *info, TRANSLOG_ADDRESS horizon)
|
|||||||
share->state.is_of_horizon= horizon;
|
share->state.is_of_horizon= horizon;
|
||||||
_ma_state_info_write_sub(share->kfile.file, &share->state, 1);
|
_ma_state_info_write_sub(share->kfile.file, &share->state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ensure that info->state is up to date as
|
||||||
|
_ma_renable_logging_for_table() is depending on this
|
||||||
|
*/
|
||||||
|
*info->state= info->s->state.state;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This leaves PAGECACHE_PLAIN_PAGE pages into the cache, while the table is
|
This leaves PAGECACHE_PLAIN_PAGE pages into the cache, while the table is
|
||||||
going to switch back to transactional. So the table will be a mix of
|
going to switch back to transactional. So the table will be a mix of
|
||||||
@ -3226,6 +3233,13 @@ my_bool _ma_reenable_logging_for_table(MARIA_HA *info, my_bool flush_pages)
|
|||||||
if ((share->now_transactional= share->base.born_transactional))
|
if ((share->now_transactional= share->base.born_transactional))
|
||||||
{
|
{
|
||||||
share->page_type= PAGECACHE_LSN_PAGE;
|
share->page_type= PAGECACHE_LSN_PAGE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy state information that where updated while the table was used
|
||||||
|
in not transactional mode
|
||||||
|
*/
|
||||||
|
_ma_copy_nontrans_state_information(info);
|
||||||
|
|
||||||
if (flush_pages)
|
if (flush_pages)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -69,7 +69,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
|
|||||||
|
|
||||||
if (fast_ma_readinfo(info))
|
if (fast_ma_readinfo(info))
|
||||||
goto err;
|
goto err;
|
||||||
if (share->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_rdlock(&share->key_root_lock[inx]);
|
rw_rdlock(&share->key_root_lock[inx]);
|
||||||
|
|
||||||
nextflag=maria_read_vec[search_flag];
|
nextflag=maria_read_vec[search_flag];
|
||||||
@ -93,7 +93,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
|
|||||||
if (!_ma_search(info, keyinfo, key_buff, use_key_length,
|
if (!_ma_search(info, keyinfo, key_buff, use_key_length,
|
||||||
maria_read_vec[search_flag],
|
maria_read_vec[search_flag],
|
||||||
info->s->state.key_root[inx]) &&
|
info->s->state.key_root[inx]) &&
|
||||||
share->concurrent_insert)
|
share->non_transactional_concurrent_insert)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Found a key, but it might not be usable. We cannot use rows that
|
Found a key, but it might not be usable. We cannot use rows that
|
||||||
@ -156,7 +156,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (share->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_unlock(&share->key_root_lock[inx]);
|
rw_unlock(&share->key_root_lock[inx]);
|
||||||
|
|
||||||
if (info->cur_row.lastpos == HA_OFFSET_ERROR)
|
if (info->cur_row.lastpos == HA_OFFSET_ERROR)
|
||||||
|
@ -39,7 +39,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
|
|
||||||
if (fast_ma_readinfo(info))
|
if (fast_ma_readinfo(info))
|
||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_rdlock(&info->s->key_root_lock[inx]);
|
rw_rdlock(&info->s->key_root_lock[inx]);
|
||||||
changed= _ma_test_if_changed(info);
|
changed= _ma_test_if_changed(info);
|
||||||
if (!flag)
|
if (!flag)
|
||||||
@ -82,7 +82,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->non_transactional_concurrent_insert)
|
||||||
{
|
{
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
|
@ -39,11 +39,10 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
|
|||||||
if (fast_ma_readinfo(info))
|
if (fast_ma_readinfo(info))
|
||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
|
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_rdlock(&info->s->key_root_lock[inx]);
|
rw_rdlock(&info->s->key_root_lock[inx]);
|
||||||
|
|
||||||
switch (keyinfo->key_alg)
|
switch (keyinfo->key_alg) {
|
||||||
{
|
|
||||||
#ifdef HAVE_RTREE_KEYS
|
#ifdef HAVE_RTREE_KEYS
|
||||||
case HA_KEY_ALG_RTREE:
|
case HA_KEY_ALG_RTREE:
|
||||||
if ((error=maria_rtree_find_next(info,inx,
|
if ((error=maria_rtree_find_next(info,inx,
|
||||||
@ -79,11 +78,12 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Skip rows that are inserted by other threads since we got a lock */
|
/* Skip rows that are inserted by other threads since we got a lock */
|
||||||
if (info->cur_row.lastpos < info->state->data_file_length)
|
if (!info->s->non_transactional_concurrent_insert ||
|
||||||
|
info->cur_row.lastpos < info->state->data_file_length)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_unlock(&info->s->key_root_lock[inx]);
|
rw_unlock(&info->s->key_root_lock[inx]);
|
||||||
/* Don't clear if database-changed */
|
/* Don't clear if database-changed */
|
||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
|
@ -39,7 +39,7 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
if (fast_ma_readinfo(info))
|
if (fast_ma_readinfo(info))
|
||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
changed= _ma_test_if_changed(info);
|
changed= _ma_test_if_changed(info);
|
||||||
if (share->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_rdlock(&share->key_root_lock[inx]);
|
rw_rdlock(&share->key_root_lock[inx]);
|
||||||
if (!flag)
|
if (!flag)
|
||||||
error= _ma_search_last(info, share->keyinfo+inx,
|
error= _ma_search_last(info, share->keyinfo+inx,
|
||||||
@ -52,7 +52,7 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
error= _ma_search(info,share->keyinfo+inx,info->lastkey,
|
error= _ma_search(info,share->keyinfo+inx,info->lastkey,
|
||||||
USE_WHOLE_KEY, flag, share->state.key_root[inx]);
|
USE_WHOLE_KEY, flag, share->state.key_root[inx]);
|
||||||
|
|
||||||
if (share->concurrent_insert)
|
if (share->non_transactional_concurrent_insert)
|
||||||
{
|
{
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
@ -66,8 +66,9 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rw_unlock(&share->key_root_lock[inx]);
|
|
||||||
}
|
}
|
||||||
|
if (share->lock_key_trees)
|
||||||
|
rw_unlock(&share->key_root_lock[inx]);
|
||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
info->update|= HA_STATE_PREV_FOUND;
|
info->update|= HA_STATE_PREV_FOUND;
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -54,12 +54,12 @@ int maria_rsame(MARIA_HA *info, uchar *record, int inx)
|
|||||||
info->lastinx=inx;
|
info->lastinx=inx;
|
||||||
info->lastkey_length= _ma_make_key(info,(uint) inx,info->lastkey,record,
|
info->lastkey_length= _ma_make_key(info,(uint) inx,info->lastkey,record,
|
||||||
info->cur_row.lastpos);
|
info->cur_row.lastpos);
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_rdlock(&info->s->key_root_lock[inx]);
|
rw_rdlock(&info->s->key_root_lock[inx]);
|
||||||
VOID(_ma_search(info,info->s->keyinfo+inx,info->lastkey, USE_WHOLE_KEY,
|
VOID(_ma_search(info,info->s->keyinfo+inx,info->lastkey, USE_WHOLE_KEY,
|
||||||
SEARCH_SAME,
|
SEARCH_SAME,
|
||||||
info->s->state.key_root[inx]));
|
info->s->state.key_root[inx]));
|
||||||
if (info->s->concurrent_insert)
|
if (info->s->lock_key_trees)
|
||||||
rw_unlock(&info->s->key_root_lock[inx]);
|
rw_unlock(&info->s->key_root_lock[inx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,9 +532,10 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
|
|||||||
}
|
}
|
||||||
if (!got_error && param->testflag & T_STATISTICS)
|
if (!got_error && param->testflag & T_STATISTICS)
|
||||||
maria_update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique,
|
maria_update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique,
|
||||||
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
|
param->stats_method ==
|
||||||
sinfo->notnull: NULL,
|
MI_STATS_METHOD_IGNORE_NULLS ?
|
||||||
(ulonglong) info->state->records);
|
sinfo->notnull : NULL,
|
||||||
|
(ulonglong) share->state.state.records);
|
||||||
}
|
}
|
||||||
my_free((uchar*) sinfo->sort_keys,MYF(0));
|
my_free((uchar*) sinfo->sort_keys,MYF(0));
|
||||||
my_free(sinfo->rec_buff, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(sinfo->rec_buff, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
|
478
storage/maria/ma_state.c
Normal file
478
storage/maria/ma_state.c
Normal file
@ -0,0 +1,478 @@
|
|||||||
|
/* Copyright (C) 2008 Sun AB and Michael Widenius
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Functions to maintain live statistics for Maria transactional tables
|
||||||
|
and versioning for not transactional tables
|
||||||
|
|
||||||
|
See WL#3138; Maria - fast "SELECT COUNT(*) FROM t;" and "CHECKSUM TABLE t"
|
||||||
|
for details about live number of rows and live checksums
|
||||||
|
|
||||||
|
TODO
|
||||||
|
- Allocate MA_USED_TABLES and MA_HISTORY_STATE from a global pool (to
|
||||||
|
avoid calls to malloc()
|
||||||
|
- In trnamn_end_trans_hook(), don't call _ma_remove_not_visible_states()
|
||||||
|
every time. One could for example call it if there has been more than
|
||||||
|
10 ended transactions since last time it was called.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <maria_def.h>
|
||||||
|
#include "trnman.h"
|
||||||
|
#include <ma_blockrec.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Setup initial start-of-transaction state for a table
|
||||||
|
|
||||||
|
@fn _ma_setup_live_state
|
||||||
|
@param info Maria handler
|
||||||
|
|
||||||
|
@notes
|
||||||
|
This function ensures that trn->used_tables contains a list of
|
||||||
|
start and live states for tables that are part of the transaction
|
||||||
|
and that info->state points to the current live state for the table.
|
||||||
|
|
||||||
|
@TODO
|
||||||
|
Change trn->table_list to a hash and share->state_history to a binary tree
|
||||||
|
|
||||||
|
@return
|
||||||
|
@retval 0 ok
|
||||||
|
@retval 1 error (out of memory)
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool _ma_setup_live_state(MARIA_HA *info)
|
||||||
|
{
|
||||||
|
TRN *trn= info->trn;
|
||||||
|
MARIA_SHARE *share= info->s;
|
||||||
|
MARIA_USED_TABLES *tables;
|
||||||
|
MARIA_STATE_HISTORY *history;
|
||||||
|
DBUG_ENTER("_ma_setup_live_state");
|
||||||
|
|
||||||
|
for (tables= (MARIA_USED_TABLES*) info->trn->used_tables;
|
||||||
|
tables;
|
||||||
|
tables= tables->next)
|
||||||
|
{
|
||||||
|
if (tables->share == share)
|
||||||
|
{
|
||||||
|
/* Table is already used by transaction */
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Table was not used before, create new table state entry */
|
||||||
|
if (!(tables= (MARIA_USED_TABLES*) my_malloc(sizeof(*tables),
|
||||||
|
MYF(MY_WME | MY_ZEROFILL))))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
tables->next= trn->used_tables;
|
||||||
|
trn->used_tables= tables;
|
||||||
|
tables->share= share;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
|
share->in_trans++;
|
||||||
|
history= share->state_history;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We must keep share locked to ensure that we don't access a history
|
||||||
|
link that is deleted by concurrently running checkpoint.
|
||||||
|
|
||||||
|
It's enough to compare trids here (instead of calling
|
||||||
|
tranman_can_read_from) as history->trid is a commit_trid
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("QQ", ("trn->trid: 0x%lu", (long) trn->trid));
|
||||||
|
while (trn->trid < history->trid)
|
||||||
|
history= history->next;
|
||||||
|
DBUG_PRINT("QQ", ("his->trid: 0x%lu", (long) history->trid));
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
/* The current item can't be deleted as it's the first one visible for us */
|
||||||
|
tables->state_start= tables->state_current= history->state;
|
||||||
|
DBUG_PRINT("info", ("records: %ld", (ulong) tables->state_start.records));
|
||||||
|
|
||||||
|
end:
|
||||||
|
info->state_start= &tables->state_start;
|
||||||
|
info->state= &tables->state_current;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Remove states that are not visible by anyone
|
||||||
|
|
||||||
|
@fn _ma_remove_not_visible_states()
|
||||||
|
@param org_history List to history
|
||||||
|
@param all 1 if we should delete the first state if it's
|
||||||
|
visible for all. For the moment this is only used
|
||||||
|
on close() of table.
|
||||||
|
|
||||||
|
@notes
|
||||||
|
The assumption is that items in the history list is ordered by
|
||||||
|
commit_trid.
|
||||||
|
|
||||||
|
A state is not visible anymore if there is no new transaction
|
||||||
|
that has been started between the commit_trid's of two states
|
||||||
|
|
||||||
|
As long as some states exists, we keep the newest = (last commit)
|
||||||
|
state as first state in the history. This is to allow us to just move
|
||||||
|
the history from the global list to the share when we open the table.
|
||||||
|
|
||||||
|
@return
|
||||||
|
@retval Pointer to new history list
|
||||||
|
*/
|
||||||
|
|
||||||
|
MARIA_STATE_HISTORY
|
||||||
|
*_ma_remove_not_visible_states(MARIA_STATE_HISTORY *org_history,
|
||||||
|
my_bool all,
|
||||||
|
my_bool trnman_is_locked)
|
||||||
|
{
|
||||||
|
TrID last_trid;
|
||||||
|
MARIA_STATE_HISTORY *history, **parent, *next;
|
||||||
|
DBUG_ENTER("_ma_remove_not_visible_states");
|
||||||
|
|
||||||
|
if (!org_history)
|
||||||
|
DBUG_RETURN(0); /* Not versioned table */
|
||||||
|
|
||||||
|
last_trid= org_history->trid;
|
||||||
|
parent= &org_history->next;
|
||||||
|
for (history= org_history->next; history; history= next)
|
||||||
|
{
|
||||||
|
next= history->next;
|
||||||
|
if (!trnman_exists_active_transactions(history->trid, last_trid,
|
||||||
|
trnman_is_locked))
|
||||||
|
{
|
||||||
|
my_free(history, MYF(0));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*parent= history;
|
||||||
|
parent= &history->next;
|
||||||
|
last_trid= history->trid;
|
||||||
|
}
|
||||||
|
*parent= 0;
|
||||||
|
|
||||||
|
if (all && parent == &org_history->next)
|
||||||
|
{
|
||||||
|
/* There is only one state left. Delete this if it's visible for all */
|
||||||
|
if (last_trid < trnman_get_min_trid())
|
||||||
|
{
|
||||||
|
my_free(org_history, MYF(0));
|
||||||
|
org_history= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(org_history);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Free state history information from share->history and reset information
|
||||||
|
to current state.
|
||||||
|
|
||||||
|
@notes
|
||||||
|
Used after repair as then all rows are visible for everyone
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _ma_reset_state(MARIA_HA *info)
|
||||||
|
{
|
||||||
|
MARIA_SHARE *share= info->s;
|
||||||
|
MARIA_STATE_HISTORY *history= share->state_history;
|
||||||
|
|
||||||
|
if (history)
|
||||||
|
{
|
||||||
|
MARIA_STATE_HISTORY *next;
|
||||||
|
|
||||||
|
/* Set the current history to current state */
|
||||||
|
share->state_history->state= share->state.state;
|
||||||
|
for (history= history->next ; history ; history= next)
|
||||||
|
{
|
||||||
|
next= history->next;
|
||||||
|
my_free(history, MYF(0));
|
||||||
|
}
|
||||||
|
share->state_history->next= 0;
|
||||||
|
share->state_history->trid= 0; /* Visibile for all */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
The following functions are called by thr_lock() in threaded applications
|
||||||
|
for not transactional tables
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a copy of the current status for the table
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
_ma_get_status()
|
||||||
|
param Pointer to Myisam handler
|
||||||
|
concurrent_insert Set to 1 if we are going to do concurrent inserts
|
||||||
|
(THR_WRITE_CONCURRENT_INSERT was used)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _ma_get_status(void* param, my_bool concurrent_insert)
|
||||||
|
{
|
||||||
|
MARIA_HA *info=(MARIA_HA*) param;
|
||||||
|
DBUG_ENTER("_ma_get_status");
|
||||||
|
DBUG_PRINT("info",("key_file: %ld data_file: %ld concurrent_insert: %d",
|
||||||
|
(long) info->s->state.state.key_file_length,
|
||||||
|
(long) info->s->state.state.data_file_length,
|
||||||
|
concurrent_insert));
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
if (info->state->key_file_length > info->s->state.state.key_file_length ||
|
||||||
|
info->state->data_file_length > info->s->state.state.data_file_length)
|
||||||
|
DBUG_PRINT("warning",("old info: key_file: %ld data_file: %ld",
|
||||||
|
(long) info->state->key_file_length,
|
||||||
|
(long) info->state->data_file_length));
|
||||||
|
#endif
|
||||||
|
info->state_save= info->s->state.state;
|
||||||
|
info->state= &info->state_save;
|
||||||
|
info->append_insert_at_end= concurrent_insert;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _ma_update_status(void* param)
|
||||||
|
{
|
||||||
|
MARIA_HA *info=(MARIA_HA*) param;
|
||||||
|
/*
|
||||||
|
Because someone may have closed the table we point at, we only
|
||||||
|
update the state if its our own state. This isn't a problem as
|
||||||
|
we are always pointing at our own lock or at a read lock.
|
||||||
|
(This is enforced by thr_multi_lock.c)
|
||||||
|
*/
|
||||||
|
if (info->state == &info->state_save)
|
||||||
|
{
|
||||||
|
MARIA_SHARE *share= info->s;
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
DBUG_PRINT("info",("updating status: key_file: %ld data_file: %ld",
|
||||||
|
(long) info->state->key_file_length,
|
||||||
|
(long) info->state->data_file_length));
|
||||||
|
if (info->state->key_file_length < share->state.state.key_file_length ||
|
||||||
|
info->state->data_file_length < share->state.state.data_file_length)
|
||||||
|
DBUG_PRINT("warning",("old info: key_file: %ld data_file: %ld",
|
||||||
|
(long) share->state.state.key_file_length,
|
||||||
|
(long) share->state.state.data_file_length));
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
we are going to modify the state without lock's log, this would break
|
||||||
|
recovery if done with a transactional table.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(!info->s->base.born_transactional);
|
||||||
|
share->state.state= *info->state;
|
||||||
|
info->state= &share->state.state;
|
||||||
|
}
|
||||||
|
info->append_insert_at_end= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _ma_restore_status(void *param)
|
||||||
|
{
|
||||||
|
MARIA_HA *info= (MARIA_HA*) param;
|
||||||
|
info->state= &info->s->state.state;
|
||||||
|
info->append_insert_at_end= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _ma_copy_status(void* to, void *from)
|
||||||
|
{
|
||||||
|
((MARIA_HA*) to)->state= &((MARIA_HA*) from)->state_save;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Check if should allow concurrent inserts
|
||||||
|
|
||||||
|
@implementation
|
||||||
|
Allow concurrent inserts if we don't have a hole in the table or
|
||||||
|
if there is no active write lock and there is active read locks and
|
||||||
|
maria_concurrent_insert == 2. In this last case the new
|
||||||
|
row('s) are inserted at end of file instead of filling up the hole.
|
||||||
|
|
||||||
|
The last case is to allow one to inserts into a heavily read-used table
|
||||||
|
even if there is holes.
|
||||||
|
|
||||||
|
@notes
|
||||||
|
If there is a an rtree indexes in the table, concurrent inserts are
|
||||||
|
disabled in maria_open()
|
||||||
|
|
||||||
|
@return
|
||||||
|
@retval 0 ok to use concurrent inserts
|
||||||
|
@retval 1 not ok
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool _ma_check_status(void *param)
|
||||||
|
{
|
||||||
|
MARIA_HA *info=(MARIA_HA*) param;
|
||||||
|
/*
|
||||||
|
The test for w_locks == 1 is here because this thread has already done an
|
||||||
|
external lock (in other words: w_locks == 1 means no other threads has
|
||||||
|
a write lock)
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u",
|
||||||
|
(long) info->s->state.dellink, (uint) info->s->r_locks,
|
||||||
|
(uint) info->s->w_locks));
|
||||||
|
return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
|
||||||
|
(maria_concurrent_insert == 2 && info->s->r_locks &&
|
||||||
|
info->s->w_locks == 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief write hook at end of trans to store status for all used table
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
|
||||||
|
my_bool active_transactions)
|
||||||
|
{
|
||||||
|
my_bool error= 0;
|
||||||
|
MARIA_USED_TABLES *tables, *next;
|
||||||
|
|
||||||
|
for (tables= (MARIA_USED_TABLES*) trn->used_tables;
|
||||||
|
tables;
|
||||||
|
tables= next)
|
||||||
|
{
|
||||||
|
next= tables->next;
|
||||||
|
if (commit)
|
||||||
|
{
|
||||||
|
MARIA_SHARE *share= tables->share;
|
||||||
|
MARIA_STATE_HISTORY *history;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
|
if (active_transactions &&
|
||||||
|
trnman_exists_active_transactions(share->state_history->trid,
|
||||||
|
trn->commit_trid, 1))
|
||||||
|
{
|
||||||
|
if (!(history= my_malloc(sizeof(*history), MYF(MY_WME))))
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
my_free(tables, MYF(0));
|
||||||
|
error= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
history->state= share->state_history->state;
|
||||||
|
history->next= share->state_history;
|
||||||
|
share->state_history= history;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Previous history can't be seen by anyone, reuse old memory */
|
||||||
|
history= share->state_history;
|
||||||
|
}
|
||||||
|
|
||||||
|
history->state.records+= (tables->state_current.records -
|
||||||
|
tables->state_start.records);
|
||||||
|
history->state.checksum+= (tables->state_current.checksum -
|
||||||
|
tables->state_start.checksum);
|
||||||
|
history->trid= trn->commit_trid;
|
||||||
|
|
||||||
|
if (history->next)
|
||||||
|
{
|
||||||
|
/* Remove not visible states */
|
||||||
|
share->state_history= _ma_remove_not_visible_states(history, 0, 1);
|
||||||
|
}
|
||||||
|
share->in_trans--;
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
}
|
||||||
|
my_free(tables, MYF(0));
|
||||||
|
}
|
||||||
|
trn->used_tables= 0;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
The following functions are called by thr_lock() in threaded applications
|
||||||
|
for transactional tables.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a copy of the current status for the table
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
_ma_get_status()
|
||||||
|
param Pointer to Myisam handler
|
||||||
|
concurrent_insert Set to 1 if we are going to do concurrent inserts
|
||||||
|
(THR_WRITE_CONCURRENT_INSERT was used)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _ma_block_get_status(void* param, my_bool concurrent_insert)
|
||||||
|
{
|
||||||
|
MARIA_HA *info=(MARIA_HA*) param;
|
||||||
|
DBUG_ENTER("_ma_block_get_status");
|
||||||
|
DBUG_PRINT("info", ("concurrent_insert %d", concurrent_insert));
|
||||||
|
info->row_base_length= info->s->base_length;
|
||||||
|
info->row_flag= info->s->base.default_row_flag;
|
||||||
|
if (concurrent_insert)
|
||||||
|
{
|
||||||
|
info->row_flag|= ROW_FLAG_TRANSID;
|
||||||
|
info->row_base_length+= TRANSID_SIZE;
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _ma_block_update_status(void *param __attribute__((unused)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ma_block_restore_status(void *param __attribute__((unused)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if should allow concurrent inserts
|
||||||
|
|
||||||
|
@return
|
||||||
|
@retval 0 ok to use concurrent inserts
|
||||||
|
@retval 1 not ok
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool _ma_block_check_status(void *param __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return (my_bool) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable/disable versioning
|
||||||
|
*/
|
||||||
|
|
||||||
|
void maria_versioning(MARIA_HA *info, my_bool versioning)
|
||||||
|
{
|
||||||
|
/* For now, this is a hack */
|
||||||
|
_ma_block_get_status((void*) info, versioning);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update data_file_length to new length
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
Only used by block records
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _ma_set_share_data_file_length(MARIA_SHARE *share, ulonglong new_length)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&share->intern_lock);
|
||||||
|
if (share->state.state.data_file_length < new_length)
|
||||||
|
share->state.state.data_file_length= new_length;
|
||||||
|
pthread_mutex_unlock(&share->intern_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Copy state information that where updated while the table was used
|
||||||
|
in not transactional mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
void _ma_copy_nontrans_state_information(MARIA_HA *info)
|
||||||
|
{
|
||||||
|
info->s->state.state.records= info->state->records;
|
||||||
|
info->s->state.state.checksum= info->state->checksum;
|
||||||
|
}
|
75
storage/maria/ma_state.h
Normal file
75
storage/maria/ma_state.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* Copyright (C) 2008 Sun AB & Michael Widenius
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
/* Struct to store tables in use by one transaction */
|
||||||
|
|
||||||
|
typedef struct st_maria_status_info
|
||||||
|
{
|
||||||
|
ha_rows records; /* Rows in table */
|
||||||
|
ha_rows del; /* Removed rows */
|
||||||
|
my_off_t empty; /* lost space in datafile */
|
||||||
|
my_off_t key_empty; /* lost space in indexfile */
|
||||||
|
my_off_t key_file_length;
|
||||||
|
my_off_t data_file_length;
|
||||||
|
ha_checksum checksum;
|
||||||
|
} MARIA_STATUS_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct st_used_tables {
|
||||||
|
struct st_used_tables *next;
|
||||||
|
struct st_maria_share *share;
|
||||||
|
MARIA_STATUS_INFO state_current;
|
||||||
|
MARIA_STATUS_INFO state_start;
|
||||||
|
} MARIA_USED_TABLES;
|
||||||
|
|
||||||
|
|
||||||
|
/* Struct to store commit state at different times */
|
||||||
|
|
||||||
|
typedef struct st_state_history {
|
||||||
|
struct st_state_history *next;
|
||||||
|
TrID trid;
|
||||||
|
MARIA_STATUS_INFO state;
|
||||||
|
} MARIA_STATE_HISTORY;
|
||||||
|
|
||||||
|
|
||||||
|
/* struct to remember history for closed tables */
|
||||||
|
|
||||||
|
typedef struct st_state_history_closed {
|
||||||
|
LSN create_rename_lsn;
|
||||||
|
MARIA_STATE_HISTORY *state_history;
|
||||||
|
} MARIA_STATE_HISTORY_CLOSED;
|
||||||
|
|
||||||
|
|
||||||
|
my_bool _ma_setup_live_state(MARIA_HA *info);
|
||||||
|
MARIA_STATE_HISTORY *_ma_remove_not_visible_states(MARIA_STATE_HISTORY
|
||||||
|
*org_history,
|
||||||
|
my_bool all,
|
||||||
|
my_bool trman_is_locked);
|
||||||
|
void _ma_reset_state(MARIA_HA *info);
|
||||||
|
void _ma_get_status(void* param, my_bool concurrent_insert);
|
||||||
|
void _ma_update_status(void* param);
|
||||||
|
void _ma_restore_status(void *param);
|
||||||
|
void _ma_copy_status(void* to, void *from);
|
||||||
|
my_bool _ma_check_status(void *param);
|
||||||
|
void _ma_block_get_status(void* param, my_bool concurrent_insert);
|
||||||
|
void _ma_block_update_status(void *param);
|
||||||
|
void _ma_block_restore_status(void *param);
|
||||||
|
my_bool _ma_block_check_status(void *param);
|
||||||
|
void maria_versioning(MARIA_HA *info, my_bool versioning);
|
||||||
|
void _ma_set_share_data_file_length(struct st_maria_share *share,
|
||||||
|
ulonglong new_length);
|
||||||
|
void _ma_copy_nontrans_state_information(MARIA_HA *info);
|
||||||
|
my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
|
||||||
|
my_bool active_transactions);
|
@ -52,6 +52,7 @@ PAGECACHE maria_log_pagecache_var;
|
|||||||
PAGECACHE *maria_log_pagecache= &maria_log_pagecache_var;
|
PAGECACHE *maria_log_pagecache= &maria_log_pagecache_var;
|
||||||
MY_TMPDIR *maria_tmpdir; /* Tempdir for redo */
|
MY_TMPDIR *maria_tmpdir; /* Tempdir for redo */
|
||||||
char *maria_data_root;
|
char *maria_data_root;
|
||||||
|
HASH maria_stored_state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief when transactionality does not matter we can use this transaction
|
@brief when transactionality does not matter we can use this transaction
|
||||||
|
@ -42,7 +42,7 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
|
|||||||
{
|
{
|
||||||
DBUG_RETURN(my_errno=EACCES);
|
DBUG_RETURN(my_errno=EACCES);
|
||||||
}
|
}
|
||||||
if (info->state->key_file_length >= share->base.margin_key_file_length)
|
if (share->state.state.key_file_length >= share->base.margin_key_file_length)
|
||||||
{
|
{
|
||||||
DBUG_RETURN(my_errno=HA_ERR_INDEX_FILE_FULL);
|
DBUG_RETURN(my_errno=HA_ERR_INDEX_FILE_FULL);
|
||||||
}
|
}
|
||||||
@ -144,24 +144,12 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
|
|||||||
*/
|
*/
|
||||||
info->cur_row.checksum= (*share->calc_checksum)(info, newrec);
|
info->cur_row.checksum= (*share->calc_checksum)(info, newrec);
|
||||||
info->new_row.checksum= (*share->calc_checksum)(info, oldrec);
|
info->new_row.checksum= (*share->calc_checksum)(info, oldrec);
|
||||||
if (!share->now_transactional)
|
info->state->checksum+= info->cur_row.checksum - info->new_row.checksum;
|
||||||
info->state->checksum+= info->cur_row.checksum - info->new_row.checksum;
|
|
||||||
}
|
}
|
||||||
{
|
|
||||||
/*
|
|
||||||
Don't update index file if data file is not extended and no status
|
|
||||||
information changed
|
|
||||||
*/
|
|
||||||
MARIA_STATUS_INFO state;
|
|
||||||
ha_rows org_split;
|
|
||||||
my_off_t org_delete_link;
|
|
||||||
|
|
||||||
memcpy((char*) &state, (char*) info->state, sizeof(state));
|
if ((*share->update_record)(info, pos, oldrec, newrec))
|
||||||
org_split= share->state.split;
|
goto err;
|
||||||
org_delete_link= share->state.dellink;
|
|
||||||
if ((*share->update_record)(info, pos, oldrec, newrec))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (auto_key_changed & !share->now_transactional)
|
if (auto_key_changed & !share->now_transactional)
|
||||||
{
|
{
|
||||||
const HA_KEYSEG *keyseg= share->keyinfo[share->base.auto_key-1].seg;
|
const HA_KEYSEG *keyseg= share->keyinfo[share->base.auto_key-1].seg;
|
||||||
@ -171,8 +159,7 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We can't yet have HA_STATE_AKTIV here, as block_record dosn't support
|
We can't yet have HA_STATE_AKTIV here, as block_record dosn't support it
|
||||||
it
|
|
||||||
*/
|
*/
|
||||||
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed);
|
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed);
|
||||||
share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
|
share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
|
||||||
|
@ -70,6 +70,10 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page, uchar *buff,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
@brief Default handler for returing position to new row
|
@brief Default handler for returing position to new row
|
||||||
|
|
||||||
|
@note
|
||||||
|
This is only called for non transactional tables and not for block format
|
||||||
|
which is why we use info->state here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MARIA_RECORD_POS _ma_write_init_default(MARIA_HA *info,
|
MARIA_RECORD_POS _ma_write_init_default(MARIA_HA *info,
|
||||||
@ -97,7 +101,7 @@ int maria_write(MARIA_HA *info, uchar *record)
|
|||||||
int save_errno;
|
int save_errno;
|
||||||
MARIA_RECORD_POS filepos;
|
MARIA_RECORD_POS filepos;
|
||||||
uchar *buff;
|
uchar *buff;
|
||||||
my_bool lock_tree= share->concurrent_insert;
|
my_bool lock_tree= share->lock_key_trees;
|
||||||
my_bool fatal_error;
|
my_bool fatal_error;
|
||||||
DBUG_ENTER("maria_write");
|
DBUG_ENTER("maria_write");
|
||||||
DBUG_PRINT("enter",("index_file: %d data_file: %d",
|
DBUG_PRINT("enter",("index_file: %d data_file: %d",
|
||||||
@ -116,12 +120,12 @@ int maria_write(MARIA_HA *info, uchar *record)
|
|||||||
|
|
||||||
if (share->base.reloc == (ha_rows) 1 &&
|
if (share->base.reloc == (ha_rows) 1 &&
|
||||||
share->base.records == (ha_rows) 1 &&
|
share->base.records == (ha_rows) 1 &&
|
||||||
info->state->records == (ha_rows) 1)
|
share->state.state.records == (ha_rows) 1)
|
||||||
{ /* System file */
|
{ /* System file */
|
||||||
my_errno=HA_ERR_RECORD_FILE_FULL;
|
my_errno=HA_ERR_RECORD_FILE_FULL;
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
if (info->state->key_file_length >= share->base.margin_key_file_length)
|
if (share->state.state.key_file_length >= share->base.margin_key_file_length)
|
||||||
{
|
{
|
||||||
my_errno=HA_ERR_INDEX_FILE_FULL;
|
my_errno=HA_ERR_INDEX_FILE_FULL;
|
||||||
goto err2;
|
goto err2;
|
||||||
@ -204,8 +208,7 @@ int maria_write(MARIA_HA *info, uchar *record)
|
|||||||
{
|
{
|
||||||
if ((*share->write_record)(info,record))
|
if ((*share->write_record)(info,record))
|
||||||
goto err;
|
goto err;
|
||||||
if (!share->now_transactional)
|
info->state->checksum+= info->cur_row.checksum;
|
||||||
info->state->checksum+= info->cur_row.checksum;
|
|
||||||
}
|
}
|
||||||
if (!share->now_transactional)
|
if (!share->now_transactional)
|
||||||
{
|
{
|
||||||
@ -216,8 +219,8 @@ int maria_write(MARIA_HA *info, uchar *record)
|
|||||||
set_if_bigger(share->state.auto_increment,
|
set_if_bigger(share->state.auto_increment,
|
||||||
ma_retrieve_auto_increment(key, keyseg->type));
|
ma_retrieve_auto_increment(key, keyseg->type));
|
||||||
}
|
}
|
||||||
info->state->records++;
|
|
||||||
}
|
}
|
||||||
|
info->state->records++;
|
||||||
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
|
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
|
||||||
HA_STATE_ROW_CHANGED);
|
HA_STATE_ROW_CHANGED);
|
||||||
share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
|
share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
|
||||||
@ -578,7 +581,7 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
|||||||
if (flag == 0)
|
if (flag == 0)
|
||||||
{
|
{
|
||||||
uint tmp_key_length;
|
uint tmp_key_length;
|
||||||
/* get position to record with duplicated key */
|
/* get position to record with duplicated key */
|
||||||
tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff);
|
tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff);
|
||||||
if (tmp_key_length)
|
if (tmp_key_length)
|
||||||
dup_key_pos= _ma_dpos(info,0,keybuff+tmp_key_length);
|
dup_key_pos= _ma_dpos(info,0,keybuff+tmp_key_length);
|
||||||
@ -1521,7 +1524,7 @@ static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
|
|||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case free_init:
|
case free_init:
|
||||||
if (share->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
{
|
{
|
||||||
rw_wrlock(&share->key_root_lock[param->keynr]);
|
rw_wrlock(&share->key_root_lock[param->keynr]);
|
||||||
share->keyinfo[param->keynr].version++;
|
share->keyinfo[param->keynr].version++;
|
||||||
@ -1534,7 +1537,7 @@ static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
|
|||||||
return _ma_ck_write_btree(param->info, param->keynr, lastkey,
|
return _ma_ck_write_btree(param->info, param->keynr, lastkey,
|
||||||
keylen - share->rec_reflength);
|
keylen - share->rec_reflength);
|
||||||
case free_end:
|
case free_end:
|
||||||
if (share->concurrent_insert)
|
if (share->lock_key_trees)
|
||||||
rw_unlock(&share->key_root_lock[param->keynr]);
|
rw_unlock(&share->key_root_lock[param->keynr]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1613,7 +1616,7 @@ void maria_flush_bulk_insert(MARIA_HA *info, uint inx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void maria_end_bulk_insert(MARIA_HA *info)
|
void maria_end_bulk_insert(MARIA_HA *info, my_bool abort)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("maria_end_bulk_insert");
|
DBUG_ENTER("maria_end_bulk_insert");
|
||||||
if (info->bulk_insert)
|
if (info->bulk_insert)
|
||||||
@ -1621,11 +1624,15 @@ void maria_end_bulk_insert(MARIA_HA *info)
|
|||||||
uint i;
|
uint i;
|
||||||
for (i=0 ; i < info->s->base.keys ; i++)
|
for (i=0 ; i < info->s->base.keys ; i++)
|
||||||
{
|
{
|
||||||
if (is_tree_inited(& info->bulk_insert[i]))
|
if (is_tree_inited(&info->bulk_insert[i]))
|
||||||
|
{
|
||||||
|
if (abort)
|
||||||
|
reset_free_element(&info->bulk_insert[i]);
|
||||||
delete_tree(&info->bulk_insert[i]);
|
delete_tree(&info->bulk_insert[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
my_free(info->bulk_insert, MYF(0));
|
my_free(info->bulk_insert, MYF(0));
|
||||||
info->bulk_insert=0;
|
info->bulk_insert= 0;
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,10 @@
|
|||||||
#else
|
#else
|
||||||
#include <my_no_pthread.h>
|
#include <my_no_pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <hash.h>
|
||||||
#include "ma_loghandler.h"
|
#include "ma_loghandler.h"
|
||||||
#include "ma_control_file.h"
|
#include "ma_control_file.h"
|
||||||
|
#include "ma_state.h"
|
||||||
|
|
||||||
/* For testing recovery */
|
/* For testing recovery */
|
||||||
#ifdef TO_BE_REMOVED
|
#ifdef TO_BE_REMOVED
|
||||||
@ -51,17 +53,6 @@ struct st_transaction;
|
|||||||
|
|
||||||
#define CRC_SIZE 4
|
#define CRC_SIZE 4
|
||||||
|
|
||||||
typedef struct st_maria_status_info
|
|
||||||
{
|
|
||||||
ha_rows records; /* Rows in table */
|
|
||||||
ha_rows del; /* Removed rows */
|
|
||||||
my_off_t empty; /* lost space in datafile */
|
|
||||||
my_off_t key_empty; /* lost space in indexfile */
|
|
||||||
my_off_t key_file_length;
|
|
||||||
my_off_t data_file_length;
|
|
||||||
ha_checksum checksum;
|
|
||||||
} MARIA_STATUS_INFO;
|
|
||||||
|
|
||||||
typedef struct st_maria_state_info
|
typedef struct st_maria_state_info
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
@ -269,8 +260,8 @@ typedef struct st_maria_share
|
|||||||
{ /* Shared between opens */
|
{ /* Shared between opens */
|
||||||
MARIA_STATE_INFO state;
|
MARIA_STATE_INFO state;
|
||||||
MARIA_BASE_INFO base;
|
MARIA_BASE_INFO base;
|
||||||
MARIA_KEYDEF ft2_keyinfo; /* Second-level ft-key
|
MARIA_STATE_HISTORY *state_history;
|
||||||
definition */
|
MARIA_KEYDEF ft2_keyinfo; /* Second-level ft-key definition */
|
||||||
MARIA_KEYDEF *keyinfo; /* Key definitions */
|
MARIA_KEYDEF *keyinfo; /* Key definitions */
|
||||||
MARIA_UNIQUEDEF *uniqueinfo; /* unique definitions */
|
MARIA_UNIQUEDEF *uniqueinfo; /* unique definitions */
|
||||||
HA_KEYSEG *keyparts; /* key part info */
|
HA_KEYSEG *keyparts; /* key part info */
|
||||||
@ -356,6 +347,7 @@ typedef struct st_maria_share
|
|||||||
File data_file; /* Shared data file */
|
File data_file; /* Shared data file */
|
||||||
int mode; /* mode of file on open */
|
int mode; /* mode of file on open */
|
||||||
uint reopen; /* How many times reopened */
|
uint reopen; /* How many times reopened */
|
||||||
|
uint in_trans; /* Number of references by trn */
|
||||||
uint w_locks, r_locks, tot_locks; /* Number of read/write locks */
|
uint w_locks, r_locks, tot_locks; /* Number of read/write locks */
|
||||||
uint block_size; /* block_size of keyfile & data file*/
|
uint block_size; /* block_size of keyfile & data file*/
|
||||||
/* Fixed length part of a packed row in BLOCK_RECORD format */
|
/* Fixed length part of a packed row in BLOCK_RECORD format */
|
||||||
@ -370,7 +362,9 @@ typedef struct st_maria_share
|
|||||||
|
|
||||||
my_bool changed, /* If changed since lock */
|
my_bool changed, /* If changed since lock */
|
||||||
global_changed, /* If changed since open */
|
global_changed, /* If changed since open */
|
||||||
not_flushed, concurrent_insert;
|
not_flushed;
|
||||||
|
my_bool lock_key_trees; /* If we have to lock trees on read */
|
||||||
|
my_bool non_transactional_concurrent_insert;
|
||||||
my_bool delay_key_write;
|
my_bool delay_key_write;
|
||||||
my_bool have_rtree;
|
my_bool have_rtree;
|
||||||
/**
|
/**
|
||||||
@ -383,6 +377,7 @@ typedef struct st_maria_share
|
|||||||
my_bool used_key_del; /* != 0 if key_del is locked */
|
my_bool used_key_del; /* != 0 if key_del is locked */
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
THR_LOCK lock;
|
THR_LOCK lock;
|
||||||
|
void (*lock_restore_status)(void *);
|
||||||
pthread_mutex_t intern_lock; /* Locking for use with _locking */
|
pthread_mutex_t intern_lock; /* Locking for use with _locking */
|
||||||
pthread_cond_t intern_cond;
|
pthread_cond_t intern_cond;
|
||||||
rw_lock_t *key_root_lock;
|
rw_lock_t *key_root_lock;
|
||||||
@ -461,7 +456,8 @@ struct st_maria_handler
|
|||||||
{
|
{
|
||||||
MARIA_SHARE *s; /* Shared between open:s */
|
MARIA_SHARE *s; /* Shared between open:s */
|
||||||
struct st_transaction *trn; /* Pointer to active transaction */
|
struct st_transaction *trn; /* Pointer to active transaction */
|
||||||
MARIA_STATUS_INFO *state, save_state;
|
MARIA_STATUS_INFO *state, state_save;
|
||||||
|
MARIA_STATUS_INFO *state_start; /* State at start of transaction */
|
||||||
MARIA_ROW cur_row; /* The active row that we just read */
|
MARIA_ROW cur_row; /* The active row that we just read */
|
||||||
MARIA_ROW new_row; /* Storage for a row during update */
|
MARIA_ROW new_row; /* Storage for a row during update */
|
||||||
MARIA_BLOCK_SCAN scan, *scan_save;
|
MARIA_BLOCK_SCAN scan, *scan_save;
|
||||||
@ -733,7 +729,7 @@ extern uint maria_quick_table_bits;
|
|||||||
extern char *maria_data_root;
|
extern char *maria_data_root;
|
||||||
extern uchar maria_zero_string[];
|
extern uchar maria_zero_string[];
|
||||||
extern my_bool maria_inited;
|
extern my_bool maria_inited;
|
||||||
|
extern HASH maria_stored_state;
|
||||||
|
|
||||||
/* This is used by _ma_calc_xxx_key_length och _ma_store_key */
|
/* This is used by _ma_calc_xxx_key_length och _ma_store_key */
|
||||||
typedef struct st_maria_s_param
|
typedef struct st_maria_s_param
|
||||||
@ -1048,6 +1044,7 @@ void _ma_update_status(void *param);
|
|||||||
void _ma_restore_status(void *param);
|
void _ma_restore_status(void *param);
|
||||||
void _ma_copy_status(void *to, void *from);
|
void _ma_copy_status(void *to, void *from);
|
||||||
my_bool _ma_check_status(void *param);
|
my_bool _ma_check_status(void *param);
|
||||||
|
void _ma_restore_status(void *param);
|
||||||
void _ma_reset_status(MARIA_HA *maria);
|
void _ma_reset_status(MARIA_HA *maria);
|
||||||
int _ma_def_scan_remember_pos(MARIA_HA *info, MARIA_RECORD_POS *lastpos);
|
int _ma_def_scan_remember_pos(MARIA_HA *info, MARIA_RECORD_POS *lastpos);
|
||||||
void _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos);
|
void _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos);
|
||||||
|
@ -166,10 +166,10 @@ static int flush_buffer(ulong neaded_length);
|
|||||||
static void end_file_buffer(void);
|
static void end_file_buffer(void);
|
||||||
static void write_bits(ulonglong value, uint bits);
|
static void write_bits(ulonglong value, uint bits);
|
||||||
static void flush_bits(void);
|
static void flush_bits(void);
|
||||||
static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
|
static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,
|
||||||
ha_checksum crc);
|
my_off_t new_length, ha_checksum crc);
|
||||||
static int save_state_mrg(File file,PACK_MRG_INFO *isam_file,my_off_t new_length,
|
static int save_state_mrg(File file,PACK_MRG_INFO *isam_file,
|
||||||
ha_checksum crc);
|
my_off_t new_length, ha_checksum crc);
|
||||||
static int mrg_close(PACK_MRG_INFO *mrg);
|
static int mrg_close(PACK_MRG_INFO *mrg);
|
||||||
static int mrg_rrnd(PACK_MRG_INFO *info,uchar *buf);
|
static int mrg_rrnd(PACK_MRG_INFO *info,uchar *buf);
|
||||||
static void mrg_reset(PACK_MRG_INFO *mrg);
|
static void mrg_reset(PACK_MRG_INFO *mrg);
|
||||||
@ -2998,7 +2998,7 @@ static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,
|
|||||||
for (key=0 ; key < share->base.keys ; key++)
|
for (key=0 ; key < share->base.keys ; key++)
|
||||||
share->state.key_root[key]= HA_OFFSET_ERROR;
|
share->state.key_root[key]= HA_OFFSET_ERROR;
|
||||||
share->state.key_del= HA_OFFSET_ERROR;
|
share->state.key_del= HA_OFFSET_ERROR;
|
||||||
isam_file->state->checksum=crc; /* Save crc here */
|
share->state.state.checksum= crc; /* Save crc in file */
|
||||||
share->changed=1; /* Force write of header */
|
share->changed=1; /* Force write of header */
|
||||||
share->state.open_count=0;
|
share->state.open_count=0;
|
||||||
share->global_changed=0;
|
share->global_changed=0;
|
||||||
|
@ -51,6 +51,10 @@ static TRN **short_trid_to_active_trn;
|
|||||||
|
|
||||||
/* locks for short_trid_to_active_trn and pool */
|
/* locks for short_trid_to_active_trn and pool */
|
||||||
static my_atomic_rwlock_t LOCK_short_trid_to_trn, LOCK_pool;
|
static my_atomic_rwlock_t LOCK_short_trid_to_trn, LOCK_pool;
|
||||||
|
static my_bool default_trnman_end_trans_hook(TRN *, my_bool, my_bool);
|
||||||
|
|
||||||
|
my_bool (*trnman_end_trans_hook)(TRN *, my_bool, my_bool)=
|
||||||
|
default_trnman_end_trans_hook;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Simple interface functions
|
Simple interface functions
|
||||||
@ -78,6 +82,16 @@ void trnman_reset_locked_tables(TRN *trn, uint locked_tables)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static my_bool
|
||||||
|
default_trnman_end_trans_hook(TRN *trn __attribute__ ((unused)),
|
||||||
|
my_bool commit __attribute__ ((unused)),
|
||||||
|
my_bool active_transactions
|
||||||
|
__attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NOTE
|
NOTE
|
||||||
Just as short_id doubles as loid, this function doubles as
|
Just as short_id doubles as loid, this function doubles as
|
||||||
@ -325,6 +339,7 @@ TRN *trnman_new_trn(pthread_mutex_t *mutex, pthread_cond_t *cond,
|
|||||||
|
|
||||||
trn->commit_trid= 0;
|
trn->commit_trid= 0;
|
||||||
trn->rec_lsn= trn->undo_lsn= trn->first_undo_lsn= 0;
|
trn->rec_lsn= trn->undo_lsn= trn->first_undo_lsn= 0;
|
||||||
|
trn->used_tables= 0;
|
||||||
|
|
||||||
trn->locks.mutex= mutex;
|
trn->locks.mutex= mutex;
|
||||||
trn->locks.cond= cond;
|
trn->locks.cond= cond;
|
||||||
@ -342,6 +357,9 @@ TRN *trnman_new_trn(pthread_mutex_t *mutex, pthread_cond_t *cond,
|
|||||||
*/
|
*/
|
||||||
set_short_trid(trn);
|
set_short_trid(trn);
|
||||||
|
|
||||||
|
DBUG_PRINT("exit", ("trn: x%lx trid: 0x%lu",
|
||||||
|
(ulong) trn, (ulong) trn->trid));
|
||||||
|
|
||||||
DBUG_RETURN(trn);
|
DBUG_RETURN(trn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +380,7 @@ TRN *trnman_new_trn(pthread_mutex_t *mutex, pthread_cond_t *cond,
|
|||||||
0 ok
|
0 ok
|
||||||
1 error
|
1 error
|
||||||
*/
|
*/
|
||||||
int trnman_end_trn(TRN *trn, my_bool commit)
|
my_bool trnman_end_trn(TRN *trn, my_bool commit)
|
||||||
{
|
{
|
||||||
int res= 1;
|
int res= 1;
|
||||||
TRN *free_me= 0;
|
TRN *free_me= 0;
|
||||||
@ -435,8 +453,7 @@ int trnman_end_trn(TRN *trn, my_bool commit)
|
|||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
res == 1 means the condition in the if() above
|
res == 1 means the condition in the if() above was false.
|
||||||
was false.
|
|
||||||
res == -1 means lf_hash_insert failed
|
res == -1 means lf_hash_insert failed
|
||||||
*/
|
*/
|
||||||
trn->next= free_me;
|
trn->next= free_me;
|
||||||
@ -446,8 +463,10 @@ int trnman_end_trn(TRN *trn, my_bool commit)
|
|||||||
{
|
{
|
||||||
committed_list_max.prev= trn->prev->next= trn;
|
committed_list_max.prev= trn->prev->next= trn;
|
||||||
}
|
}
|
||||||
|
if ((*trnman_end_trans_hook)(trn, commit,
|
||||||
|
active_list_min.next != &active_list_max))
|
||||||
|
res= -1;
|
||||||
trnman_active_transactions--;
|
trnman_active_transactions--;
|
||||||
DBUG_PRINT("info", ("pthread_mutex_unlock LOCK_trn_list"));
|
|
||||||
pthread_mutex_unlock(&LOCK_trn_list);
|
pthread_mutex_unlock(&LOCK_trn_list);
|
||||||
|
|
||||||
/* the rest is done outside of a critical section */
|
/* the rest is done outside of a critical section */
|
||||||
@ -763,9 +782,30 @@ TRN *trnman_get_any_trn()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the minimum existing transaction id.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TrID trnman_get_min_trid()
|
||||||
|
{
|
||||||
|
TrID min_read_from;
|
||||||
|
if (short_trid_to_active_trn == NULL)
|
||||||
|
{
|
||||||
|
/* Transaction manager not initialize; Probably called from maria_chk */
|
||||||
|
return ~(TrID) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&LOCK_trn_list);
|
||||||
|
min_read_from= active_list_min.next->min_read_from;
|
||||||
|
pthread_mutex_unlock(&LOCK_trn_list);
|
||||||
|
return min_read_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns maximum transaction id given to a transaction so far.
|
Returns maximum transaction id given to a transaction so far.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TrID trnman_get_max_trid()
|
TrID trnman_get_max_trid()
|
||||||
{
|
{
|
||||||
TrID id;
|
TrID id;
|
||||||
@ -776,3 +816,39 @@ TrID trnman_get_max_trid()
|
|||||||
pthread_mutex_unlock(&LOCK_trn_list);
|
pthread_mutex_unlock(&LOCK_trn_list);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if there exist an active transaction between two commit_id's
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Improve speed of this.
|
||||||
|
- Store transactions in tree or skip list
|
||||||
|
- Have function to copying all active transaction id's to b-tree
|
||||||
|
and use b-tree for checking states. This could be a big win
|
||||||
|
for checkpoint that will call this function for a lot of objects.
|
||||||
|
|
||||||
|
@return
|
||||||
|
0 No transaction exists
|
||||||
|
1 There is at least on active transaction in the given range
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool trnman_exists_active_transactions(TrID min_id, TrID max_id,
|
||||||
|
my_bool trnman_is_locked)
|
||||||
|
{
|
||||||
|
TRN *trn;
|
||||||
|
my_bool ret= 0;
|
||||||
|
|
||||||
|
if (!trnman_is_locked)
|
||||||
|
pthread_mutex_lock(&LOCK_trn_list);
|
||||||
|
for (trn= active_list_min.next; trn != &active_list_max; trn= trn->next)
|
||||||
|
{
|
||||||
|
if (trn->trid > min_id && trn->trid < max_id)
|
||||||
|
{
|
||||||
|
ret= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!trnman_is_locked)
|
||||||
|
pthread_mutex_unlock(&LOCK_trn_list);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -42,9 +42,10 @@ C_MODE_START
|
|||||||
struct st_transaction
|
struct st_transaction
|
||||||
{
|
{
|
||||||
LOCK_OWNER locks; /* must be the first! see short_trid_to_TRN() */
|
LOCK_OWNER locks; /* must be the first! see short_trid_to_TRN() */
|
||||||
LF_PINS *pins;
|
LF_PINS *pins;
|
||||||
|
void *used_tables; /* Tables used by transaction */
|
||||||
|
TRN *next, *prev;
|
||||||
TrID trid, min_read_from, commit_trid;
|
TrID trid, min_read_from, commit_trid;
|
||||||
TRN *next, *prev;
|
|
||||||
LSN rec_lsn, undo_lsn;
|
LSN rec_lsn, undo_lsn;
|
||||||
LSN_WITH_FLAGS first_undo_lsn;
|
LSN_WITH_FLAGS first_undo_lsn;
|
||||||
uint locked_tables;
|
uint locked_tables;
|
||||||
|
@ -33,11 +33,13 @@ typedef struct st_transaction TRN;
|
|||||||
|
|
||||||
extern uint trnman_active_transactions, trnman_allocated_transactions;
|
extern uint trnman_active_transactions, trnman_allocated_transactions;
|
||||||
extern TRN dummy_transaction_object;
|
extern TRN dummy_transaction_object;
|
||||||
|
extern my_bool (*trnman_end_trans_hook)(TRN *trn, my_bool commit,
|
||||||
|
my_bool active_transactions);
|
||||||
|
|
||||||
int trnman_init(TrID);
|
int trnman_init(TrID);
|
||||||
void trnman_destroy(void);
|
void trnman_destroy(void);
|
||||||
TRN *trnman_new_trn(pthread_mutex_t *, pthread_cond_t *, void *);
|
TRN *trnman_new_trn(pthread_mutex_t *, pthread_cond_t *, void *);
|
||||||
int trnman_end_trn(TRN *trn, my_bool commit);
|
my_bool trnman_end_trn(TRN *trn, my_bool commit);
|
||||||
#define trnman_commit_trn(T) trnman_end_trn(T, TRUE)
|
#define trnman_commit_trn(T) trnman_end_trn(T, TRUE)
|
||||||
#define trnman_abort_trn(T) trnman_end_trn(T, FALSE)
|
#define trnman_abort_trn(T) trnman_end_trn(T, FALSE)
|
||||||
#define trnman_rollback_trn(T) trnman_end_trn(T, FALSE)
|
#define trnman_rollback_trn(T) trnman_end_trn(T, FALSE)
|
||||||
@ -55,7 +57,10 @@ uint trnman_has_locked_tables(TRN *trn);
|
|||||||
void trnman_reset_locked_tables(TRN *trn, uint locked_tables);
|
void trnman_reset_locked_tables(TRN *trn, uint locked_tables);
|
||||||
TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid);
|
TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid);
|
||||||
TRN *trnman_get_any_trn(void);
|
TRN *trnman_get_any_trn(void);
|
||||||
|
TrID trnman_get_min_trid(void);
|
||||||
TrID trnman_get_max_trid(void);
|
TrID trnman_get_max_trid(void);
|
||||||
|
my_bool trnman_exists_active_transactions(TrID min_id, TrID max_id,
|
||||||
|
my_bool trnman_is_locked);
|
||||||
#define TRANSID_SIZE 6
|
#define TRANSID_SIZE 6
|
||||||
#define transid_store(dst, id) int6store(dst,id)
|
#define transid_store(dst, id) int6store(dst,id)
|
||||||
#define transid_korr(P) uint6korr(P)
|
#define transid_korr(P) uint6korr(P)
|
||||||
|
@ -1511,12 +1511,12 @@ void ha_myisam::start_bulk_insert(ha_rows rows)
|
|||||||
!= 0 Error
|
!= 0 Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ha_myisam::end_bulk_insert()
|
int ha_myisam::end_bulk_insert(bool abort)
|
||||||
{
|
{
|
||||||
mi_end_bulk_insert(file);
|
mi_end_bulk_insert(file);
|
||||||
int err=mi_extra(file, HA_EXTRA_NO_CACHE, 0);
|
int err=mi_extra(file, HA_EXTRA_NO_CACHE, 0);
|
||||||
return err ? err : can_enable_indexes ?
|
return (err || abort ? err : can_enable_indexes ?
|
||||||
enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE) : 0;
|
enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ class ha_myisam: public handler
|
|||||||
int enable_indexes(uint mode);
|
int enable_indexes(uint mode);
|
||||||
int indexes_are_disabled(void);
|
int indexes_are_disabled(void);
|
||||||
void start_bulk_insert(ha_rows rows);
|
void start_bulk_insert(ha_rows rows);
|
||||||
int end_bulk_insert();
|
int end_bulk_insert(bool abort);
|
||||||
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
|
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
|
||||||
void update_create_info(HA_CREATE_INFO *create_info);
|
void update_create_info(HA_CREATE_INFO *create_info);
|
||||||
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
|
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user