List:Commits« Previous MessageNext Message »
From:monty Date:May 29 2008 5:33pm
Subject:bk commit into maria tree (monty:1.2629)
View as plain text  
Below is the list of changes that have just been committed into a local
maria repository of monty.  When monty does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-05-29 18:33:33+03:00, monty@stripped +72 -0
  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@stripped, 2008-05-29 18:33:25+03:00, monty@stripped +1 -1
    Added argument to maria_end_bulk_insert() to know if the table will be deleted after
the operation

  include/my_tree.h@stripped, 2008-05-29 18:33:25+03:00, monty@stripped +3 -2
    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@stripped, 2008-05-29 18:33:25+03:00, monty@stripped +1 -1
    Upgrade to new mysql_install_db options

  mysql-test/r/maria-mvcc.result@stripped, 2008-05-29 18:33:25+03:00, monty@stripped +61 -0
    New tests

  mysql-test/r/maria.result@stripped, 2008-05-29 18:33:25+03:00, monty@stripped +14 -0
    New tests

  mysql-test/suite/ndb/r/ndb_auto_increment.result@stripped, 2008-05-29 18:33:25+03:00,
monty@stripped +1 -1
    Fixed error message now when bulk insert is not always called

  mysql-test/suite/ndb/t/ndb_auto_increment.test@stripped, 2008-05-29 18:33:25+03:00,
monty@stripped +1 -1
    Fixed error message now when bulk insert is not always called

  mysql-test/t/maria-mvcc.test@stripped, 2008-05-29 18:33:25+03:00, monty@stripped +28 -0
    Added testing of versioning of count(*)

  mysql-test/t/maria-page-checksum.test@stripped, 2008-05-29 18:33:25+03:00, monty@stripped +5
-0
    Added comment

  mysql-test/t/maria.test@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +7 -1
    More tests

  mysys/hash.c@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +1 -1
    Code style change

  sql/field.cc@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +1 -1
    Allow storing year 2155 in year field

  sql/ha_ndbcluster.cc@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +3 -3
    Added new argument to end_bulk_insert() to signal if the bulk insert should ignored

  sql/ha_ndbcluster.h@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +1 -1
    Added new argument to end_bulk_insert() to signal if the bulk insert should ignored

  sql/ha_partition.cc@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +3 -2
    Added new argument to end_bulk_insert() to signal if the bulk insert should ignored

  sql/ha_partition.h@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +1 -1
    Added new argument to end_bulk_insert() to signal if the bulk insert should ignored

  sql/handler.cc@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +7 -4
    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@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +3 -3
    Added new argument to end_bulk_insert() to signal if the bulk insert should ignored
(ie, the table will be deleted)

  sql/item.cc@stripped, 2008-05-29 18:33:26+03:00, monty@stripped +7 -7
    Style fix
    Removed compiler warning

  sql/log_event.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +1 -1
    Added new argument to ha_end_bulk_insert()

  sql/log_event_old.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +2 -2
    Added new argument to ha_end_bulk_insert()

  sql/mysqld.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +1 -1
    Removed compiler warning

  sql/protocol.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +2 -0
    Added DBUG

  sql/sql_class.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +10 -3
    Added DBUG
    Fixed wrong call to strmake

  sql/sql_insert.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +10 -5
    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@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +1 -1
    Added new argument to ha_end_bulk_insert()

  sql/sql_parse.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +11 -8
    Style fixes
    Avoid goto in common senario

  sql/sql_select.cc@stripped, 2008-05-29 18:33:27+03:00, monty@stripped +18 -5
    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@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +2 -1
    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@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +3 -1
    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@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +1 -1
    Added new argument to end_bulk_insert()

  storage/archive/ha_archive.h@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +1 -1
    Added new argument to end_bulk_insert()

  storage/federated/ha_federated.cc@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +2
-2
    Added new argument to end_bulk_insert()

  storage/federated/ha_federated.h@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +1 -1
    Added new argument to end_bulk_insert()

  storage/maria/Makefile.am@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +7 -6
    Added ma_state.c and ma_state.h

  storage/maria/ha_maria.cc@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +101 -74
    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@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +1 -1
    New argument to end_bulk_insert()

  storage/maria/ma_blockrec.c@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +20 -85
    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@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +142 -145
    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@stripped, 2008-05-29 18:33:28+03:00, monty@stripped +8 -0
    Call _ma_remove_not_visible_states() on checkpoint to clean up not visible state
history from tables

  storage/maria/ma_close.c@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +21 -0
    Remember state history for running transaction even if table is closed

  storage/maria/ma_commit.c@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +9 -5
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +2 -5
    Versioning of count(*) and checksum:
    - Always update info->state->checksum and info->state->records

  storage/maria/ma_delete_all.c@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +9 -7
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +6 -6
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +23 -13
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +5 -5
    Get most state information from current state

  storage/maria/ma_init.c@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +23 -0
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +3 -3
    Versioning of count(*) and checksum:
    - Use share->state.state instead of info->state

  storage/maria/ma_locking.c@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +18 -139
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +49 -7
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +11 -7
    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@stripped, 2008-05-29 18:33:29+03:00, monty@stripped +7 -6
    Versioning of count(*) and checksum:
    - Lock trees based on share->lock_key_trees
    
    info->s -> share

  storage/maria/ma_recovery.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +14 -0
    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@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +3 -3
    Versioning of count(*) and checksum:
    - Lock trees based on share->lock_key_trees

  storage/maria/ma_rnext.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +2 -2
    Versioning of count(*) and checksum:
    - Lock trees based on share->lock_key_trees

  storage/maria/ma_rnext_same.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +5 -5
    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@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +4 -3
    Versioning of count(*) and checksum:
    - Lock trees based on share->lock_key_trees

  storage/maria/ma_rsame.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +2 -2
    Versioning of count(*) and checksum:
    - Lock trees based on share->lock_key_trees

  storage/maria/ma_sort.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +4 -3
    Use share->state.state instead of info->state
    Fixed indentation

  storage/maria/ma_state.c@stripped, 2008-05-29 18:33:31+03:00, monty@stripped +478 -0
    Functions to handle state of count(*) and checksum

  storage/maria/ma_state.c@stripped, 2008-05-29 18:33:31+03:00, monty@stripped +0 -0

  storage/maria/ma_state.h@stripped, 2008-05-29 18:33:31+03:00, monty@stripped +75 -0
    Structures and declarations to handle state of count(*) and checksum

  storage/maria/ma_state.h@stripped, 2008-05-29 18:33:31+03:00, monty@stripped +0 -0

  storage/maria/ma_static.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +1 -0
    Added maria_stored_state

  storage/maria/ma_update.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +7 -20
    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@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +19 -12
    Versioning of count(*) and checksum:
    - Always update info->state->checksum and info->state->records

  storage/maria/maria_def.h@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +13 -16
    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@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +5 -5
    Versioning of count(*) and checksum:
    - Use share->state.state instead of info->state
    
    Indentation fixes

  storage/maria/trnman.c@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +80 -4
    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@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +3 -2
    Added 'used_tables'
    Moved all pointers into same groups to get better memory alignment

  storage/maria/trnman_public.h@stripped, 2008-05-29 18:33:30+03:00, monty@stripped +6 -1
    Added prototypes for new functions and variables
    Chagned return type of trnman_end_trn() to my_bool

  storage/myisam/ha_myisam.cc@stripped, 2008-05-29 18:33:31+03:00, monty@stripped +3 -3
    Added argument to end_bulk_insert() if operation should be aborted

  storage/myisam/ha_myisam.h@stripped, 2008-05-29 18:33:31+03:00, monty@stripped +1 -1
    Added argument to end_bulk_insert() if operation should be aborted

diff -Nrup a/include/maria.h b/include/maria.h
--- a/include/maria.h	2008-04-10 05:25:43 +03:00
+++ b/include/maria.h	2008-05-29 18:33:25 +03:00
@@ -427,7 +427,7 @@ my_bool maria_test_if_sort_rep(MARIA_HA 
 
 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_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,
 			      PAGECACHE *key_cache);
 void maria_change_pagecache(PAGECACHE *old_key_cache,
diff -Nrup a/include/my_tree.h b/include/my_tree.h
--- a/include/my_tree.h	2007-05-10 12:59:24 +03:00
+++ b/include/my_tree.h	2008-05-29 18:33:25 +03:00
@@ -66,8 +66,8 @@ void init_tree(TREE *tree, ulong default
 	       tree_element_free free_element, void *custom_arg);
 void delete_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)
 
 	/* Functions on leafs */
@@ -86,6 +86,7 @@ void *tree_search_next(TREE *tree, TREE_
                        int r_offs);
 ha_rows tree_record_pos(TREE *tree, const void *key, 
                      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*))
 
diff -Nrup a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh
--- a/mysql-test/install_test_db.sh	2007-03-21 15:34:23 +02:00
+++ b/mysql-test/install_test_db.sh	2008-05-29 18:33:25 +03:00
@@ -102,7 +102,7 @@ basedir=.
 EXTRA_ARG="--windows"
 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"
 
 cd ..
diff -Nrup a/mysql-test/r/maria-mvcc.result b/mysql-test/r/maria-mvcc.result
--- a/mysql-test/r/maria-mvcc.result	2008-04-10 05:26:34 +03:00
+++ b/mysql-test/r/maria-mvcc.result	2008-05-29 18:33:25 +03:00
@@ -1,3 +1,4 @@
+set global maria_page_checksum=1;
 drop table if exists t1;
 create table t1 (i int) engine=maria;
 show create table t1;
@@ -13,9 +14,15 @@ select i from t1;
 i
 1
 2
+select count(*) from t1;
+count(*)
+2
 /* should see nothing */
 select i from t1;
 i
+select count(*) from t1;
+count(*)
+0
 lock tables t1 write concurrent;
 insert into t1 values (3);
 insert into t1 values (4);
@@ -24,6 +31,9 @@ select i from t1;
 i
 3
 4
+select count(*) from t1;
+count(*)
+2
 unlock tables;
 lock tables t1 write concurrent;
 insert into t1 values (5);
@@ -33,6 +43,18 @@ i
 3
 4
 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);
 /* Should see 1, 2, 6 */
 select i from t1;
@@ -40,6 +62,9 @@ i
 1
 2
 6
+select count(*) from t1;
+count(*)
+3
 unlock tables;
 lock tables t1 write concurrent;
 /* Should see 1, 2, 3, 4 and 6 */
@@ -50,12 +75,18 @@ i
 3
 4
 6
+select count(*) from t1;
+count(*)
+5
 /* should see 3, 4, 5 */
 select i from t1;
 i
 3
 4
 5
+select count(*) from t1;
+count(*)
+3
 unlock tables;
 /* should see 1, 2, 3, 4, 5, 6 */
 select i from t1;
@@ -66,6 +97,9 @@ i
 4
 5
 6
+select count(*) from t1;
+count(*)
+6
 unlock tables;
 /* should see 1, 2, 3, 4, 5, 6 */
 select i from t1;
@@ -76,4 +110,31 @@ i
 4
 5
 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;
diff -Nrup a/mysql-test/r/maria.result b/mysql-test/r/maria.result
--- a/mysql-test/r/maria.result	2008-04-01 17:57:27 +03:00
+++ b/mysql-test/r/maria.result	2008-05-29 18:33:25 +03:00
@@ -355,6 +355,9 @@ INSERT into t2 values (1,1,1), (2,2,2);
 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
 show index from t1;
 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	
@@ -2100,6 +2103,11 @@ test.t2	check	status	OK
 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
 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;
 CREATE TABLE t1 (seq int, s1 int, s2 blob);
 insert into t1 values (1, 1, MD5(1));
@@ -2242,6 +2250,12 @@ t
 9999-12-31 23:59:59
 2003-01-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;
 optimize table t1;
 Table	Op	Msg_type	Msg_text
diff -Nrup a/mysql-test/suite/ndb/r/ndb_auto_increment.result
b/mysql-test/suite/ndb/r/ndb_auto_increment.result
--- a/mysql-test/suite/ndb/r/ndb_auto_increment.result	2007-11-06 11:57:21 +02:00
+++ b/mysql-test/suite/ndb/r/ndb_auto_increment.result	2008-05-29 18:33:25 +03:00
@@ -416,7 +416,7 @@ a
 insert into t1 values (35);
 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;
 a
 1
diff -Nrup a/mysql-test/suite/ndb/t/ndb_auto_increment.test
b/mysql-test/suite/ndb/t/ndb_auto_increment.test
--- a/mysql-test/suite/ndb/t/ndb_auto_increment.test	2007-11-06 11:56:51 +02:00
+++ b/mysql-test/suite/ndb/t/ndb_auto_increment.test	2008-05-29 18:33:25 +03:00
@@ -276,7 +276,7 @@ connection server1;
 insert into t1 values (35);
 insert into t1 values (NULL);
 connection server2;
---error ER_DUP_ENTRY
+--error ER_DUP_ENTRY, ER_DUP_KEY
 insert into t1 values (NULL);
 select * from t1 order by a;
 
diff -Nrup a/mysql-test/t/maria-mvcc.test b/mysql-test/t/maria-mvcc.test
--- a/mysql-test/t/maria-mvcc.test	2008-04-10 05:26:34 +03:00
+++ b/mysql-test/t/maria-mvcc.test	2008-05-29 18:33:25 +03:00
@@ -4,6 +4,7 @@
 #
 
 -- source include/have_maria.inc
+set global maria_page_checksum=1;
 
 --disable_warnings
 drop table if exists t1;
@@ -19,41 +20,68 @@ insert into t1 values (1);
 insert into t1 values (2);
 /* should see 1 and 2 */
 select i from t1;
+select count(*) from t1;
 
 connect (con2,localhost,root,,);
 connection con2;
 /* should see nothing */
 select i from t1;
+select count(*) from t1;
 lock tables t1 write concurrent;
 insert into t1 values (3);
 insert into t1 values (4);
 /* should see 3 and 4 */
 select i from t1;
+select count(*) from t1;
 unlock tables;
 lock tables t1 write concurrent;
 insert into t1 values (5);
 /* should see 3, 4 and 5 */
 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;
 insert into t1 values (6);
 /* Should see 1, 2, 6 */
 select i from t1;
+select count(*) from t1;
 unlock tables;
 lock tables t1 write concurrent;
 /* Should see 1, 2, 3, 4 and 6 */
 select i from t1;
+select count(*) from t1;
 
 connection con2;
 /* should see 3, 4, 5 */
 select i from t1;
+select count(*) from t1;
 unlock tables;
 /* should see 1, 2, 3, 4, 5, 6 */
 select i from t1;
+select count(*) from t1;
 
 connection con1;
 unlock tables;
 /* should see 1, 2, 3, 4, 5, 6 */
 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;
diff -Nrup a/mysql-test/t/maria-page-checksum.test b/mysql-test/t/maria-page-checksum.test
--- a/mysql-test/t/maria-page-checksum.test	2008-04-10 05:25:43 +03:00
+++ b/mysql-test/t/maria-page-checksum.test	2008-05-29 18:33:25 +03:00
@@ -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
 
 --disable_warnings
diff -Nrup a/mysql-test/t/maria.test b/mysql-test/t/maria.test
--- a/mysql-test/t/maria.test	2008-04-01 17:57:27 +03:00
+++ b/mysql-test/t/maria.test	2008-05-29 18:33:26 +03:00
@@ -1,5 +1,5 @@
 #
-# Testing of potential probelms in Maria
+# Testing of potential problems in Maria
 # This code was initially taken from myisam.test
 #
 
@@ -377,6 +377,7 @@ INSERT into t1 values (0, null, 0), (0, 
 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);
 optimize table t1;
+check table t1;
 show index from t1;
 explain select * from t1,t2 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,
 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;
 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;
 
 # 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;
 insert into t1 values
(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030100000000),(20030000000000);
 select * from t1;
+optimize table t1;
+check table t1;
 delete from t1 where t > 0;
 optimize table t1;
 check table t1;
diff -Nrup a/mysys/hash.c b/mysys/hash.c
--- a/mysys/hash.c	2007-07-30 11:33:41 +03:00
+++ b/mysys/hash.c	2008-05-29 18:33:26 +03:00
@@ -318,7 +318,7 @@ my_bool my_hash_insert(HASH *info,const 
   LINT_INIT(ptr_to_rec);
   LINT_INIT(ptr_to_rec2);
 
-  if (HASH_UNIQUE & info->flags)
+  if (info->flags & HASH_UNIQUE)
   {
     uchar *key= (uchar*) hash_key(info, record, &idx, 1);
     if (hash_search(info, key, idx))
diff -Nrup a/sql/field.cc b/sql/field.cc
--- a/sql/field.cc	2008-02-13 21:27:03 +02:00
+++ b/sql/field.cc	2008-05-29 18:33:26 +03:00
@@ -5393,7 +5393,7 @@ int Field_year::store(const char *from, 
 
 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);
     return 1;
diff -Nrup a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
--- a/sql/ha_ndbcluster.cc	2007-12-27 18:49:20 +02:00
+++ b/sql/ha_ndbcluster.cc	2008-05-29 18:33:26 +03:00
@@ -4258,11 +4258,11 @@ void ha_ndbcluster::start_bulk_insert(ha
 /**
   End of an insert.
 */
-int ha_ndbcluster::end_bulk_insert()
+int ha_ndbcluster::end_bulk_insert(bool abort)
 {
   int error= 0;
-
   DBUG_ENTER("end_bulk_insert");
+
   // Check if last inserts need to be flushed
   if (m_bulk_insert_not_flushed)
   {
@@ -4578,7 +4578,7 @@ int ha_ndbcluster::external_lock(THD *th
   Thd_ndb *thd_ndb= get_thd_ndb(thd);
   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",
                        (long) this, (long) thd, (long) thd_ndb,
                        thd_ndb->lock_count));
diff -Nrup a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
--- a/sql/ha_ndbcluster.h	2007-11-05 22:11:14 +02:00
+++ b/sql/ha_ndbcluster.h	2008-05-29 18:33:26 +03:00
@@ -328,7 +328,7 @@ class ha_ndbcluster: public handler
   double scan_time();
   ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
   void start_bulk_insert(ha_rows rows);
-  int end_bulk_insert();
+  int end_bulk_insert(bool abort);
 
   static Thd_ndb* seize_thd_ndb();
   static void release_thd_ndb(Thd_ndb* thd_ndb);
diff -Nrup a/sql/ha_partition.cc b/sql/ha_partition.cc
--- a/sql/ha_partition.cc	2008-02-13 21:27:04 +02:00
+++ b/sql/ha_partition.cc	2008-05-29 18:33:26 +03:00
@@ -2999,13 +2999,14 @@ void ha_partition::start_bulk_insert(ha_
 
   SYNOPSIS
     end_bulk_insert()
+    abort		1 if table will be deleted (error condition)
 
   RETURN VALUE
     >0                      Error code
     0                       Success
 */
 
-int ha_partition::end_bulk_insert()
+int ha_partition::end_bulk_insert(bool abort)
 {
   int error= 0;
   handler **file;
@@ -3015,7 +3016,7 @@ int ha_partition::end_bulk_insert()
   do
   {
     int tmp;
-    if ((tmp= (*file)->ha_end_bulk_insert()))
+    if ((tmp= (*file)->ha_end_bulk_insert(abort)))
       error= tmp;
   } while (*(++file));
   DBUG_RETURN(error);
diff -Nrup a/sql/ha_partition.h b/sql/ha_partition.h
--- a/sql/ha_partition.h	2007-10-08 22:00:20 +03:00
+++ b/sql/ha_partition.h	2008-05-29 18:33:26 +03:00
@@ -315,7 +315,7 @@ public:
   virtual int delete_row(const uchar * buf);
   virtual int delete_all_rows(void);
   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)
   {
diff -Nrup a/sql/handler.cc b/sql/handler.cc
--- a/sql/handler.cc	2008-02-11 20:54:55 +02:00
+++ b/sql/handler.cc	2008-05-29 18:33:26 +03:00
@@ -2116,11 +2116,14 @@ void handler::print_error(int error, myf
     break;
   case HA_ERR_FOUND_DUPP_KEY:
   {
-    uint key_nr=get_dup_key(error);
-    if ((int) key_nr >= 0)
+    if (table)
     {
-      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
-      DBUG_VOID_RETURN;
+      uint key_nr=get_dup_key(error);
+      if ((int) key_nr >= 0)
+      {
+        print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
+        DBUG_VOID_RETURN;
+      }
     }
     textno=ER_DUP_KEY;
     break;
diff -Nrup a/sql/handler.h b/sql/handler.h
--- a/sql/handler.h	2008-02-11 20:54:55 +02:00
+++ b/sql/handler.h	2008-05-29 18:33:26 +03:00
@@ -1115,10 +1115,10 @@ public:
     estimation_rows_to_insert= rows;
     start_bulk_insert(rows);
   }
-  int ha_end_bulk_insert()
+  int ha_end_bulk_insert(bool abort)
   {
     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,
                          uint *dup_key_found);
@@ -1736,7 +1736,7 @@ private:
   virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
   { return HA_ADMIN_NOT_IMPLEMENTED; }
   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,
                          enum ha_rkey_function find_flag)
    { return  HA_ERR_WRONG_COMMAND; }
diff -Nrup a/sql/item.cc b/sql/item.cc
--- a/sql/item.cc	2008-02-13 21:27:04 +02:00
+++ b/sql/item.cc	2008-05-29 18:33:26 +03:00
@@ -1440,7 +1440,9 @@ bool DTCollation::aggregate(DTCollation 
     if (collation == &my_charset_bin)
     {
       if (derivation <= dt.derivation)
-	; // Do nothing
+      {
+	/* Do nothing */
+      }
       else
       {
 	set(dt); 
@@ -1452,13 +1454,11 @@ bool DTCollation::aggregate(DTCollation 
       {
         set(dt);
       }
-      else
-       ; // Do nothing
     }
     else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
              left_is_superset(this, &dt))
     {
-      // Do nothing
+      /* Do nothing */
     }
     else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
              left_is_superset(&dt, this))
@@ -1469,7 +1469,7 @@ bool DTCollation::aggregate(DTCollation 
              derivation < dt.derivation &&
              dt.derivation >= DERIVATION_SYSCONST)
     {
-      // Do nothing;
+      /* Do nothing */
     }
     else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
              dt.derivation < derivation &&
@@ -1486,7 +1486,7 @@ bool DTCollation::aggregate(DTCollation 
   }
   else if (derivation < dt.derivation)
   {
-    // Do nothing
+    /* Do nothing */
   }
   else if (dt.derivation < derivation)
   {
@@ -1496,7 +1496,7 @@ bool DTCollation::aggregate(DTCollation 
   { 
     if (collation == dt.collation)
     {
-      // Do nothing
+      /* Do nothing */
     }
     else 
     {
diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc	2008-02-13 21:27:04 +02:00
+++ b/sql/log_event.cc	2008-05-29 18:33:27 +03:00
@@ -7623,7 +7623,7 @@ Write_rows_log_event::do_after_row_opera
       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));
   }
diff -Nrup a/sql/log_event_old.cc b/sql/log_event_old.cc
--- a/sql/log_event_old.cc	2008-02-05 15:42:21 +02:00
+++ b/sql/log_event_old.cc	2008-05-29 18:33:27 +03:00
@@ -962,7 +962,7 @@ int Write_rows_log_event_old::do_after_r
     fires bug#27077
     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));
   }
@@ -2633,7 +2633,7 @@ Write_rows_log_event_old::do_after_row_o
     fires bug#27077
     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));
   }
diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2008-03-04 19:00:55 +02:00
+++ b/sql/mysqld.cc	2008-05-29 18:33:27 +03:00
@@ -2669,7 +2669,7 @@ int my_message_sql(uint error, const cha
     }
   }
 to_error_log:
-  if (!thd || MyFlags & ME_NOREFRESH)
+  if (!thd || (MyFlags & ME_NOREFRESH))
     (*func)("%s: %s", my_progname_short, str); /* purecov: inspected */
   DBUG_RETURN(0);
 }
diff -Nrup a/sql/protocol.cc b/sql/protocol.cc
--- a/sql/protocol.cc	2007-12-20 23:11:31 +02:00
+++ b/sql/protocol.cc	2008-05-29 18:33:27 +03:00
@@ -385,6 +385,7 @@ static uchar *net_store_length_fast(ucha
 
 void net_end_statement(THD *thd)
 {
+  DBUG_ENTER("net_end_statement");
   DBUG_ASSERT(! thd->main_da.is_sent);
 
   /* Can not be true, but do not take chances in production. */
@@ -421,6 +422,7 @@ void net_end_statement(THD *thd)
     break;
   }
   thd->main_da.is_sent= TRUE;
+  DBUG_VOID_RETURN;
 }
 
 
diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc
--- a/sql/sql_class.cc	2008-02-13 21:27:06 +02:00
+++ b/sql/sql_class.cc	2008-05-29 18:33:27 +03:00
@@ -367,6 +367,7 @@ char *thd_security_context(THD *thd, cha
 void
 Diagnostics_area::reset_diagnostics_area()
 {
+  DBUG_ENTER("reset_diagnostics_area");
 #ifdef DBUG_OFF
   can_overwrite_status= FALSE;
   /** Don't take chances in production */
@@ -380,6 +381,7 @@ Diagnostics_area::reset_diagnostics_area
   is_sent= FALSE;
   /** Tiny reset in debug mode to see garbage right away */
   m_status= DA_EMPTY;
+  DBUG_VOID_RETURN;
 }
 
 
@@ -393,6 +395,7 @@ Diagnostics_area::set_ok_status(THD *thd
                                 ulonglong last_insert_id_arg,
                                 const char *message_arg)
 {
+  DBUG_ENTER("set_ok_status");
   DBUG_ASSERT(! is_set());
   /* Refuse to overwrite an error with an OK packet. */
   if (is_error())
@@ -407,6 +410,7 @@ Diagnostics_area::set_ok_status(THD *thd
   else
     m_message[0]= '\0';
   m_status= DA_OK;
+  DBUG_VOID_RETURN;
 }
 
 
@@ -417,8 +421,8 @@ Diagnostics_area::set_ok_status(THD *thd
 void
 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());
   /* Refuse to overwrite an error with an EOF packet. */
   if (is_error())
@@ -433,6 +437,7 @@ Diagnostics_area::set_eof_status(THD *th
   m_total_warn_count= thd->spcont ? 0 : thd->total_warn_count;
 
   m_status= DA_EOF;
+  DBUG_VOID_RETURN;
 }
 
 /**
@@ -443,6 +448,7 @@ void
 Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
                                    const char *message_arg)
 {
+  DBUG_ENTER("set_error_status");
   /*
     Only allowed to report error if has not yet reported a success
     The only exception is when we flush the message to the client,
@@ -451,9 +457,10 @@ Diagnostics_area::set_error_status(THD *
   DBUG_ASSERT(! is_set() || can_overwrite_status);
 
   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;
+  DBUG_VOID_RETURN;
 }
 
 
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc	2008-02-05 17:07:57 +02:00
+++ b/sql/sql_insert.cc	2008-05-29 18:33:27 +03:00
@@ -555,6 +555,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   bool transactional_table, joins_freed= FALSE;
   bool changed;
   bool was_insert_delayed= (table_list->lock_type ==  TL_WRITE_DELAYED);
+  bool using_bulk_insert= 0;
   uint value_count;
   ulong counter = 1;
   ulonglong id;
@@ -716,8 +717,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
     values_list.elements, and - if nothing else - to initialize
     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);
+  }
 
   thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
                                        (MODE_STRICT_TRANS_TABLES |
@@ -831,7 +836,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       auto_inc values from the delayed_insert thread as they share TABLE.
     */
     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));
       error=1;
@@ -1167,7 +1172,7 @@ bool mysql_prepare_insert(THD *thd, TABL
   bool res= 0;
   table_map map= 0;
   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,
 		       (int)insert_into_view));
   /* 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'",
                        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_WRITE_CANNOT_REPLACE);
 
@@ -3195,7 +3200,7 @@ void select_insert::abort() {
       before.
     */
     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
diff -Nrup a/sql/sql_load.cc b/sql/sql_load.cc
--- a/sql/sql_load.cc	2008-02-13 21:27:06 +02:00
+++ b/sql/sql_load.cc	2008-05-29 18:33:27 +03:00
@@ -391,7 +391,7 @@ bool mysql_load(THD *thd,sql_exchange *e
       error= read_sep_field(thd, info, table_list, fields_vars,
                             set_fields, set_values, read_info,
 			    *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));
       error= 1;
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2008-02-13 21:27:06 +02:00
+++ b/sql/sql_parse.cc	2008-05-29 18:33:27 +03:00
@@ -2612,10 +2612,12 @@ end_with_restore_list:
 #endif /* HAVE_REPLICATION */
 
   case SQLCOM_ALTER_TABLE:
-    DBUG_ASSERT(first_table == all_tables && first_table != 0);
     {
       ulong priv=0;
       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,
         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);
       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;
       /*
         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))
     thd->row_count_func= -1;
 
-  goto finish;
-
-error:
-  res= TRUE;
-
 finish:
   if (need_start_waiting)
   {
@@ -4707,6 +4704,11 @@ finish:
     start_waiting_global_read_lock(thd);
   }
   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,
                Object_creation_ctx *creation_ctx)
 {
+  bool mysql_parse_status;
   DBUG_ASSERT(thd->m_lip == NULL);
 
   /* Backup creation context. */
@@ -7381,7 +7384,7 @@ bool parse_sql(THD *thd,
 
   /* 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. */
 
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc	2008-02-05 17:47:06 +02:00
+++ b/sql/sql_select.cc	2008-05-29 18:33:27 +03:00
@@ -1818,7 +1818,10 @@ JOIN::exec()
       curr_join->having= curr_join->tmp_having= 0; // Allready done
     
     /* 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)
     {
       items1= items0 + all_fields.elements;
@@ -1836,8 +1839,13 @@ JOIN::exec()
 				      fields_list.elements, all_fields))
 	  DBUG_VOID_RETURN;
       }
-      curr_join->tmp_all_fields1= tmp_all_fields1;
-      curr_join->tmp_fields_list1= tmp_fields_list1;
+#ifdef HAVE_purify
+      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_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_end=
 	curr_join->tmp_table_param.copy_field_end;
-      curr_join->tmp_all_fields3= tmp_all_fields3;
-      curr_join->tmp_fields_list3= tmp_fields_list3;
+#ifdef HAVE_purify
+      if (curr_join != this)
+#endif
+      {
+        curr_join->tmp_all_fields3= tmp_all_fields3;
+        curr_join->tmp_fields_list3= tmp_fields_list3;
+      }
     }
     else
     {
diff -Nrup a/sql/sql_select.h b/sql/sql_select.h
--- a/sql/sql_select.h	2007-12-27 18:49:23 +02:00
+++ b/sql/sql_select.h	2008-05-29 18:33:28 +03:00
@@ -459,7 +459,8 @@ public:
     group_optimized_away= 0;
 
     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));
     tmp_table_param.init();
     tmp_table_param.end_write_records= HA_POS_ERROR;
diff -Nrup a/sql/sql_table.cc b/sql/sql_table.cc
--- a/sql/sql_table.cc	2008-04-02 19:36:56 +03:00
+++ b/sql/sql_table.cc	2008-05-29 18:33:28 +03:00
@@ -7112,7 +7112,9 @@ err:
   free_io_cache(from);
   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));
     error=1;
diff -Nrup a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
--- a/storage/archive/ha_archive.cc	2007-12-20 22:24:07 +02:00
+++ b/storage/archive/ha_archive.cc	2008-05-29 18:33:28 +03:00
@@ -1511,7 +1511,7 @@ void ha_archive::start_bulk_insert(ha_ro
   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.
 */
-int ha_archive::end_bulk_insert()
+int ha_archive::end_bulk_insert(bool table_will_be_deleted)
 {
   DBUG_ENTER("ha_archive::end_bulk_insert");
   bulk_insert= FALSE;
diff -Nrup a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h
--- a/storage/archive/ha_archive.h	2007-07-13 03:39:04 +03:00
+++ b/storage/archive/ha_archive.h	2008-05-29 18:33:28 +03:00
@@ -134,7 +134,7 @@ public:
   int optimize(THD* thd, HA_CHECK_OPT* check_opt);
   int repair(THD* thd, HA_CHECK_OPT* check_opt);
   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 
   { 
     return ROW_TYPE_COMPRESSED;
diff -Nrup a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
--- a/storage/federated/ha_federated.cc	2007-11-30 20:30:22 +02:00
+++ b/storage/federated/ha_federated.cc	2008-05-29 18:33:28 +03:00
@@ -1961,12 +1961,12 @@ void ha_federated::start_bulk_insert(ha_
   @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;
   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))
       error= stash_remote_error();
diff -Nrup a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
--- a/storage/federated/ha_federated.h	2007-11-30 22:46:38 +02:00
+++ b/storage/federated/ha_federated.h	2008-05-29 18:33:28 +03:00
@@ -205,7 +205,7 @@ public:
   int close(void);                                              // required
 
   void start_bulk_insert(ha_rows rows);
-  int end_bulk_insert();
+  int end_bulk_insert(bool abort);
   int write_row(uchar *buf);
   int update_row(const uchar *old_data, uchar *new_data);
   int delete_row(const uchar *buf);
diff -Nrup a/storage/maria/Makefile.am b/storage/maria/Makefile.am
--- a/storage/maria/Makefile.am	2008-03-04 13:58:17 +02:00
+++ b/storage/maria/Makefile.am	2008-05-29 18:33:28 +03:00
@@ -71,9 +71,9 @@ noinst_HEADERS =	maria_def.h ma_rt_index
 			ma_ft_eval.h trnman.h lockman.h tablockman.h \
 			ma_control_file.h ha_maria.h ma_blockrec.h \
 			ma_loghandler.h ma_loghandler_lsn.h ma_pagecache.h \
-			ma_checkpoint.h ma_recovery.h ma_commit.h \
-			trnman_public.h ma_check_standalone.h ma_key_recover.h \
-			ma_recovery_util.h
+			ma_checkpoint.h ma_recovery.h ma_commit.h ma_state.h \
+			trnman_public.h ma_check_standalone.h \
+			ma_key_recover.h ma_recovery_util.h
 ma_test1_DEPENDENCIES=	$(LIBRARIES)
 ma_test1_LDADD=		@CLIENT_EXTRA_LDFLAGS@ libmaria.a \
                         $(top_builddir)/storage/myisam/libmyisam.a \
@@ -115,7 +115,7 @@ ma_sp_test_LDADD=		@CLIENT_EXTRA_LDFLAGS
 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_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_statrec.c ma_packrec.c ma_dynrec.c \
 			ma_blockrec.c ma_bitmap.c \
@@ -129,12 +129,13 @@ libmaria_a_SOURCES =	ma_init.c ma_open.c
 			ma_keycache.c ma_preload.c ma_ft_parser.c \
 			ma_ft_update.c ma_ft_boolean_search.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_sp_key.c ma_control_file.c ma_loghandler.c \
 			ma_pagecache.c ma_pagecaches.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?
 
 SUFFIXES = .sh
diff -Nrup a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
--- a/storage/maria/ha_maria.cc	2008-04-10 05:25:43 +03:00
+++ b/storage/maria/ha_maria.cc	2008-05-29 18:33:28 +03:00
@@ -1280,6 +1280,14 @@ int ha_maria::repair(THD *thd, HA_CHECK 
     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.table_name= table->alias;
   param.tmpfile_createflag= O_RDWR | O_TRUNC;
@@ -1287,7 +1295,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
   param.thd= thd;
   param.tmpdir= &mysql_tmpdir_list;
   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
   if (!thd->locked_tables &&
@@ -1298,7 +1306,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
   }
 
   if (!do_optimize ||
-      ((file->s->data_file_type == BLOCK_RECORD) ?
+      ((share->data_file_type == BLOCK_RECORD) ?
        (share->state.changed & STATE_NOT_OPTIMIZED_ROWS) :
        (file->state->del || share->state.split != file->state->records))
&&
       (!(param.testflag & T_QUICK) ||
@@ -1317,7 +1325,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
       statistics_done= 1;
       /* TODO: Remove BLOCK_RECORD test when parallel works with blocks */
       if (THDVAR(thd,repair_threads) > 1 &&
-          file->s->data_file_type != BLOCK_RECORD)
+          share->data_file_type != BLOCK_RECORD)
       {
         char buf[40];
         /* TODO: respect maria_repair_threads variable */
@@ -1379,18 +1387,17 @@ int ha_maria::repair(THD *thd, HA_CHECK 
       file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
     }
     /*
-       the following 'if', thought conceptually wrong,
-       is a useful optimization nevertheless.
+      repair updates share->state.state. Ensure that file->state is up to date
     */
-    if (file->state != &file->s->state.state)
-      file->s->state.state= *file->state;
-    if (file->s->base.auto_key)
+    if (file->state != &share->state.state)
+      *file->state= share->state.state;
+    if (share->base.auto_key)
       _ma_update_auto_increment_key(&param, file, 1);
     if (optimize_done)
       error= maria_update_state_info(&param, file,
-                               UPDATE_TIME | UPDATE_OPEN_COUNT |
-                               (local_testflag &
-                                T_STATISTICS ? UPDATE_STAT : 0));
+                                     UPDATE_TIME | UPDATE_OPEN_COUNT |
+                                     (local_testflag &
+                                      T_STATISTICS ? UPDATE_STAT : 0));
     info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
          HA_STATUS_CONST);
     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",
                         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. */
       param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
       error= (repair(thd, param, 0) != HA_ADMIN_OK);
@@ -1790,14 +1799,14 @@ void ha_maria::start_bulk_insert(ha_rows
     != 0  Error
 */
 
-int ha_maria::end_bulk_insert()
+int ha_maria::end_bulk_insert(bool table_will_be_deleted)
 {
   int err;
   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)))
     goto end;
-  if (can_enable_indexes)
+  if (can_enable_indexes && !table_will_be_deleted)
     err= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 end:
   if (bulk_insert_single_undo != BULK_INSERT_NONE)
@@ -2181,77 +2190,95 @@ int ha_maria::external_lock(THD *thd, in
     external_lock(F_UNLCK) will happen and we can then allow the user to
     create transactional temporary tables.
   */
-  if (!file->s->base.born_transactional)
-    goto skip_transaction;
-  if (lock_type != F_UNLCK)
+  if (file->s->base.born_transactional)
   {
-    if (!trn)  /* no transaction yet - open it now */
+    /* Transactional table */
+    if (lock_type != F_UNLCK)
     {
-      trn= trnman_new_trn(& thd->mysys_var->mutex,
-                          & thd->mysys_var->suspend,
-                          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);
+      /* Start of new statement */
+      if (!trn)  /* no transaction yet - open it now */
+      {
+        trn= trnman_new_trn(& thd->mysys_var->mutex,
+                            & thd->mysys_var->suspend,
+                            thd->thread_stack + STACK_DIRECTION *
+                            (my_thread_stack_size - STACK_MIN_SIZE));
+        if (unlikely(!trn))
+          DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+        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 (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);
+      }
     }
-    if (!thd->transaction.on)
+    else
     {
+      /* End of transaction */
+
       /*
-        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.
+        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).
       */
-      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))
+      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))
       {
-        /* 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)))
+        if (!trnman_decrement_locked_tables(trn))
         {
-          trnman_rollback_trn(trn);
-          DBUG_PRINT("info", ("THD_TRN set to 0x0"));
+          /* 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
+        }
       }
     }
-  }
-skip_transaction:
+  } /* if transactional table */
   DBUG_RETURN(maria_lock_database(file, !table->s->tmp_table ?
                                   lock_type : ((lock_type == F_UNLCK) ?
                                                F_UNLCK : F_EXTRA_LCK)));
@@ -2849,7 +2876,7 @@ my_bool ha_maria::register_query_cache_t
     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;
-  current_data_file_length= file->save_state.data_file_length;
+  current_data_file_length= file->state->data_file_length;
 
   if (!file->s->now_transactional &&
       current_data_file_length != actual_data_file_length)
diff -Nrup a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h
--- a/storage/maria/ha_maria.h	2008-04-01 17:57:27 +03:00
+++ b/storage/maria/ha_maria.h	2008-05-29 18:33:28 +03:00
@@ -122,7 +122,7 @@ public:
   int enable_indexes(uint mode);
   int indexes_are_disabled(void);
   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);
   void update_create_info(HA_CREATE_INFO * create_info);
   int create(const char *name, TABLE * form, HA_CREATE_INFO * create_info);
diff -Nrup a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
--- a/storage/maria/ma_blockrec.c	2008-04-10 05:26:12 +03:00
+++ b/storage/maria/ma_blockrec.c	2008-05-29 18:33:28 +03:00
@@ -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
    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 */
   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
@@ -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
       collect_tables()).
     */
-    info->state->data_file_length= position + block_size;
+    _ma_set_share_data_file_length(share, position + block_size);
   }
 
   if (block_is_read)
@@ -2020,8 +2020,8 @@ static my_bool write_full_pages(MARIA_HA
   sub_blocks= block->sub_blocks;
 
   position= (my_off_t) (page + page_count) * block_size;
-  if (info->state->data_file_length < position)
-    info->state->data_file_length= position;
+  if (share->state.state.data_file_length < position)
+    _ma_set_share_data_file_length(share, position);
 
   /* Increase data file size, if extended */
 
@@ -2044,8 +2044,8 @@ static my_bool write_full_pages(MARIA_HA
                           (ulong) block->page, (ulong) block->page_count));
 
       position= (page + page_count + 1) * block_size;
-      if (info->state->data_file_length < position)
-        info->state->data_file_length= position;
+      if (share->state.state.data_file_length < position)
+        _ma_set_share_data_file_length(share, position);
     }
     lsn_store(buff, lsn);
     buff[PAGE_TYPE_OFFSET]= (uchar) BLOB_PAGE;
@@ -3003,8 +3003,8 @@ static my_bool write_block_record(MARIA_
 
   /* Increase data file size, if extended */
   position= (my_off_t) head_block->page * block_size;
-  if (info->state->data_file_length <= position)
-    info->state->data_file_length= position + block_size;
+  if (share->state.state.data_file_length <= position)
+    _ma_set_share_data_file_length(share, position + block_size);
 
   if (head_block_is_read)
   {
@@ -4318,7 +4318,8 @@ static uchar *read_next_extent(MARIA_HA 
   if (!buff)
   {
     /* 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;
     DBUG_RETURN(0);
   }
@@ -5223,7 +5224,7 @@ restart_bitmap_scan:
   /* Read next bitmap */
   info->scan.bitmap_page+= share->bitmap.pages_covered;
   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_RETURN((my_errno= HA_ERR_END_OF_FILE));
@@ -5798,7 +5799,6 @@ my_bool write_hook_for_undo(enum translo
   if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0))
     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;
   /*
     when we implement purging, we will specialize this hook: UNDO_PURGE
@@ -5820,14 +5820,13 @@ my_bool write_hook_for_redo_delete_all(e
                                        __attribute__ ((unused)),
                                        LSN *lsn, void *hook_arg)
 {
-  DBUG_ASSERT(tbl_info->state == &tbl_info->s->state.state);
   _ma_reset_status(tbl_info);
   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)
 */
@@ -5974,10 +5973,10 @@ uint _ma_apply_redo_insert_row_head_or_t
                           STATE_NOT_MOVABLE);
 
   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",
-                        (ulong) info->state->data_file_length,
+                        (ulong) share->state.state.data_file_length,
                         (ulong) end_of_page));
     /*
       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_t
     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.
   */
-  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);
 
 crashed_file:
@@ -6439,13 +6438,13 @@ uint _ma_apply_redo_insert_row_blobs(MAR
           continue;
 
         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 */
           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)));
-          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;
           info->keyread_buff_used= 1;
           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
-
-  @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
+  @brief Enable reading of all rows, ignoring versioning
 
   @note
     This is mainly useful in single user applications, like maria_pack,
diff -Nrup a/storage/maria/ma_check.c b/storage/maria/ma_check.c
--- a/storage/maria/ma_check.c	2008-04-10 05:26:12 +03:00
+++ b/storage/maria/ma_check.c	2008-05-29 18:33:28 +03:00
@@ -201,7 +201,7 @@ int maria_chk_del(HA_CHECK *param, regis
     puts("- check record delete-chain");
 
   next_link=share->state.dellink;
-  if (info->state->del == 0)
+  if (share->state.state.del == 0)
   {
     if (test_flag & T_VERBOSE)
     {
@@ -213,13 +213,13 @@ int maria_chk_del(HA_CHECK *param, regis
     if (test_flag & T_VERBOSE)
       printf("Recordlinks:    ");
     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))
         DBUG_RETURN(1);
       if (test_flag & T_VERBOSE)
 	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;
       if (my_pread(info->dfile.file, (uchar*) buff, delete_link_length,
 		   next_link,MYF(MY_NABP)))
@@ -256,28 +256,28 @@ int maria_chk_del(HA_CHECK *param, regis
 	empty+=share->base.pack_reclength;
       }
     }
-    if (info->state->del && (test_flag & T_VERBOSE))
+    if (share->state.state.del && (test_flag & T_VERBOSE))
       puts("\n");
-    if (empty != info->state->empty)
+    if (empty != share->state.state.empty)
     {
       _ma_check_print_warning(param,
 			     "Found %s deleted space in delete link chain. Should be %s",
 			     llstr(empty,buff2),
-			     llstr(info->state->empty,buff));
+			     llstr(share->state.state.empty,buff));
     }
     if (next_link != HA_OFFSET_ERROR)
     {
       _ma_check_print_error(param,
 			   "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;
     }
     if (i != 0)
     {
       _ma_check_print_error(param,
 			   "Found %s deleted rows in delete link chain. Should be %s",
-			   llstr(info->state->del - i, buff2),
-			   llstr(info->state->del, buff));
+			   llstr(share->state.state.del - i, buff2),
+			   llstr(share->state.state.del, buff));
       goto wrong;
     }
   }
@@ -307,7 +307,7 @@ static int check_k_link(HA_CHECK *param,
   if (next_link == HA_OFFSET_ERROR)
     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)
   {
     if (*_ma_killed_ptr(param))
@@ -316,13 +316,13 @@ static int check_k_link(HA_CHECK *param,
       printf("%16s",llstr(next_link,llbuff));
 
     /* 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 */
       _ma_check_print_error(param, "Invalid key block position: %s  "
                             "key block size: %u  file_length: %s",
                             llstr(next_link, llbuff), block_size,
-                            llstr(info->state->key_file_length, llbuff2));
+                            llstr(share->state.state.key_file_length, llbuff2));
       DBUG_RETURN(1);
       /* purecov: end */
     }
@@ -396,7 +396,7 @@ int maria_chk_size(HA_CHECK *param, regi
     _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));
-  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 */
     if (skr > size && maria_is_any_key_active(share->state.key_map))
@@ -413,26 +413,26 @@ int maria_chk_size(HA_CHECK *param, regi
   }
   if (!(param->testflag & T_VERY_SILENT) &&
       ! (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)
     _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));
 
   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)
     skr+= MEMMAP_EXTRA_MARGIN;
 #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;
 #endif
   if (skr != size)
   {
-    info->state->data_file_length=size;	/* Skip other errors */
     if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
     {
+      share->state.state.data_file_length=size;	/* Skip other errors */
       error=1;
       _ma_check_print_error(param,"Size of datafile is: %-9s         Should be: %s",
 		    llstr(size,buff), llstr(skr,buff2));
@@ -447,10 +447,10 @@ int maria_chk_size(HA_CHECK *param, regi
   }
   if (!(param->testflag & T_VERY_SILENT) &&
       !(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))
     _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));
   DBUG_RETURN(error);
 } /* maria_chk_size */
@@ -488,8 +488,8 @@ int maria_chk_key(HA_CHECK *param, regis
   init_checksum=param->record_checksum;
   old_record_checksum=0;
   if (share->data_file_type == STATIC_RECORD)
-    old_record_checksum= (calc_checksum(info->state->records +
-                                        info->state->del-1) *
+    old_record_checksum= (calc_checksum(share->state.state.records +
+                                        share->state.state.del-1) *
                           share->base.pack_reclength);
   rec_per_key_part= param->new_rec_per_key_part;
   for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
@@ -518,7 +518,7 @@ int maria_chk_key(HA_CHECK *param, regis
       full_text_keys++;
     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);
       goto do_stat;
     }
@@ -542,10 +542,10 @@ int maria_chk_key(HA_CHECK *param, regis
       DBUG_RETURN(-1);
     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),
-		    llstr(info->state->records,buff2));
+		    llstr(share->state.state.records,buff2));
 	if (!(param->testflag & T_INFO))
 	DBUG_RETURN(-1);
 	result= -1;
@@ -625,7 +625,7 @@ do_stat:
       maria_update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
                        param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
                        param->notnull_count: NULL,
-                       (ulonglong)info->state->records);
+                       (ulonglong)share->state.state.records);
   }
   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))
       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)
     _ma_check_print_warning(param, "Some data are unreferenced in keyfile");
   if (found_keys != full_text_keys)
@@ -657,10 +657,11 @@ static int chk_index_down(HA_CHECK *para
                           ha_checksum *key_checksum, uint level)
 {
   char llbuff[22],llbuff2[22];
+  MARIA_SHARE *share= info->s;
   DBUG_ENTER("chk_index_down");
 
   /* 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 */
     /* Give it a chance to fit in the real file size. */
@@ -669,12 +670,13 @@ static int chk_index_down(HA_CHECK *para
     _ma_check_print_error(param, "Invalid key block position: %s  "
                           "key block size: %u  file_length: %s",
                           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)
       goto err;
     /* Fix the remembered key file length. */
-    info->state->key_file_length= (max_length &
-                                   ~ (my_off_t) (keyinfo->block_length - 1));
+    share->state.state.key_file_length= (max_length &
+                                          ~ (my_off_t) (keyinfo->block_length -
+                                                        1));
     /* purecov: end */
   }
 
@@ -941,7 +943,7 @@ static int chk_index(HA_CHECK *param, MA
       }
       /* fall through */
     }
-    if (record >= info->state->data_file_length)
+    if (record >= share->state.state.data_file_length)
     {
 #ifndef DBUG_OFF
       char llbuff2[22], llbuff3[22];
@@ -949,7 +951,7 @@ static int chk_index(HA_CHECK *param, MA
       _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",
 			 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("new_in_page", old_keypos, (uint) (keypos-old_keypos));
       goto err;
@@ -1126,7 +1128,7 @@ static int check_static_record(HA_CHECK 
   char llbuff[22];
 
   pos= 0;
-  while (pos < info->state->data_file_length)
+  while (pos < share->state.state.data_file_length)
   {
     if (*_ma_killed_ptr(param))
       return -1;
@@ -1173,7 +1175,7 @@ static int check_dynamic_record(HA_CHECK
   LINT_INIT(to);
 
   pos= 0;
-  while (pos < info->state->data_file_length)
+  while (pos < share->state.state.data_file_length)
   {
     my_bool got_error= 0;
     int flag;
@@ -1228,9 +1230,9 @@ static int check_dynamic_record(HA_CHECK
             DBUG_RETURN(1);
           }
           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 >= 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",
                                   llstr(pos,llbuff));
@@ -1248,7 +1250,7 @@ static int check_dynamic_record(HA_CHECK
                               llstr(start_block,llbuff));
         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)
       {
         _ma_check_print_error(param,
@@ -1322,7 +1324,7 @@ static int check_dynamic_record(HA_CHECK
           got_error=1;
           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,
                                 "Found next-recordlink that points outside datafile at
%s",
@@ -1391,7 +1393,7 @@ static int check_compressed_record(HA_CH
   DBUG_ENTER("check_compressed_record");
 
   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))
       DBUG_RETURN(-1);
@@ -1742,10 +1744,10 @@ static int check_block_record(HA_CHECK *
   full_page_count= tail_count= 0;
   param->full_page_count= param->tail_count= 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;
-       pos < info->state->data_file_length;
+       pos < share->state.state.data_file_length;
        pos+= block_size, page++)
   {
     uint row_count, real_row_count, empty_space, page_type, bitmap_pattern;
@@ -1985,12 +1987,12 @@ int maria_chk_data_link(HA_CHECK *param,
   {
     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,
                           "Record-count is not ok; found %-10s  Should be: %s",
                           llstr(param->records,llbuff),
-                          llstr(info->state->records,llbuff2));
+                          llstr(share->state.state.records,llbuff2));
     error=1;
   }
   else if (param->record_checksum &&
@@ -2000,7 +2002,7 @@ int maria_chk_data_link(HA_CHECK *param,
                           "Key pointers and record positions doesn't match");
     error=1;
   }
-  else if (param->glob_crc != info->state->checksum &&
+  else if (param->glob_crc != share->state.state.checksum &&
 	   (share->options &
 	    (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
   {
@@ -2023,18 +2025,18 @@ int maria_chk_data_link(HA_CHECK *param,
     }
   }
 
-  if (param->del_length != info->state->empty)
+  if (param->del_length != share->state.state.empty)
   {
     _ma_check_print_warning(param,
                             "Found %s deleted space.   Should be %s",
                             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 */
   if (share->data_file_type != BLOCK_RECORD)
   {
     if (param->used + param->empty + param->del_length !=
-        info->state->data_file_length)
+        share->state.state.data_file_length)
     {
       _ma_check_print_warning(param,
                               "Found %s record data and %s unused data and %s deleted
data",
@@ -2045,14 +2047,14 @@ int maria_chk_data_link(HA_CHECK *param,
                               "Total %s   Should be: %s",
                               llstr((param->used+param->empty +
                                      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,
                               "Found %10s deleted blocks       Should be: %s",
                               llstr(param->del_blocks,llbuff),
-                              llstr(info->state->del,llbuff2));
+                              llstr(share->state.state.del,llbuff2));
     }
     if (param->splits != share->state.split)
     {
@@ -2224,7 +2226,7 @@ static int initialize_variables_for_repa
   sort_info->filelength= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
   if ((param->testflag & T_CREATE_MISSING_KEYS) ||
       sort_info->org_data_file_type == COMPRESSED_RECORD)
-    sort_info->max_records= info->state->records;
+    sort_info->max_records= share->state.state.records;
   else
   {
     ulong rec_length;
@@ -2354,7 +2356,7 @@ static int maria_drop_all_indexes(HA_CHE
   share->state.key_del=  HA_OFFSET_ERROR;
 
   /* 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:
   DBUG_RETURN(0);
@@ -2403,7 +2405,7 @@ int maria_repair(HA_CHECK *param, regist
 
   got_error= 1;
   new_file= -1;
-  start_records= info->state->records;
+  start_records= share->state.state.records;
   if (!(param->testflag & T_SILENT))
   {
     printf("- recovering (with keycache) MARIA-table '%s'\n",name);
@@ -2494,9 +2496,9 @@ int maria_repair(HA_CHECK *param, regist
   sort_param.master=1;
   sort_info.max_records= ~(ha_rows) 0;
 
-  del=info->state->del;
-  info->state->records=info->state->del=share->state.split=0;
-  info->state->empty=0;
+  del= share->state.state.del;
+  share->state.state.records= share->state.state.del= share->state.split= 0;
+  share->state.state.empty= 0;
 
   if (param->testflag & T_CREATE_MISSING_KEYS)
     maria_set_all_keys_active(share->state.key_map, share->base.keys);
@@ -2538,7 +2540,7 @@ int maria_repair(HA_CHECK *param, regist
       /* purecov: begin tested */
       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))
         {
           _ma_check_print_error(param,"Couldn't delete duplicate row");
@@ -2565,7 +2567,7 @@ int maria_repair(HA_CHECK *param, regist
   {
     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,
 			   "Can't change size of indexfile, error: %d",
@@ -2573,7 +2575,7 @@ int maria_repair(HA_CHECK *param, regist
     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,"Run recovery again without -q");
@@ -2585,9 +2587,9 @@ int maria_repair(HA_CHECK *param, regist
   if (param->testflag & T_SAFE_REPAIR)
   {
     /* 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;
     }
   }
@@ -2606,7 +2608,7 @@ int maria_repair(HA_CHECK *param, regist
 
   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)
     {
       MARIA_STATE_INFO save_state= sort_info.new_info->s->state;
@@ -2638,15 +2640,15 @@ int maria_repair(HA_CHECK *param, regist
   }
   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)
-    info->state->checksum= param->glob_crc;
+    share->state.state.checksum= param->glob_crc;
 
   if (!(param->testflag & T_SILENT))
   {
-    if (start_records != info->state->records)
-      printf("Data records: %s\n", llstr(info->state->records,llbuff));
+    if (start_records != share->state.state.records)
+      printf("Data records: %s\n", llstr(share->state.state.records,llbuff));
   }
   if (sort_info.dupp)
     _ma_check_print_warning(param,
@@ -2656,11 +2658,12 @@ int maria_repair(HA_CHECK *param, regist
   got_error= 0;
   /* If invoked by external program that uses thr_lock */
   if (&share->state.state != info->state)
-    memcpy(&share->state.state, info->state, sizeof(*info->state));
+    *info->state= *info->state_start= share->state.state;
 
 err:
   if (scan_inited)
     maria_scan_end(sort_info.info);
+  _ma_reset_state(info);
 
   VOID(end_io_cache(&param->read_cache));
   VOID(end_io_cache(&sort_info.new_info->rec_cache));
@@ -2952,7 +2955,7 @@ int maria_sort_index(HA_CHECK *param, re
   share->tot_locks= r_locks+w_locks;
   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);
   for (key=0 ; key < share->base.keys ; key++)
     share->state.key_root[key]=index_pos[key];
@@ -3185,7 +3188,7 @@ static my_bool maria_zerofill_data(HA_CH
 
   /* Go through the record file */
   for (page= 1, pos= block_size;
-       pos < info->state->data_file_length;
+       pos < share->state.state.data_file_length;
        pos+= block_size, page++)
   {
     uchar *buff;
@@ -3416,7 +3419,7 @@ int maria_repair_by_sort(HA_CHECK *param
 
   got_error= 1;
   new_file= -1;
-  start_records= info->state->records;
+  start_records= share->state.state.records;
   if (!(param->testflag & T_SILENT))
   {
     printf("- recovering (with sort) MARIA-table '%s'\n",name);
@@ -3517,7 +3520,7 @@ int maria_repair_by_sort(HA_CHECK *param
   sort_param.tmpdir=param->tmpdir;
   sort_param.master =1;
 
-  del=info->state->del;
+  del=share->state.state.del;
 
   rec_per_key_part= param->new_rec_per_key_part;
   for (sort_param.key=0 ; sort_param.key < share->base.keys ;
@@ -3559,8 +3562,8 @@ int maria_repair_by_sort(HA_CHECK *param
       if (keyseg[i].flag & HA_NULL_PART)
 	sort_param.key_length++;
     }
-    info->state->records=info->state->del=share->state.split=0;
-    info->state->empty=0;
+    share->state.state.records=share->state.state.del=share->state.split=0;
+    share->state.state.empty=0;
 
     if (sort_param.keyinfo->flag & HA_FULLTEXT)
     {
@@ -3638,15 +3641,14 @@ int maria_repair_by_sort(HA_CHECK *param
     free_root(&sort_param.wordroot, MYF(0));
 
     /* 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)
       maria_update_key_parts(sort_param.keyinfo, rec_per_key_part,
                              sort_param.unique,
                              (param->stats_method ==
                               MI_STATS_METHOD_IGNORE_NULLS ?
                               sort_param.notnull : NULL),
-                             (ulonglong) info->state->records);
+                             (ulonglong) share->state.state.records);
     maria_set_key_active(share->state.key_map, 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
       if (param->testflag & T_SAFE_REPAIR)
       {
 	/* 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,
                                 "Rows lost; Aborting because safe repair was "
                                 "requested");
-          info->state->records=start_records;
+          share->state.state.records=start_records;
 	  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)
       {
         MARIA_STATE_INFO save_state= sort_info.new_info->s->state;
@@ -3716,11 +3718,11 @@ int maria_repair_by_sort(HA_CHECK *param
 
       org_header_length= share->pack.header_length;
       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;
     }
     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 */
     reinit_io_cache(&param->read_cache,READ_CACHE,share->pack.header_length,
@@ -3732,7 +3734,7 @@ int maria_repair_by_sort(HA_CHECK *param
     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,"Run recovery again without -q");
@@ -3744,7 +3746,7 @@ int maria_repair_by_sort(HA_CHECK *param
 
   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) ?
                    MEMMAP_EXTRA_MARGIN : 0);
 #ifdef USE_RELOC
@@ -3760,30 +3762,31 @@ int maria_repair_by_sort(HA_CHECK *param
   }
 
   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,
 			   "Can't change size of indexfile, error: %d",
 			   my_errno);
 
   if (!(param->testflag & T_SILENT))
   {
-    if (start_records != info->state->records)
-      printf("Data records: %s\n", llstr(info->state->records,llbuff));
+    if (start_records != share->state.state.records)
+      printf("Data records: %s\n", llstr(share->state.state.records,llbuff));
   }
   if (sort_info.dupp)
     _ma_check_print_warning(param,
                             "%s records have been removed",
                             llstr(sort_info.dupp,llbuff));
   got_error=0;
-
+  /* If invoked by external program that uses thr_lock */
   if (&share->state.state != info->state)
-    memcpy(&share->state.state, info->state, sizeof(*info->state));
+    *info->state= *info->state_start= share->state.state;
 
 err:
   if (scan_inited)
     maria_scan_end(sort_info.info);
+  _ma_reset_state(info);
 
   VOID(end_io_cache(&sort_info.new_info->rec_cache));
   VOID(end_io_cache(&param->read_cache));
@@ -3909,7 +3912,7 @@ int maria_repair_parallel(HA_CHECK *para
 
   got_error= 1;
   new_file= -1;
-  start_records= info->state->records;
+  start_records= share->state.state.records;
   if (!(param->testflag & T_SILENT))
   {
     printf("- parallel recovering (with sort) MARIA-table '%s'\n",name);
@@ -4014,7 +4017,7 @@ int maria_repair_parallel(HA_CHECK *para
 
   /*
     +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
     increased in sort_key_write. In maria_repair_by_sort, sort_key_write
     is called after sort_key_read, where the comparison is performed,
@@ -4026,7 +4029,7 @@ int maria_repair_parallel(HA_CHECK *para
   */
   sort_info.max_records++;
 
-  del=info->state->del;
+  del=share->state.state.del;
 
   if (!(sort_param=(MARIA_SORT_PARAM *)
         my_malloc((uint) share->base.keys *
@@ -4038,8 +4041,8 @@ int maria_repair_parallel(HA_CHECK *para
   }
   total_key_length=0;
   rec_per_key_part= param->new_rec_per_key_part;
-  info->state->records=info->state->del=share->state.split=0;
-  info->state->empty=0;
+  share->state.state.records=share->state.state.del=share->state.split=0;
+  share->state.state.empty=0;
 
   for (i=key=0, istep=1 ; key < share->base.keys ;
        rec_per_key_part+=sort_param[i].keyinfo->keysegs, i+=istep, key++)
@@ -4213,16 +4216,16 @@ int maria_repair_parallel(HA_CHECK *para
     if (param->testflag & T_SAFE_REPAIR)
     {
       /* 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;
       }
     }
-    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;
     /* 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
       new file from now on.
@@ -4232,9 +4235,9 @@ int maria_repair_parallel(HA_CHECK *para
     share->pack.header_length=(ulong) new_header_length;
   }
   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,"Run recovery again without -q");
@@ -4245,7 +4248,7 @@ int maria_repair_parallel(HA_CHECK *para
 
   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) ?
                    MEMMAP_EXTRA_MARGIN : 0);
 #ifdef USE_RELOC
@@ -4260,28 +4263,30 @@ int maria_repair_parallel(HA_CHECK *para
 			       my_errno);
   }
   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,
 			   "Can't change size of indexfile, error: %d",
                             my_errno);
 
   if (!(param->testflag & T_SILENT))
   {
-    if (start_records != info->state->records)
-      printf("Data records: %s\n", llstr(info->state->records,llbuff));
+    if (start_records != share->state.state.records)
+      printf("Data records: %s\n", llstr(share->state.state.records,llbuff));
   }
   if (sort_info.dupp)
     _ma_check_print_warning(param,
                             "%s records have been removed",
                             llstr(sort_info.dupp,llbuff));
   got_error=0;
-
+  /* If invoked by external program that uses thr_lock */
   if (&share->state.state != info->state)
-    memcpy(&share->state.state, info->state, sizeof(*info->state));
+    *info->state= *info->state_start= share->state.state;
 
 err:
+  _ma_reset_state(info);
+
   /*
     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
@@ -4360,7 +4365,7 @@ static int sort_key_read(MARIA_SORT_PARA
 
   if ((error=sort_get_next_record(sort_param)))
     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,
 			 "Key %d - Found too many records; Can't continue",
@@ -4504,7 +4509,7 @@ static int sort_get_next_record(MARIA_SO
           Scan on clean table.
           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;
         flag= _ma_scan_block_record(info, sort_param->record,
                                     info->cur_row.nextpos, 1);
@@ -4542,7 +4547,7 @@ static int sort_get_next_record(MARIA_SO
       }
       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);
       }
       /* Retry only if wrong record, not if disk error */
@@ -4580,8 +4585,8 @@ static int sort_get_next_record(MARIA_SO
       }
       if (!sort_param->fix_datafile && sort_param->master)
       {
-	info->state->del++;
-	info->state->empty+=share->base.pack_reclength;
+	share->state.state.del++;
+	share->state.state.empty+=share->base.pack_reclength;
       }
     }
   case DYNAMIC_RECORD:
@@ -4685,9 +4690,9 @@ static int sort_get_next_record(MARIA_SO
 	  {
 	    if ((block_info.next_filepos != HA_OFFSET_ERROR &&
 		 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 >= info->state->data_file_length))
+		 block_info.prev_filepos >= share->state.state.data_file_length))
 	    {
 	      if (!searching)
 		_ma_check_print_info(param,
@@ -4735,8 +4740,8 @@ static int sort_get_next_record(MARIA_SO
           if (!sort_param->fix_datafile && sort_param->master &&
               (b_type & BLOCK_DELETED))
 	  {
-	    info->state->empty+=block_info.block_len;
-	    info->state->del++;
+	    share->state.state.empty+=block_info.block_len;
+	    share->state.state.del++;
 	    share->state.split++;
 	  }
 	  if (found_record)
@@ -5010,7 +5015,7 @@ int _ma_sort_write_record(MARIA_SORT_PAR
           HA_OFFSET_ERROR)
         DBUG_RETURN(1);
       /* Pointer to end of file */
-      sort_param->filepos= info->state->data_file_length;
+      sort_param->filepos= share->state.state.data_file_length;
       break;
     case STATIC_RECORD:
       if (my_b_write(&info->rec_cache,sort_param->record,
@@ -5089,12 +5094,12 @@ int _ma_sort_write_record(MARIA_SORT_PAR
   }
   if (sort_param->master)
   {
-    info->state->records++;
+    share->state.state.records++;
     if ((param->testflag & T_WRITE_LOOP) &&
-        (info->state->records % WRITE_COUNT) == 0)
+        (share->state.state.records % WRITE_COUNT) == 0)
     {
       char llbuff[22];
-      printf("%s\r", llstr(info->state->records,llbuff));
+      printf("%s\r", llstr(share->state.state.records,llbuff));
       VOID(fflush(stdout));
     }
   }
@@ -5392,7 +5397,7 @@ static int sort_insert_key(MARIA_SORT_PA
   _ma_store_page_used(share, anc_buff, key_block->last_length);
   bzero(anc_buff+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)
     DBUG_RETURN(1);
   _ma_fast_unlock_key_del(info);
@@ -5491,7 +5496,7 @@ static int sort_delete_record(MARIA_SORT
     _ma_check_print_error(param,"Got error %d when deleting record",
                           my_errno);
   row_info->dfile.file= old_file;           /* restore actual value */
-  row_info->state->records--;
+  row_info->s->state.state.records--;
   DBUG_RETURN(error);
 } /* sort_delete_record */
 
@@ -5518,7 +5523,7 @@ int _ma_flush_pending_blocks(MARIA_SORT_
     length= _ma_get_page_used(info->s, key_block->buff);
     if (nod_flag)
       _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);
     if ((filepos= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
         HA_OFFSET_ERROR)
@@ -5753,16 +5758,16 @@ int maria_recreate_table(HA_CHECK *param
   /* We are modifing */
   (*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
   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)
     (*org_info)->s->state.create_time=share.state.create_time;
-  (*org_info)->s->state.unique=(*org_info)->this_unique=
-    share.state.unique;
-  (*org_info)->state->checksum=info.state->checksum;
-  (*org_info)->state->del=info.state->del;
-  (*org_info)->s->state.dellink=share.state.dellink;
-  (*org_info)->state->empty=info.state->empty;
-  (*org_info)->state->data_file_length=info.state->data_file_length;
+  (*org_info)->s->state.unique= (*org_info)->this_unique= share.state.unique;
+  (*org_info)->s->state.state.checksum= info.state->checksum;
+  (*org_info)->s->state.state.del= info.state->del;
+  (*org_info)->s->state.dellink= share.state.dellink;
+  (*org_info)->s->state.state.empty= info.state->empty;
+  (*org_info)->s->state.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 |
                               UPDATE_OPEN_COUNT))
     goto end;
@@ -5813,9 +5818,9 @@ int maria_update_state_info(HA_CHECK *pa
   if (update & UPDATE_STAT)
   {
     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;
-    if (info->state->records)
+    if (share->state.state.records)
     {
       for (i=0; i<key_parts; i++)
       {
@@ -5830,16 +5835,8 @@ int maria_update_state_info(HA_CHECK *pa
     {
       share->state.check_time= (long) time((time_t*) 0);
       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))
       goto err;
     share->changed=0;
@@ -6064,7 +6061,7 @@ void maria_disable_non_unique_index(MARI
   MARIA_KEYDEF    *key=share->keyinfo;
   uint          i;
 
-  DBUG_ASSERT(info->state->records == 0 &&
+  DBUG_ASSERT(share->state.state.records == 0 &&
               (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES));
   for (i=0 ; i < share->base.keys ; i++,key++)
   {
@@ -6148,7 +6145,7 @@ static my_bool create_new_data_handle(MA
     DBUG_RETURN(1);
 
   /* 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 */
   info->s->keypos_to_recpos= new_info->s->keypos_to_recpos;
diff -Nrup a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c
--- a/storage/maria/ma_checkpoint.c	2008-04-04 20:10:49 +03:00
+++ b/storage/maria/ma_checkpoint.c	2008-05-29 18:33:28 +03:00
@@ -1053,6 +1053,14 @@ static int collect_tables(LEX_STRING *st
       }
       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)
     {
       /* maria_close() left us to free the share */
diff -Nrup a/storage/maria/ma_close.c b/storage/maria/ma_close.c
--- a/storage/maria/ma_close.c	2007-12-30 22:40:00 +02:00
+++ b/storage/maria/ma_close.c	2008-05-29 18:33:29 +03:00
@@ -128,6 +128,27 @@ int maria_close(register MARIA_HA *info)
     }
     else
       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(&share->intern_lock);
diff -Nrup a/storage/maria/ma_commit.c b/storage/maria/ma_commit.c
--- a/storage/maria/ma_commit.c	2008-04-03 16:40:19 +03:00
+++ b/storage/maria/ma_commit.c	2008-05-29 18:33:29 +03:00
@@ -49,6 +49,8 @@ int ma_commit(TRN *trn)
     if crash happens between the two, trn will be rolled back which is an
     issue (transaction's updates were made visible to other transactions).
     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.
   */
   res= (translog_write_record(&commit_lsn, LOGREC_COMMIT,
-                              trn, NULL, 0,
-                              sizeof(log_array)/sizeof(log_array[0]),
-                              log_array, NULL, NULL) ||
-        translog_flush(commit_lsn) ||
+                             trn, NULL, 0,
+                             sizeof(log_array)/sizeof(log_array[0]),
+                             log_array, NULL, NULL) |
+        translog_flush(commit_lsn) |
         trnman_commit_trn(trn));
+
+
   /*
     Note: if trnman_commit_trn() fails above, we have already
     written the COMMIT record, so Checkpoint and Recovery will see the
@@ -96,7 +100,6 @@ int maria_commit(MARIA_HA *info)
      @retval #      Error code.
 */
 
-
 int maria_begin(MARIA_HA *info)
 {
   DBUG_ENTER("maria_begin");
@@ -116,3 +119,4 @@ int maria_begin(MARIA_HA *info)
   }
   DBUG_RETURN(0);
 }
+
diff -Nrup a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c
--- a/storage/maria/ma_delete.c	2008-04-10 05:26:12 +03:00
+++ b/storage/maria/ma_delete.c	2008-05-29 18:33:29 +03:00
@@ -111,11 +111,8 @@ int maria_delete(MARIA_HA *info,const uc
   if ((*share->delete_record)(info, record))
     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;
   share->state.changed|= (STATE_NOT_OPTIMIZED_ROWS | STATE_NOT_MOVABLE |
                           STATE_NOT_ZEROFILLED);
diff -Nrup a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c
--- a/storage/maria/ma_delete_all.c	2008-04-03 16:40:19 +03:00
+++ b/storage/maria/ma_delete_all.c	2008-05-29 18:33:29 +03:00
@@ -91,13 +91,12 @@ int maria_delete_all_rows(MARIA_HA *info
   if (_ma_flush_table_files(info, MARIA_FLUSH_DATA|MARIA_FLUSH_INDEX,
                             FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED) ||
       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;
 
   if (_ma_initialize_data_file(share, info->dfile.file))
     goto err;
 
-
   if (log_record)
   {
     /*
@@ -156,14 +155,17 @@ void _ma_reset_status(MARIA_HA *info)
   MARIA_STATE_INFO *state= &share->state;
   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->dellink= HA_OFFSET_ERROR;
   state->sortkey=  (ushort) ~0;
-  info->state->key_file_length= share->base.keystart;
-  info->state->data_file_length= 0;
-  info->state->empty= info->state->key_empty= 0;
-  info->state->checksum= 0;
+  state->state.key_file_length= share->base.keystart;
+  state->state.data_file_length= 0;
+  state->state.empty= state->state.key_empty= 0;
+  state->state.checksum= 0;
+
+  *info->state= state->state;
 
   /* Drop the delete key chain. */
   state->key_del= HA_OFFSET_ERROR;
diff -Nrup a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c
--- a/storage/maria/ma_dynrec.c	2008-04-03 16:40:19 +03:00
+++ b/storage/maria/ma_dynrec.c	2008-05-29 18:33:29 +03:00
@@ -136,7 +136,7 @@ size_t _ma_mmap_pread(MARIA_HA *info, uc
 		      size_t Count, my_off_t offset, myf MyFlags)
 {
   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);
 
   /*
@@ -149,13 +149,13 @@ size_t _ma_mmap_pread(MARIA_HA *info, uc
   if (info->s->mmaped_length >= 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);
     return 0;
   }
   else
   {
-    if (info->s->concurrent_insert)
+    if (info->s->lock_key_trees)
       rw_unlock(&info->s->mmap_lock);
     return my_pread(info->dfile.file, Buffer, Count, offset, MyFlags);
   }
@@ -191,7 +191,7 @@ size_t _ma_mmap_pwrite(MARIA_HA *info, c
 		       size_t Count, my_off_t offset, myf MyFlags)
 {
   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);
 
   /*
@@ -204,14 +204,14 @@ size_t _ma_mmap_pwrite(MARIA_HA *info, c
   if (info->s->mmaped_length >= offset + 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);
     return 0;
   }
   else
   {
     info->s->nonmmaped_inserts++;
-    if (info->s->concurrent_insert)
+    if (info->s->lock_key_trees)
       rw_unlock(&info->s->mmap_lock);
     return my_pwrite(info->dfile.file, Buffer, Count, offset, MyFlags);
   }
diff -Nrup a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c
--- a/storage/maria/ma_extra.c	2008-01-18 00:59:06 +02:00
+++ b/storage/maria/ma_extra.c	2008-05-29 18:33:29 +03:00
@@ -105,7 +105,7 @@ int maria_extra(MARIA_HA *info, enum ha_
       cache_size= (extra_arg ? *(ulong*) extra_arg :
 		   my_default_record_cache_size);
       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),
 			  READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
 			  MYF(share->write_flag & MY_WAIT_IF_FULL))))
@@ -113,7 +113,7 @@ int maria_extra(MARIA_HA *info, enum ha_
 	info->opt_flag|= READ_CACHE_USED;
 	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;
     }
     break;
@@ -124,7 +124,7 @@ int maria_extra(MARIA_HA *info, enum ha_
 		      (pbool) (info->lock_type != F_UNLCK),
 		      (pbool) test(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;
     }
     break;
@@ -143,7 +143,7 @@ int maria_extra(MARIA_HA *info, enum ha_
 	  (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
 	!share->state.header.uniques)
       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),
 			  MYF(share->write_flag & MY_WAIT_IF_FULL))))
       {
@@ -258,7 +258,8 @@ int maria_extra(MARIA_HA *info, enum ha_
 	  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;
         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
                           enum flush_type flush_type_for_data,
                           enum flush_type flush_type_for_index)
 {
+  int error= 0;
   MARIA_SHARE *share= info->s;
   /* flush data file first because it's more critical */
   if (flush_data_or_index & MARIA_FLUSH_DATA)
   {
     if ((info->opt_flag & WRITE_CACHE_USED) &&
+        flush_type_for_data != FLUSH_IGNORE_CHANGED &&
         flush_io_cache(&info->rec_cache))
-      goto err;
+      error= 1;
     if (share->data_file_type == BLOCK_RECORD)
     {
-      if(_ma_bitmap_flush(share) ||
-         flush_pagecache_blocks(share->pagecache, &info->dfile,
-                                flush_type_for_data))
-        goto err;
+      if (flush_type_for_data != FLUSH_IGNORE_CHANGED)
+      {
+        if (_ma_bitmap_flush(share))
+          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) &&
       flush_pagecache_blocks(share->pagecache, &share->kfile,
                              flush_type_for_index))
-    goto err;
-  return 0;
-err:
+    error= 1;
+  if (!error)
+    return 0;
+
   maria_print_error(info->s, HA_ERR_CRASHED);
   maria_mark_crashed(info);
   return 1;
diff -Nrup a/storage/maria/ma_info.c b/storage/maria/ma_info.c
--- a/storage/maria/ma_info.c	2008-01-13 00:30:36 +02:00
+++ b/storage/maria/ma_info.c	2008-05-29 18:33:29 +03:00
@@ -50,15 +50,15 @@ int maria_status(MARIA_HA *info, registe
   if (flag & HA_STATUS_VARIABLE)
   {
     x->records	 	= info->state->records;
-    x->deleted	 	= info->state->del;
-    x->delete_length	= info->state->empty;
-    x->data_file_length	=info->state->data_file_length;
-    x->index_file_length=info->state->key_file_length;
+    x->deleted	 	= share->state.state.del;
+    x->delete_length	= share->state.state.empty;
+    x->data_file_length	= share->state.state.data_file_length;
+    x->index_file_length= share->state.state.key_file_length;
 
     x->keys	 	= share->state.header.keys;
     x->check_time	= share->state.check_time;
     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;
   }
   if (flag & HA_STATUS_ERRKEY)
diff -Nrup a/storage/maria/ma_init.c b/storage/maria/ma_init.c
--- a/storage/maria/ma_init.c	2008-04-04 20:10:50 +03:00
+++ b/storage/maria/ma_init.c	2008-05-29 18:33:29 +03:00
@@ -20,6 +20,25 @@
 #include "ma_blockrec.h"
 #include "trnman_public.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
@@ -42,8 +61,11 @@ int maria_init(void)
     maria_inited= TRUE;
     pthread_mutex_init(&THR_LOCK_maria,MY_MUTEX_INIT_SLOW);
     _ma_init_block_record_data();
+    trnman_end_trans_hook= _ma_trnman_end_trans_hook;
     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;
 }
 
@@ -73,5 +95,6 @@ void maria_end(void)
     end_pagecache(maria_pagecache, TRUE);
     ma_control_file_end();
     pthread_mutex_destroy(&THR_LOCK_maria);
+    hash_free(&maria_stored_state);
   }
 }
diff -Nrup a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c
--- a/storage/maria/ma_key_recover.c	2008-04-03 16:40:20 +03:00
+++ b/storage/maria/ma_key_recover.c	2008-05-29 18:33:29 +03:00
@@ -626,9 +626,9 @@ uint _ma_apply_redo_index_new_page(MARIA
       cmp_translog_addr(lsn, share->state.is_of_horizon) >= 0)
     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;
     info->keyread_buff_used= 1;
     unlock_method= PAGECACHE_LOCK_WRITE;
@@ -1138,7 +1138,7 @@ void _ma_unlock_key_del(MARIA_HA *info)
     MARIA_SHARE *share= info->s;
     pthread_mutex_lock(&share->intern_lock);
     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_cond_signal(&share->intern_cond);
   }
diff -Nrup a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c
--- a/storage/maria/ma_locking.c	2008-04-10 05:26:13 +03:00
+++ b/storage/maria/ma_locking.c	2008-05-29 18:33:29 +03:00
@@ -14,10 +14,9 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 /*
-  locking of isam-tables.
-  reads info from a isam-table. Must be first request before doing any furter
-  calls to any isamfunktion.  Is used to allow many process use the same
-  isamdatabase.
+  Locking of Maria-tables.
+  Must be first request before doing any furter calls to any Maria function.
+  Is used to allow many process use the same non transactional Maria table
 */
 
 #include "ma_ftdefs.h"
@@ -57,12 +56,14 @@ int maria_lock_database(MARIA_HA *info, 
       if (info->lock_type == F_RDLCK)
       {
 	count= --share->r_locks;
-        _ma_restore_status(info);
+        if (share->lock_restore_status)
+          (*share->lock_restore_status)(info);
       }
       else
       {
 	count= --share->w_locks;
-        _ma_update_status(info);
+        if (share->lock.update_status)
+          (*share->lock.update_status)(info);
       }
       --share->tot_locks;
       if (info->lock_type == F_WRLCK && !share->w_locks)
@@ -91,16 +92,16 @@ int maria_lock_database(MARIA_HA *info, 
 	if (share->changed && !share->w_locks)
 	{
 #ifdef HAVE_MMAP
-          if ((info->s->mmaped_length !=
-               info->s->state.state.data_file_length) &&
-              (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
+          if ((share->mmaped_length !=
+               share->state.state.data_file_length) &&
+              (share->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
           {
-            if (info->s->concurrent_insert)
-              rw_wrlock(&info->s->mmap_lock);
-            _ma_remap_file(info, info->s->state.state.data_file_length);
-            info->s->nonmmaped_inserts= 0;
-            if (info->s->concurrent_insert)
-              rw_unlock(&info->s->mmap_lock);
+            if (share->lock_key_trees)
+              rw_wrlock(&share->mmap_lock);
+            _ma_remap_file(info, share->state.state.data_file_length);
+            share->nonmmaped_inserts= 0;
+            if (share->lock_key_trees)
+              rw_unlock(&share->mmap_lock);
           }
 #endif
 #ifdef EXTERNAL_LOCKING
@@ -212,7 +213,7 @@ int maria_lock_database(MARIA_HA *info, 
       VOID(_ma_test_if_changed(info));
 
       info->lock_type=lock_type;
-      info->invalidator=info->s->invalidator;
+      info->invalidator=share->invalidator;
       share->w_locks++;
       share->tot_locks++;
       break;
@@ -242,128 +243,6 @@ int maria_lock_database(MARIA_HA *info, 
 
 
 /****************************************************************************
-  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
 ****************************************************************************/
 
@@ -389,7 +268,7 @@ int _ma_readinfo(register MARIA_HA *info
     }
     if (check_keybuffer)
       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)
   {
diff -Nrup a/storage/maria/ma_open.c b/storage/maria/ma_open.c
--- a/storage/maria/ma_open.c	2008-04-10 05:26:13 +03:00
+++ b/storage/maria/ma_open.c	2008-05-29 18:33:29 +03:00
@@ -91,6 +91,7 @@ static MARIA_HA *maria_clone_internal(MA
   int save_errno;
   uint errpos;
   MARIA_HA info,*m_info;
+  MARIA_STATUS_INFO *state_dummy;
   my_bitmap_map *changed_fields_bitmap;
   DBUG_ENTER("maria_clone_internal");
 
@@ -120,6 +121,7 @@ static MARIA_HA *maria_clone_internal(MA
                        share->have_rtree ? 1024 : 0,
                        &changed_fields_bitmap,
                        bitmap_buffer_size(share->base.fields),
+                       &state_dummy, sizeof(*state_dummy),
 		       NullS))
     goto err;
   errpos= 6;
@@ -176,9 +178,18 @@ static MARIA_HA *maria_clone_internal(MA
       maria_delay_key_write)
     share->delay_key_write=1;
 
-  info.state= &share->state.state;	/* Change global values by default */
   if (!share->base.born_transactional)   /* For transactional ones ... */
+  {
     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);
 
   /* Allocate buffer for one record */
@@ -759,7 +770,31 @@ MARIA_HA *maria_open(const char *name, i
     _ma_setup_functions(share);
     if ((*share->once_init)(share, info.dfile.file))
       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
     thr_lock_init(&share->lock);
     VOID(pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST));
@@ -774,22 +809,24 @@ MARIA_HA *maria_open(const char *name, i
     }
     else if (maria_concurrent_insert)
     {
-      share->concurrent_insert=
+      share->non_transactional_concurrent_insert=
 	((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
                             HA_OPTION_COMPRESS_RECORD |
                             HA_OPTION_TEMP_COMPRESS_RECORD)) ||
 	 (open_flags & HA_OPEN_TMP_TABLE) ||
-         (share->data_file_type == BLOCK_RECORD &&
-          !share->now_transactional) ||
+         share->data_file_type == BLOCK_RECORD ||
 	 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)
         {
           share->lock.get_status=    _ma_block_get_status;
           share->lock.update_status= _ma_block_update_status;
           share->lock.check_status=  _ma_block_check_status;
           share->lock.allow_multiple_concurrent_insert= 1;
+          share->lock_restore_status= 0;
         }
         else
         {
@@ -798,6 +835,7 @@ MARIA_HA *maria_open(const char *name, i
           share->lock.update_status= _ma_update_status;
           share->lock.restore_status=_ma_restore_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;
   MARIA_SHARE *share= info->s;
+  DBUG_ENTER("maria_enable_indexes");
 
   if ((share->state.state.data_file_length !=
        (share->data_file_type == BLOCK_RECORD ? share->block_size : 0)) ||
       (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);
     error= HA_ERR_CRASHED;
   }
   else
     maria_set_all_keys_active(share->state.key_map, share->base.keys);
-  return error;
+  DBUG_RETURN(error);
 }
 
 
diff -Nrup a/storage/maria/ma_page.c b/storage/maria/ma_page.c
--- a/storage/maria/ma_page.c	2008-04-03 16:40:20 +03:00
+++ b/storage/maria/ma_page.c	2008-05-29 18:33:29 +03:00
@@ -101,13 +101,13 @@ int _ma_write_keypage(register MARIA_HA 
     uint page_length, nod;
     _ma_get_used_and_nod(share, buff, page_length, nod);
     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)))
     {
       DBUG_PRINT("error",("Trying to write inside key status region: "
                           "key_start: %lu  length: %lu  page: %lu",
                           (long) share->base.keystart,
-                          (long) info->state->key_file_length,
+                          (long) share->state.state.key_file_length,
                           (long) pos));
       my_errno=EINVAL;
       DBUG_ASSERT(0);
@@ -299,14 +299,18 @@ my_off_t _ma_new(register MARIA_HA *info
 
   if (_ma_lock_key_del(info, 1))
   {
-    if (info->state->key_file_length >=
-	share->base.max_key_file_length - block_size)
+    pthread_mutex_lock(&share->intern_lock);
+    pos= share->state.state.key_file_length;
+    if (pos >= share->base.max_key_file_length - block_size)
     {
       my_errno=HA_ERR_INDEX_FILE_FULL;
+      pthread_mutex_unlock(&share->intern_lock);
       DBUG_RETURN(HA_OFFSET_ERROR);
     }
-    pos= info->state->key_file_length;
-    info->state->key_file_length+= block_size;
+    share->state.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)->write_lock= PAGECACHE_LOCK_WRITE;
   }
@@ -337,7 +341,7 @@ my_off_t _ma_new(register MARIA_HA *info
                   (current_key_del != 0) &&
                   ((current_key_del == HA_OFFSET_ERROR) ||
                    (current_key_del <=
-                    (info->state->key_file_length - block_size))));
+                    (share->state.state.key_file_length - block_size))));
 #endif
     }
 
diff -Nrup a/storage/maria/ma_range.c b/storage/maria/ma_range.c
--- a/storage/maria/ma_range.c	2007-12-10 02:31:58 +02:00
+++ b/storage/maria/ma_range.c	2008-05-29 18:33:29 +03:00
@@ -48,6 +48,7 @@ ha_rows maria_records_in_range(MARIA_HA 
                             key_range *max_key)
 {
   ha_rows start_pos,end_pos,res;
+  MARIA_SHARE *share= info->s;
   DBUG_ENTER("maria_records_in_range");
 
   if ((inx = _ma_check_index(info,inx)) < 0)
@@ -56,10 +57,10 @@ ha_rows maria_records_in_range(MARIA_HA 
   if (fast_ma_readinfo(info))
     DBUG_RETURN(HA_POS_ERROR);
   info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
-  if (info->s->concurrent_insert)
-    rw_rdlock(&info->s->key_root_lock[inx]);
+  if (share->lock_key_trees)
+    rw_rdlock(&share->key_root_lock[inx]);
 
-  switch(info->s->keyinfo[inx].key_alg){
+  switch(share->keyinfo[inx].key_alg){
 #ifdef HAVE_RTREE_KEYS
   case HA_KEY_ALG_RTREE:
   {
@@ -81,7 +82,7 @@ ha_rows maria_records_in_range(MARIA_HA 
       res= HA_POS_ERROR;
       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,
                                 min_key->key, min_key->keypart_map,
                                 (HA_KEYSEG**) 0);
@@ -107,8 +108,8 @@ ha_rows maria_records_in_range(MARIA_HA 
       res=HA_POS_ERROR;
   }
 
-  if (info->s->concurrent_insert)
-    rw_unlock(&info->s->key_root_lock[inx]);
+  if (share->lock_key_trees)
+    rw_unlock(&share->key_root_lock[inx]);
   fast_ma_writeinfo(info);
 
   /**
diff -Nrup a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
--- a/storage/maria/ma_recovery.c	2008-04-04 20:10:50 +03:00
+++ b/storage/maria/ma_recovery.c	2008-05-29 18:33:30 +03:00
@@ -2726,6 +2726,13 @@ static void prepare_table_for_close(MARI
     share->state.is_of_horizon= horizon;
     _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
     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(M
   if ((share->now_transactional= share->base.born_transactional))
   {
     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)
     {
       /*
diff -Nrup a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c
--- a/storage/maria/ma_rkey.c	2007-12-10 02:31:58 +02:00
+++ b/storage/maria/ma_rkey.c	2008-05-29 18:33:30 +03:00
@@ -69,7 +69,7 @@ int maria_rkey(MARIA_HA *info, uchar *bu
 
   if (fast_ma_readinfo(info))
     goto err;
-  if (share->concurrent_insert)
+  if (share->lock_key_trees)
     rw_rdlock(&share->key_root_lock[inx]);
 
   nextflag=maria_read_vec[search_flag];
@@ -93,7 +93,7 @@ int maria_rkey(MARIA_HA *info, uchar *bu
     if (!_ma_search(info, keyinfo, key_buff, use_key_length,
                     maria_read_vec[search_flag],
                     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
@@ -156,7 +156,7 @@ int maria_rkey(MARIA_HA *info, uchar *bu
       }
     }
   }
-  if (share->concurrent_insert)
+  if (share->lock_key_trees)
     rw_unlock(&share->key_root_lock[inx]);
 
   if (info->cur_row.lastpos == HA_OFFSET_ERROR)
diff -Nrup a/storage/maria/ma_rnext.c b/storage/maria/ma_rnext.c
--- a/storage/maria/ma_rnext.c	2007-07-02 20:45:01 +03:00
+++ b/storage/maria/ma_rnext.c	2008-05-29 18:33:30 +03:00
@@ -39,7 +39,7 @@ int maria_rnext(MARIA_HA *info, uchar *b
 
   if (fast_ma_readinfo(info))
     DBUG_RETURN(my_errno);
-  if (info->s->concurrent_insert)
+  if (info->s->lock_key_trees)
     rw_rdlock(&info->s->key_root_lock[inx]);
   changed= _ma_test_if_changed(info);
   if (!flag)
@@ -82,7 +82,7 @@ int maria_rnext(MARIA_HA *info, uchar *b
     }
   }
 
-  if (info->s->concurrent_insert)
+  if (info->s->non_transactional_concurrent_insert)
   {
     if (!error)
     {
diff -Nrup a/storage/maria/ma_rnext_same.c b/storage/maria/ma_rnext_same.c
--- a/storage/maria/ma_rnext_same.c	2008-04-01 17:57:27 +03:00
+++ b/storage/maria/ma_rnext_same.c	2008-05-29 18:33:30 +03:00
@@ -39,11 +39,10 @@ int maria_rnext_same(MARIA_HA *info, uch
   if (fast_ma_readinfo(info))
     DBUG_RETURN(my_errno);
 
-  if (info->s->concurrent_insert)
+  if (info->s->lock_key_trees)
     rw_rdlock(&info->s->key_root_lock[inx]);
 
-  switch (keyinfo->key_alg)
-  {
+  switch (keyinfo->key_alg) {
 #ifdef HAVE_RTREE_KEYS
     case HA_KEY_ALG_RTREE:
       if ((error=maria_rtree_find_next(info,inx,
@@ -79,11 +78,12 @@ int maria_rnext_same(MARIA_HA *info, uch
           break;
         }
         /* 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;
       }
   }
-  if (info->s->concurrent_insert)
+  if (info->s->lock_key_trees)
     rw_unlock(&info->s->key_root_lock[inx]);
 	/* Don't clear if database-changed */
   info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
diff -Nrup a/storage/maria/ma_rprev.c b/storage/maria/ma_rprev.c
--- a/storage/maria/ma_rprev.c	2007-12-10 02:31:58 +02:00
+++ b/storage/maria/ma_rprev.c	2008-05-29 18:33:30 +03:00
@@ -39,7 +39,7 @@ int maria_rprev(MARIA_HA *info, uchar *b
   if (fast_ma_readinfo(info))
     DBUG_RETURN(my_errno);
   changed= _ma_test_if_changed(info);
-  if (share->concurrent_insert)
+  if (share->lock_key_trees)
     rw_rdlock(&share->key_root_lock[inx]);
   if (!flag)
     error= _ma_search_last(info, share->keyinfo+inx,
@@ -52,7 +52,7 @@ int maria_rprev(MARIA_HA *info, uchar *b
     error= _ma_search(info,share->keyinfo+inx,info->lastkey,
 		     USE_WHOLE_KEY, flag, share->state.key_root[inx]);
 
-  if (share->concurrent_insert)
+  if (share->non_transactional_concurrent_insert)
   {
     if (!error)
     {
@@ -66,8 +66,9 @@ int maria_rprev(MARIA_HA *info, uchar *b
 	  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_PREV_FOUND;
   if (error)
diff -Nrup a/storage/maria/ma_rsame.c b/storage/maria/ma_rsame.c
--- a/storage/maria/ma_rsame.c	2008-02-21 02:43:04 +02:00
+++ b/storage/maria/ma_rsame.c	2008-05-29 18:33:30 +03:00
@@ -54,12 +54,12 @@ int maria_rsame(MARIA_HA *info, uchar *r
     info->lastinx=inx;
     info->lastkey_length= _ma_make_key(info,(uint) inx,info->lastkey,record,
 				      info->cur_row.lastpos);
-    if (info->s->concurrent_insert)
+    if (info->s->lock_key_trees)
       rw_rdlock(&info->s->key_root_lock[inx]);
     VOID(_ma_search(info,info->s->keyinfo+inx,info->lastkey, USE_WHOLE_KEY,
 		    SEARCH_SAME,
 		    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]);
   }
 
diff -Nrup a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
--- a/storage/maria/ma_sort.c	2008-04-01 17:57:28 +03:00
+++ b/storage/maria/ma_sort.c	2008-05-29 18:33:30 +03:00
@@ -532,9 +532,10 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM 
       }
       if (!got_error && param->testflag & T_STATISTICS)
         maria_update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique,
-                         param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
-                         sinfo->notnull: NULL,
-                         (ulonglong) info->state->records);
+                               param->stats_method ==
+                               MI_STATS_METHOD_IGNORE_NULLS ?
+                               sinfo->notnull : NULL,
+                               (ulonglong) share->state.state.records);
     }
     my_free((uchar*) sinfo->sort_keys,MYF(0));
     my_free(sinfo->rec_buff, MYF(MY_ALLOW_ZERO_PTR));
diff -Nrup a/storage/maria/ma_state.c b/storage/maria/ma_state.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/storage/maria/ma_state.c	2008-05-29 18:33:31 +03:00
@@ -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;
+}
diff -Nrup a/storage/maria/ma_state.h b/storage/maria/ma_state.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/storage/maria/ma_state.h	2008-05-29 18:33:31 +03:00
@@ -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);
diff -Nrup a/storage/maria/ma_static.c b/storage/maria/ma_static.c
--- a/storage/maria/ma_static.c	2008-01-26 23:03:22 +02:00
+++ b/storage/maria/ma_static.c	2008-05-29 18:33:30 +03:00
@@ -52,6 +52,7 @@ PAGECACHE maria_log_pagecache_var;
 PAGECACHE *maria_log_pagecache= &maria_log_pagecache_var;
 MY_TMPDIR *maria_tmpdir;                        /* Tempdir for redo */
 char *maria_data_root;
+HASH maria_stored_state;
 
 /**
    @brief when transactionality does not matter we can use this transaction
diff -Nrup a/storage/maria/ma_update.c b/storage/maria/ma_update.c
--- a/storage/maria/ma_update.c	2008-01-31 03:06:01 +02:00
+++ b/storage/maria/ma_update.c	2008-05-29 18:33:30 +03:00
@@ -42,7 +42,7 @@ int maria_update(register MARIA_HA *info
   {
     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);
   }
@@ -144,24 +144,12 @@ int maria_update(register MARIA_HA *info
     */
     info->cur_row.checksum= (*share->calc_checksum)(info, newrec);
     info->new_row.checksum= (*share->calc_checksum)(info, oldrec);
-    if (!share->now_transactional)
-      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));
-    org_split=	     share->state.split;
-    org_delete_link= share->state.dellink;
-    if ((*share->update_record)(info, pos, oldrec, newrec))
-      goto err;
+    info->state->checksum+= info->cur_row.checksum - info->new_row.checksum;
   }
+
+  if ((*share->update_record)(info, pos, oldrec, newrec))
+    goto err;
+
   if (auto_key_changed & !share->now_transactional)
   {
     const HA_KEYSEG *keyseg= share->keyinfo[share->base.auto_key-1].seg;
@@ -171,8 +159,7 @@ int maria_update(register MARIA_HA *info
   }
 
   /*
-    We can't yet have HA_STATE_AKTIV here, as block_record dosn't support
-    it
+    We can't yet have HA_STATE_AKTIV here, as block_record dosn't support it
   */
   info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed);
   share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
diff -Nrup a/storage/maria/ma_write.c b/storage/maria/ma_write.c
--- a/storage/maria/ma_write.c	2008-04-10 05:26:13 +03:00
+++ b/storage/maria/ma_write.c	2008-05-29 18:33:30 +03:00
@@ -70,6 +70,10 @@ static my_bool _ma_log_key_middle(MARIA_
 
 /*
   @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,
@@ -97,7 +101,7 @@ int maria_write(MARIA_HA *info, uchar *r
   int save_errno;
   MARIA_RECORD_POS filepos;
   uchar *buff;
-  my_bool lock_tree= share->concurrent_insert;
+  my_bool lock_tree= share->lock_key_trees;
   my_bool fatal_error;
   DBUG_ENTER("maria_write");
   DBUG_PRINT("enter",("index_file: %d  data_file: %d",
@@ -116,12 +120,12 @@ int maria_write(MARIA_HA *info, uchar *r
 
   if (share->base.reloc == (ha_rows) 1 &&
       share->base.records == (ha_rows) 1 &&
-      info->state->records == (ha_rows) 1)
+      share->state.state.records == (ha_rows) 1)
   {						/* System file */
     my_errno=HA_ERR_RECORD_FILE_FULL;
     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;
     goto err2;
@@ -204,8 +208,7 @@ int maria_write(MARIA_HA *info, uchar *r
   {
     if ((*share->write_record)(info,record))
       goto err;
-    if (!share->now_transactional)
-      info->state->checksum+= info->cur_row.checksum;
+    info->state->checksum+= info->cur_row.checksum;
   }
   if (!share->now_transactional)
   {
@@ -216,8 +219,8 @@ int maria_write(MARIA_HA *info, uchar *r
       set_if_bigger(share->state.auto_increment,
                     ma_retrieve_auto_increment(key, keyseg->type));
     }
-    info->state->records++;
   }
+  info->state->records++;
   info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
 		 HA_STATE_ROW_CHANGED);
   share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
@@ -578,7 +581,7 @@ static int w_search(register MARIA_HA *i
   if (flag == 0)
   {
     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);
     if (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_FR
 
   switch (mode) {
   case free_init:
-    if (share->concurrent_insert)
+    if (share->lock_key_trees)
     {
       rw_wrlock(&share->key_root_lock[param->keynr]);
       share->keyinfo[param->keynr].version++;
@@ -1534,7 +1537,7 @@ static int keys_free(uchar *key, TREE_FR
     return _ma_ck_write_btree(param->info, param->keynr, lastkey,
                               keylen - share->rec_reflength);
   case free_end:
-    if (share->concurrent_insert)
+    if (share->lock_key_trees)
       rw_unlock(&share->key_root_lock[param->keynr]);
     return 0;
   }
@@ -1613,7 +1616,7 @@ void maria_flush_bulk_insert(MARIA_HA *i
   }
 }
 
-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");
   if (info->bulk_insert)
@@ -1621,11 +1624,15 @@ void maria_end_bulk_insert(MARIA_HA *inf
     uint 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]);
+      }
     }
     my_free(info->bulk_insert, MYF(0));
-    info->bulk_insert=0;
+    info->bulk_insert= 0;
   }
   DBUG_VOID_RETURN;
 }
diff -Nrup a/storage/maria/maria_def.h b/storage/maria/maria_def.h
--- a/storage/maria/maria_def.h	2008-04-10 05:26:33 +03:00
+++ b/storage/maria/maria_def.h	2008-05-29 18:33:30 +03:00
@@ -25,8 +25,10 @@
 #else
 #include <my_no_pthread.h>
 #endif
+#include <hash.h>
 #include "ma_loghandler.h"
 #include "ma_control_file.h"
+#include "ma_state.h"
 
 /* For testing recovery */
 #ifdef TO_BE_REMOVED
@@ -51,17 +53,6 @@ struct st_transaction;
 
 #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
 {
   struct
@@ -269,8 +260,8 @@ typedef struct st_maria_share
 {					/* Shared between opens */
   MARIA_STATE_INFO state;
   MARIA_BASE_INFO base;
-  MARIA_KEYDEF ft2_keyinfo;		/* Second-level ft-key
-						   definition */
+  MARIA_STATE_HISTORY *state_history;
+  MARIA_KEYDEF ft2_keyinfo;		/* Second-level ft-key definition */
   MARIA_KEYDEF *keyinfo;		/* Key definitions */
   MARIA_UNIQUEDEF *uniqueinfo;		/* unique definitions */
   HA_KEYSEG *keyparts;			/* key part info */
@@ -356,6 +347,7 @@ typedef struct st_maria_share
   File data_file;			/* Shared data file */
   int mode;				/* mode of file on open */
   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 block_size;			/* block_size of keyfile & data file*/
   /* 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 */
     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 have_rtree;
   /**
@@ -383,6 +377,7 @@ typedef struct st_maria_share
   my_bool used_key_del;                         /* != 0 if key_del is locked */
 #ifdef THREAD
   THR_LOCK lock;
+  void (*lock_restore_status)(void *);
   pthread_mutex_t intern_lock;		/* Locking for use with _locking */
   pthread_cond_t intern_cond;
   rw_lock_t *key_root_lock;
@@ -461,7 +456,8 @@ struct st_maria_handler
 {
   MARIA_SHARE *s;			/* Shared between open:s */
   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 new_row;			/* Storage for a row during update */
   MARIA_BLOCK_SCAN scan, *scan_save;
@@ -733,7 +729,7 @@ extern uint maria_quick_table_bits;
 extern char *maria_data_root;
 extern uchar maria_zero_string[];
 extern my_bool maria_inited;
-
+extern HASH maria_stored_state;
 
 /* This is used by _ma_calc_xxx_key_length och _ma_store_key */
 typedef struct st_maria_s_param
@@ -1048,6 +1044,7 @@ 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_restore_status(void *param);
 void _ma_reset_status(MARIA_HA *maria);
 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);
diff -Nrup a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c
--- a/storage/maria/maria_pack.c	2008-04-10 05:26:33 +03:00
+++ b/storage/maria/maria_pack.c	2008-05-29 18:33:30 +03:00
@@ -166,10 +166,10 @@ static int flush_buffer(ulong neaded_len
 static void end_file_buffer(void);
 static void write_bits(ulonglong value, uint bits);
 static void flush_bits(void);
-static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,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,
-			  ha_checksum crc);
+static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,
+                      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, ha_checksum crc);
 static int mrg_close(PACK_MRG_INFO *mrg);
 static int mrg_rrnd(PACK_MRG_INFO *info,uchar *buf);
 static void mrg_reset(PACK_MRG_INFO *mrg);
@@ -2998,7 +2998,7 @@ static int save_state(MARIA_HA *isam_fil
   for (key=0 ; key < share->base.keys ; key++)
     share->state.key_root[key]= 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->state.open_count=0;
   share->global_changed=0;
diff -Nrup a/storage/maria/trnman.c b/storage/maria/trnman.c
--- a/storage/maria/trnman.c	2008-04-10 05:26:33 +03:00
+++ b/storage/maria/trnman.c	2008-05-29 18:33:30 +03:00
@@ -51,6 +51,10 @@ static TRN **short_trid_to_active_trn;
 
 /* locks for short_trid_to_active_trn and 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
@@ -78,6 +82,16 @@ void trnman_reset_locked_tables(TRN *trn
 }
 
 
+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
     Just as short_id doubles as loid, this function doubles as
@@ -325,6 +339,7 @@ TRN *trnman_new_trn(pthread_mutex_t *mut
 
   trn->commit_trid= 0;
   trn->rec_lsn= trn->undo_lsn= trn->first_undo_lsn= 0;
+  trn->used_tables= 0;
 
   trn->locks.mutex= mutex;
   trn->locks.cond= cond;
@@ -342,6 +357,9 @@ TRN *trnman_new_trn(pthread_mutex_t *mut
   */
   set_short_trid(trn);
 
+  DBUG_PRINT("exit", ("trn: x%lx  trid: 0x%lu",
+                      (ulong) trn, (ulong) trn->trid));
+
   DBUG_RETURN(trn);
 }
 
@@ -362,7 +380,7 @@ TRN *trnman_new_trn(pthread_mutex_t *mut
     0  ok
     1  error
 */
-int trnman_end_trn(TRN *trn, my_bool commit)
+my_bool trnman_end_trn(TRN *trn, my_bool commit)
 {
   int res= 1;
   TRN *free_me= 0;
@@ -435,8 +453,7 @@ int trnman_end_trn(TRN *trn, my_bool com
   if (res)
   {
     /*
-      res == 1 means the condition in the if() above
-      was false.
+      res == 1 means the condition in the if() above was false.
       res == -1 means lf_hash_insert failed
     */
     trn->next= free_me;
@@ -446,8 +463,10 @@ int trnman_end_trn(TRN *trn, my_bool com
   {
     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--;
-  DBUG_PRINT("info", ("pthread_mutex_unlock LOCK_trn_list"));
   pthread_mutex_unlock(&LOCK_trn_list);
 
   /* the rest is done outside of a critical section */
@@ -764,8 +783,29 @@ 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.
 */
+
 TrID trnman_get_max_trid()
 {
   TrID id;
@@ -775,4 +815,40 @@ TrID trnman_get_max_trid()
   id= global_trid_generator;
   pthread_mutex_unlock(&LOCK_trn_list);
   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;
 }
diff -Nrup a/storage/maria/trnman.h b/storage/maria/trnman.h
--- a/storage/maria/trnman.h	2007-07-02 20:45:02 +03:00
+++ b/storage/maria/trnman.h	2008-05-29 18:33:30 +03:00
@@ -42,9 +42,10 @@ C_MODE_START
 struct st_transaction
 {
   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;
-  TRN                 *next, *prev;
   LSN		       rec_lsn, undo_lsn;
   LSN_WITH_FLAGS       first_undo_lsn;
   uint                 locked_tables;
diff -Nrup a/storage/maria/trnman_public.h b/storage/maria/trnman_public.h
--- a/storage/maria/trnman_public.h	2008-04-04 20:10:50 +03:00
+++ b/storage/maria/trnman_public.h	2008-05-29 18:33:30 +03:00
@@ -33,11 +33,13 @@ typedef struct st_transaction TRN;
 
 extern uint trnman_active_transactions, trnman_allocated_transactions;
 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);
 void trnman_destroy(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_abort_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);
 TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid);
 TRN *trnman_get_any_trn(void);
+TrID trnman_get_min_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_store(dst, id) int6store(dst,id)
 #define transid_korr(P) uint6korr(P)
diff -Nrup a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
--- a/storage/myisam/ha_myisam.cc	2008-02-05 17:08:00 +02:00
+++ b/storage/myisam/ha_myisam.cc	2008-05-29 18:33:31 +03:00
@@ -1511,12 +1511,12 @@ void ha_myisam::start_bulk_insert(ha_row
     != 0  Error
 */
 
-int ha_myisam::end_bulk_insert()
+int ha_myisam::end_bulk_insert(bool abort)
 {
   mi_end_bulk_insert(file);
   int err=mi_extra(file, HA_EXTRA_NO_CACHE, 0);
-  return err ? err : can_enable_indexes ?
-                     enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE) : 0;
+  return (err || abort ? err : can_enable_indexes ?
+          enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE) : 0);
 }
 
 
diff -Nrup a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
--- a/storage/myisam/ha_myisam.h	2007-12-18 16:18:14 +02:00
+++ b/storage/myisam/ha_myisam.h	2008-05-29 18:33:31 +03:00
@@ -107,7 +107,7 @@ class ha_myisam: public handler
   int enable_indexes(uint mode);
   int indexes_are_disabled(void);
   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);
   void update_create_info(HA_CREATE_INFO *create_info);
   int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
Thread
bk commit into maria tree (monty:1.2629)monty29 May