[Commits] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2945)

Michael Widenius monty at askmonty.org
Tue Sep 28 16:05:50 EEST 2010


#At lp:maria based on revid:igor at askmonty.org-20100926222257-qtynyyogm3esvrlv

 2945 Michael Widenius	2010-09-28
      Merge with 1.0.11-7 Pre-GA - 2010-09-09
      Updated results for failing test cases (In all cases the estimated number of rows was different)
      modified:
        mysql-test/suite/pbxt/r/negation_elimination.result
        mysql-test/suite/pbxt/r/select.result
        storage/pbxt/ChangeLog
        storage/pbxt/src/Makefile.am
        storage/pbxt/src/cache_xt.cc
        storage/pbxt/src/cache_xt.h
        storage/pbxt/src/database_xt.h
        storage/pbxt/src/datadic_xt.cc
        storage/pbxt/src/datalog_xt.cc
        storage/pbxt/src/discover_xt.cc
        storage/pbxt/src/ha_pbxt.cc
        storage/pbxt/src/index_xt.cc
        storage/pbxt/src/index_xt.h
        storage/pbxt/src/myxt_xt.cc
        storage/pbxt/src/myxt_xt.h
        storage/pbxt/src/restart_xt.cc
        storage/pbxt/src/strutil_xt.cc
        storage/pbxt/src/table_xt.cc
        storage/pbxt/src/table_xt.h
        storage/pbxt/src/thread_xt.cc
        storage/pbxt/src/xaction_xt.cc
        storage/pbxt/src/xt_defs.h

=== modified file 'mysql-test/suite/pbxt/r/negation_elimination.result'
--- a/mysql-test/suite/pbxt/r/negation_elimination.result	2010-05-06 12:43:19 +0000
+++ b/mysql-test/suite/pbxt/r/negation_elimination.result	2010-09-28 13:05:45 +0000
@@ -388,7 +388,7 @@ Table	Op	Msg_type	Msg_text
 test.t1	analyze	status	OK
 explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like "1"), not (a not in (1,2)), not(a != 2) from t1 where not(not(a)) having not(not(a));
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	t1	index	NULL	a	5	NULL	21	100.00	Using where; Using index
+1	SIMPLE	t1	index	NULL	a	5	NULL	5	100.00	Using where; Using index
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or `test`.`t1`.`a`) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where `test`.`t1`.`a` having `test`.`t1`.`a`
 drop table t1;

=== modified file 'mysql-test/suite/pbxt/r/select.result'
--- a/mysql-test/suite/pbxt/r/select.result	2010-05-06 12:43:19 +0000
+++ b/mysql-test/suite/pbxt/r/select.result	2010-09-28 13:05:45 +0000
@@ -1384,52 +1384,52 @@ Table	Op	Msg_type	Msg_text
 test.t2	analyze	status	OK
 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	Using where
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	Using where
 1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	1	test.t2.companynr	1	
 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	Using where
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	Using where
 1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	1	test.t2.companynr	1	
 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	Using where
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	Using where
 1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	1	test.t2.companynr	1	
 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	PRIMARY	NULL	NULL	NULL	12	Using where
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	
 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	PRIMARY	NULL	NULL	NULL	12	Using where
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	
 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	PRIMARY	NULL	NULL	NULL	12	Using where
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	
 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	NULL	NULL	NULL	NULL	12	
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	Using where
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	Using where
 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	PRIMARY	NULL	NULL	NULL	12	
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	Using where
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	Using where
 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	NULL	NULL	NULL	NULL	12	
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	Using where
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	Using where
 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	PRIMARY	NULL	NULL	NULL	12	Using where
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	
 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	PRIMARY	NULL	NULL	NULL	12	Using where
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	
 explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	ALL	NULL	NULL	NULL	NULL	12	Using where
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	
 select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
 companynr	companynr
 37	36
@@ -1437,7 +1437,7 @@ companynr	companynr
 explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t4	index	NULL	PRIMARY	1	NULL	12	Using index; Using temporary
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	Using where; Using join buffer
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	Using where; Using join buffer
 select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008;
 fld1	companynr	fld3	period
 038008	37	reporters	1008
@@ -1511,7 +1511,7 @@ count(*)	min(fld4)	max(fld4)	sum(fld1)	a
 70	absentee	vest	17788966	254128.0857	3272.5940	10709871.3069
 explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	100.00	Using where
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	100.00	Using where
 Warnings:
 Note	1003	select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> ''))
 select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
@@ -1955,7 +1955,7 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
 explain select fld3 from t2 where fld1=fld1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1200	
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	1199	
 select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
 companynr	fld1
 34	250501
@@ -2007,7 +2007,7 @@ count(*)
 4181
 explain select min(fld1),max(fld1),count(*) from t2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	index	NULL	fld1	4	NULL	1200	Using index
+1	SIMPLE	t2	index	NULL	fld1	4	NULL	1199	Using index
 select min(fld1),max(fld1),count(*) from t2;
 min(fld1)	max(fld1)	count(*)
 0	1232609	1199
@@ -2093,9 +2093,9 @@ show full columns from t2 from test like
 Field	Type	Collation	Null	Key	Default	Extra	Privileges	Comment
 show keys from t2;
 Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
-t2	0	PRIMARY	1	auto	A	1200	NULL	NULL		BTREE	
-t2	0	fld1	1	fld1	A	1200	NULL	NULL		BTREE	
-t2	1	fld3	1	fld3	A	1200	NULL	NULL		BTREE	
+t2	0	PRIMARY	1	auto	A	1199	NULL	NULL		BTREE	
+t2	0	fld1	1	fld1	A	1199	NULL	NULL		BTREE	
+t2	1	fld3	1	fld3	A	1199	NULL	NULL		BTREE	
 drop table t4, t3, t2, t1;
 DO 1;
 DO benchmark(100,1+1),1,1;

=== modified file 'storage/pbxt/ChangeLog'
--- a/storage/pbxt/ChangeLog	2010-05-06 16:33:54 +0000
+++ b/storage/pbxt/ChangeLog	2010-09-28 13:05:45 +0000
@@ -1,7 +1,49 @@
 PBXT Release Notes
 ==================
 
-+------- 1.0.11 Pre-GA - 2010-05-11
+------- 1.0.11-7 Pre-GA - 2010-09-09
+
+RN336: Compiled and tested with MySQL 5.1.50.
+
+RN335: Fixed bug #523994: Deleting all records does not update table statistics. 
+
+RN334: Made a change to reduce the time that only temporary tables exist during the ALTER TABLE and REPAIR TABLE statements. This increases the chance of recovery if a crash occurs during these operations.
+
+RN333: Log name of table when PBXT recovers an index on startup. If an error occurs during index recovery, the index is set to "repair pending".
+
+RN332: Fixed an inifinite loop when a record in a row is corrupt. Added logging and set the table to "repair pending" in this case.
+
+RN331: Fixed bug #626890: Crash on truncate table operation.
+
+RN330: Added additional checks for corruption of the index free list.
+
+------- 1.0.11-6 Pre-GA - 2010-07-08
+
+RN329: Fixed bug #601245: make fails. PBXT did not compile if the partition engine was disabled in the MySQL build.
+
+------- 1.0.11-5 Pre-GA - 2010-06-18
+
+RN328: Fixed bug #595478: Compile fails (1.0.11-4).
+
+------- 1.0.11-4 Pre-GA - 2010-06-15
+
+RN327: Fixed a bug that caused a crash during delete on the index. The crash occurred due to memory overwrite when a long key is promoted after a shorter key is deleted, and the difference causes a node size overflow.
+
+------- 1.0.11-3 Pre-GA - 2010-06-11
+
+RN326: Fixed bug #587740: pbxt-1.0.11-pre2-ga first time create partition table error. This was not a new bug. The problem was the PBXT system table's .frm files are corrupted when the first PBXT table created is a partition table.
+
+RN325: Fixed the "to-sweep" column output in xtstat.
+
+------- 1.0.11-2 Pre-GA - 2010-05-26
+
+RN324: Fixed bug #584070:pbxt-1.0.11-pre-ga does not work with mysql 5.1.47. This bug fix removes a hack which was done to avoid running into the LOCK_plugin lock.
+
+------- 1.0.11-1 Pre-GA - 2010-05-19
+
+RN323: Detect corruption of a key length in an index page. This bug fix avoids a possible crash due to index page corruption. 
+
+------- 1.0.11 Pre-GA - 2010-05-11
 
 RN322: Creating a table the references a non-existing table can now only be done if you set: foreign_key_checks = 0. Also fixed a failure when creating tables with recursive foreign key declarations.
 

=== modified file 'storage/pbxt/src/Makefile.am'
--- a/storage/pbxt/src/Makefile.am	2010-09-09 13:35:47 +0000
+++ b/storage/pbxt/src/Makefile.am	2010-09-28 13:05:45 +0000
@@ -40,8 +40,8 @@ libpbxt_la_LDFLAGS =	-module
 # These are the warning Drizzle uses:
 # DRIZZLE_WARNINGS =		-W -Wall -Wextra -pedantic -Wundef -Wredundant-decls -Wno-strict-aliasing -Wno-long-long -Wno-unused-parameter
 
-libpbxt_la_CXXFLAGS =	-shared $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-libpbxt_la_CFLAGS =	-shared $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -std=c99
+libpbxt_la_CXXFLAGS =	$(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+libpbxt_la_CFLAGS =		$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -std=c99
 
 EXTRA_LIBRARIES =		libpbxt.a
 noinst_LIBRARIES = 		libpbxt.a

=== modified file 'storage/pbxt/src/cache_xt.cc'
--- a/storage/pbxt/src/cache_xt.cc	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/cache_xt.cc	2010-09-28 13:05:45 +0000
@@ -668,6 +668,9 @@ xtPublic void xt_ind_init(XTThreadPtr se
 			block->cb_data = buffer;
 			buffer += XT_INDEX_PAGE_SIZE;
 #endif
+#ifdef CHECK_BLOCK_TRAILERS
+			XT_SET_DISK_4(block->cp_check, 0xDEADBEEF);
+#endif
 			ind_cac_globals.cg_free_list = block;
 			block++;
 		}
@@ -684,6 +687,19 @@ xtPublic void xt_ind_init(XTThreadPtr se
 	cont_(a);
 }
 
+#ifdef CHECK_BLOCK_TRAILERS
+xtPublic void check_block_trailers()
+{
+	XTIndBlockPtr	block;
+
+	block = ind_cac_globals.cg_blocks;
+	for (u_int i=0; i<ind_cac_globals.cg_block_count; i++) {
+		ASSERT_NS(XT_GET_DISK_4(block->cp_check) == 0xDEADBEEF);
+		block++;
+	}
+}
+#endif
+
 xtPublic void xt_ind_exit(XTThreadPtr self)
 {
 #ifdef XT_USE_MYSYS
@@ -1283,7 +1299,7 @@ static XTIndBlockPtr ind_cac_fetch(XTOpe
 	 * Conditionally count the number of deleted entries in the index:
 	 * We do this before other threads can read the block.
 	 */
-	if (ind->mi_lazy_delete && read_data)
+	if (ind && ind->mi_lazy_delete && read_data)
 		xt_ind_count_deleted_items(ot->ot_table, ind, block);
 
 	/* Add to the hash table: */
@@ -1358,6 +1374,9 @@ xtPublic xtBool xt_ind_write(XTOpenTable
 #ifdef XT_TRACK_INDEX_UPDATES
 	ot->ot_ind_changed++;
 #endif
+#ifdef CHECK_BLOCK_TRAILERS
+	check_block_trailers();
+#endif
 	return OK;
 }
 

=== modified file 'storage/pbxt/src/cache_xt.h'
--- a/storage/pbxt/src/cache_xt.h	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/cache_xt.h	2010-09-28 13:05:45 +0000
@@ -33,6 +33,7 @@ struct XTIdxReadBuffer;
 
 #ifdef DEBUG
 //#define XT_USE_CACHE_DEBUG_SIZES
+//#define CHECK_BLOCK_TRAILERS
 #endif
 
 #ifdef XT_USE_CACHE_DEBUG_SIZES
@@ -116,6 +117,9 @@ typedef struct XTIndBlock {
 #else
 	xtWord1				cb_data[XT_INDEX_PAGE_SIZE];
 #endif
+#ifdef CHECK_BLOCK_TRAILERS
+	xtWord1				cp_check[4];
+#endif
 } XTIndBlockRec, *XTIndBlockPtr;
 
 typedef struct XTIndReference {
@@ -177,6 +181,10 @@ xtBool			xt_ind_copy_on_write(XTIndRefer
 XTIndHandlePtr	xt_ind_get_handle(struct XTOpenTable *ot, XTIndexPtr ind, XTIndReferencePtr iref);
 void			xt_ind_release_handle(XTIndHandlePtr handle, xtBool have_lock, XTThreadPtr thread);
 
+#ifdef CHECK_BLOCK_TRAILERS
+extern void check_block_trailers();
+#endif
+
 #ifdef DEBUG
 //#define DEBUG_CHECK_IND_CACHE
 #endif

=== modified file 'storage/pbxt/src/database_xt.h'
--- a/storage/pbxt/src/database_xt.h	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/database_xt.h	2010-09-28 13:05:45 +0000
@@ -117,6 +117,7 @@ typedef struct XTDatabase : public XTHea
 	XTSortedListPtr			db_table_by_id;
 	XTSortedListPtr			db_table_paths;							/* A list of table paths used by this database. */
 	xtBool					db_multi_path;
+	XTSortedListPtr			db_error_list;							/* A list of errors already reported. */
 
 	/* The open table pool: */
 	XTAllTablePoolsRec		db_ot_pool;

=== modified file 'storage/pbxt/src/datadic_xt.cc'
--- a/storage/pbxt/src/datadic_xt.cc	2010-05-06 12:42:28 +0000
+++ b/storage/pbxt/src/datadic_xt.cc	2010-09-28 13:05:45 +0000
@@ -396,7 +396,7 @@ void XTToken::expectNumber(XTThreadPtr s
 struct charset_info_st;
 
 class XTTokenizer {
-	struct charset_info_st	*tkn_charset;
+	MX_CONST_CHARSET_INFO	*tkn_charset;
 	char					*tkn_cstring;
 	char					*tkn_curr_pos;
 	XTToken					*tkn_current;
@@ -1324,7 +1324,7 @@ void XTParseTable::parseDropIndex(XTThre
 class XTCreateTable : public XTParseTable {
 	public:
 	bool					ct_convert;
-	struct charset_info_st	*ct_charset;
+	MX_CONST_CHARSET_INFO	*ct_charset;
 	XTPathStrPtr			ct_tab_path;
 	u_int					ct_contraint_no;
 	XTDDTable				*ct_curr_table;
@@ -2039,11 +2039,6 @@ void XTDDTableRef::deleteAllRows(XTThrea
 	if (!(ot = xt_db_open_table_using_tab(tr_fkey->co_table->dt_table, self)))
 		xt_throw(self);
 
-	/* {FREE-ROWS-BAD} */
-	/*
-	row_count = ((xtInt8) ot->ot_table->tab_row_eof_id) - 1;
-	row_count -= (xtInt8) ot->ot_table->tab_row_fnum;
-	*/
 	/* Check if there are any rows in the referencing table: */
 	if (!xt_tab_seq_init(ot))
 		goto failed;

=== modified file 'storage/pbxt/src/datalog_xt.cc'
--- a/storage/pbxt/src/datalog_xt.cc	2010-05-14 11:56:14 +0000
+++ b/storage/pbxt/src/datalog_xt.cc	2010-09-28 13:05:45 +0000
@@ -1249,7 +1249,7 @@ xtBool XTDataLogBuffer::dlb_write_thru_l
 	 */
 	dlb_data_log->dlf_log_eof += size;
 #ifdef DEBUG
-	if ((ulonglong) (log_offset + size) > (ulonglong) dlb_max_write_offset)
+	if (log_offset + (xtLogOffset) size > (xtLogOffset) dlb_max_write_offset)
 		dlb_max_write_offset = log_offset + size;
 #endif
 	dlb_flush_required = TRUE;
@@ -1291,7 +1291,7 @@ xtBool XTDataLogBuffer::dlb_append_log(x
 	if (!xt_pwrite_file(dlb_data_log->dlf_log_file, log_offset, size, data, &thread->st_statistics.st_data, thread))
 		return FAILED;
 #ifdef DEBUG
-	if ((ulonglong) (log_offset + size) > (ulonglong) dlb_max_write_offset)
+	if (log_offset + (xtLogOffset) size > (xtLogOffset) dlb_max_write_offset)
 		dlb_max_write_offset = log_offset + size;
 #endif
 	dlb_flush_required = TRUE;
@@ -1734,8 +1734,8 @@ static xtBool dl_collect_garbage(XTThrea
 	xtLogOffset			src_log_offset;
 	xtLogID				curr_log_id;
 	xtLogOffset			curr_log_offset;
-	xtLogID				dest_log_id= 0;
-	xtLogOffset			dest_log_offset= 0;
+	xtLogID				dest_log_id = 0;
+	xtLogOffset			dest_log_offset = 0;
 	off_t				garbage_count = 0;
 
 	memset(&cs, 0, sizeof(XTCompactorStateRec));

=== modified file 'storage/pbxt/src/discover_xt.cc'
--- a/storage/pbxt/src/discover_xt.cc	2009-12-21 13:13:15 +0000
+++ b/storage/pbxt/src/discover_xt.cc	2010-09-28 13:05:45 +0000
@@ -1622,7 +1622,11 @@ int xt_create_table_frm(handlerton *hton
 				COLUMN_FORMAT_TYPE_FIXED,
 #endif
 		       NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/, 
-		       NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/)) 
+		       NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/
+#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID > 50200
+		       , NULL /*vcol_info*/, NULL /* create options */
+#endif
+		       )) 
 #endif
 			goto error;
 
@@ -1654,8 +1658,17 @@ int xt_create_table_frm(handlerton *hton
 	if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0)) 
 		goto error;
 #else
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+	partition_info *part_info;
+
+	part_info = thd->work_part_info;
+	thd->work_part_info = NULL;
+#endif
 	if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0)) 
 		goto error;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+	thd->work_part_info = part_info;
+#endif
 #endif
 
 	noerror:

=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- a/storage/pbxt/src/ha_pbxt.cc	2010-05-27 17:18:31 +0000
+++ b/storage/pbxt/src/ha_pbxt.cc	2010-09-28 13:05:45 +0000
@@ -1232,6 +1232,11 @@ static int pbxt_init(void *p)
 				THD *thd = NULL;
 
 #ifndef DRIZZLED
+#if MYSQL_VERSION_ID < 50147
+				/* A hack which is no longer required after 5.1.46 */
+				extern myxt_mutex_t LOCK_plugin;
+#endif
+
 				/* {MYSQL QUIRK}
 				 * I have to release this lock for PBXT recovery to
 				 * work, because it needs to open .frm files.
@@ -1248,8 +1253,7 @@ static int pbxt_init(void *p)
 				 * Only real problem, 2 threads try to load the same
 				 * plugin at the same time.
 				 */
-#if MYSQL_VERSION_ID <= 50146
-				extern myxt_mutex_t LOCK_plugin;
+#if MYSQL_VERSION_ID < 50147
 				myxt_mutex_unlock(&LOCK_plugin);
 #endif
 #endif
@@ -1285,9 +1289,11 @@ static int pbxt_init(void *p)
 
 				if (thd)
 					myxt_destroy_thread(thd, FALSE);
-#if MYSQL_VERSION_ID <= 50146 && !defined(DRIZZLED)
+#ifndef DRIZZLED
+#if MYSQL_VERSION_ID < 50147
 				myxt_mutex_lock(&LOCK_plugin);
 #endif
+#endif
 			}
 #endif
 		}
@@ -1948,8 +1954,13 @@ xtPublic int ha_pbxt::reopen()
 			 * selectity of the indices, as soon as the number of rows
 			 * exceeds 200 (see [**])
 			 */
+#ifdef XT_ROW_COUNT_CORRECTED
+			/* {CORRECTED-ROW-COUNT} */
+			pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;
+#else
 			/* {FREE-ROWS-BAD} */
 			pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
+#endif
 		}
 
 		/* I am not doing this anymore because it was only required
@@ -2006,7 +2017,7 @@ static int pbxt_statistics_fill_table(TH
 			xt_ha_open_database_of_table(self, (XTPathStrPtr) NULL);
 		}
 
-		err = myxt_statistics_fill_table(self, thd, tables, cond, system_charset_info);
+		err = myxt_statistics_fill_table(self, thd, tables, cond, (void*) system_charset_info);
 	}
 	catch_(a) {
 		err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
@@ -2296,6 +2307,36 @@ void ha_pbxt::internal_close(THD *thd, s
 					 */
 					if (!thd || thd_sql_command(thd) == SQLCOM_FLUSH) // FLUSH TABLES
 						xt_sync_flush_table(self, ot);
+					else {
+						/* This change is a result of a problem mentioned by Arjen.
+						 * REPAIR and ALTER lead to the following sequence:
+						 * 1. tab  -- copy --> tmp1
+						 * 2. tab  -- rename --> tmp2
+						 * 3. tmp1 -- rename --> tab
+						 * 4. delete tmp2
+						 *
+						 * PBXT flushes a table before rename.
+						 * In the sequence above results in a table flush in step 3 which can
+						 * take a very long time.
+						 *
+						 * The problem is, during this time frame we have only temp tables.
+						 * A crash in this state leaves the database in a bad state.
+						 *
+						 * To reduce the time in this state, the flush needs to be done
+						 * elsewhere. The code below causes the flish to occur after
+						 * step 1:
+						 */ 
+						switch (thd_sql_command(thd)) {
+							case SQLCOM_REPAIR:
+							case SQLCOM_RENAME_TABLE:
+							case SQLCOM_OPTIMIZE:
+							case SQLCOM_ANALYZE:
+							case SQLCOM_ALTER_TABLE:
+							case SQLCOM_CREATE_INDEX:
+								xt_sync_flush_table(self, ot);
+								break;
+						}
+					}
 				}
 				freer_(); // xt_db_return_table_to_pool(ot);
 			}
@@ -2356,9 +2397,15 @@ int ha_pbxt::open(const char *table_path
 #else
 			xt_tab_load_row_pointers(self, pb_open_tab);
 #endif
+
 			xt_ind_set_index_selectivity(pb_open_tab, self);
+#ifdef XT_ROW_COUNT_CORRECTED
+			/* {CORRECTED-ROW-COUNT} */
+			pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;
+#else
 			/* {FREE-ROWS-BAD} */
 			pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
+#endif
 		}
 
 		init_auto_increment(0);
@@ -3929,6 +3976,8 @@ int ha_pbxt::info(uint flag)
 
 	if ((ot = pb_open_tab)) {
 		if (flag & HA_STATUS_VARIABLE) {
+				register XTTableHPtr tab = ot->ot_table;
+
 			/* {FREE-ROWS-BAD}
 			 * Free row count is not reliable, so ignore it.
 			 * The problem is if tab_row_fnum > tab_row_eof_id - 1 then
@@ -3955,11 +4004,26 @@ int ha_pbxt::info(uint flag)
 			 * the actual number of vectors. But it must assume that it has at
 			 * least EXTRA_RECORDS vectors.
 			 */
-			stats.deleted = /* ot->ot_table->tab_row_fnum */ 0;
-			stats.records = (ha_rows) (ot->ot_table->tab_row_eof_id - 1 /* - stats.deleted */);
-			stats.data_file_length = xt_rec_id_to_rec_offset(ot->ot_table, ot->ot_table->tab_rec_eof_id);
-			stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof);
-			stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size;
+#ifdef XT_ROW_COUNT_CORRECTED
+			if (tab->tab_row_eof_id <= tab->tab_row_fnum ||
+				(!tab->tab_row_free_id && tab->tab_row_fnum))
+				xt_tab_check_free_lists(NULL, ot, false, true);
+			stats.records = (ha_rows) tab->tab_row_eof_id - 1;
+			if (stats.records >= tab->tab_row_fnum) {
+				stats.deleted = tab->tab_row_fnum;
+				stats.records -= stats.deleted;
+			}
+			else {
+				stats.deleted = 0;
+				stats.records = 2;
+			}
+#else
+			stats.deleted = /* tab->tab_row_fnum */ 0;
+			stats.records = (ha_rows) (tab->tab_row_eof_id - 1 /* - stats.deleted */);
+#endif
+			stats.data_file_length = xt_rec_id_to_rec_offset(tab, tab->tab_rec_eof_id);
+			stats.index_file_length = xt_ind_node_to_offset(tab, tab->tab_ind_eof);
+			stats.delete_length = tab->tab_rec_fnum * ot->ot_rec_size;
 			//check_time = info.check_time;
 			stats.mean_rec_length = (ulong) ot->ot_rec_size;
 		}
@@ -4584,13 +4648,24 @@ xtPublic int ha_pbxt::external_lock(THD
 				}
 
 				if (pb_share->sh_recalc_selectivity) {
+#ifdef XT_ROW_COUNT_CORRECTED
+					/* {CORRECTED-ROW-COUNT} */
+					if ((pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) >= 200)
+#else
 					/* {FREE-ROWS-BAD} */
-					if ((pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) >= 200) {
+					if ((pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) >= 200)
+#endif
+					{
 						/* [**] */
 						pb_share->sh_recalc_selectivity = FALSE;
 						xt_ind_set_index_selectivity(pb_open_tab, self);
+#ifdef XT_ROW_COUNT_CORRECTED
+						/* {CORRECTED-ROW-COUNT} */
+						pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;
+#else
 						/* {FREE-ROWS-BAD} */
 						pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
+#endif
 					}
 				}
 			}
@@ -4638,6 +4713,17 @@ xtPublic int ha_pbxt::external_lock(THD
 				goto complete;
 			}
 			cont_(a);
+
+			/* Occurs if you do:
+			 * truncate table t1;
+			 * truncate table t1;
+			 */
+			if (!pb_open_tab) {
+				if ((err = reopen())) {
+					pb_ex_in_use = 0;
+					goto complete;
+				}
+			}
 		}
 		else {
 			pb_ex_in_use = 1;
@@ -6076,6 +6162,40 @@ mysql_declare_plugin(pbxt)
 drizzle_declare_plugin_end;
 #else
 mysql_declare_plugin_end;
+#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID > 50200
+maria_declare_plugin(pbxt)
+{ /* PBXT */
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &pbxt_storage_engine,
+  "PBXT",
+  "Paul McCullagh, PrimeBase Technologies GmbH",
+  "High performance, multi-versioning transactional engine",
+  PLUGIN_LICENSE_GPL,
+  pbxt_init, /* Plugin Init */
+  pbxt_end, /* Plugin Deinit */
+  0x0001 /* 0.1 */,
+  NULL,                       /* status variables */
+  pbxt_system_variables,      /* system variables */
+  "1.0.11-7 Pre-GA",              /* string version */
+  MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+},
+{ /* PBXT_STATISTICS */
+  MYSQL_INFORMATION_SCHEMA_PLUGIN,
+  &pbxt_statitics,
+  "PBXT_STATISTICS",
+  "Paul McCullagh, PrimeBase Technologies GmbH",
+  "PBXT internal system statitics",
+  PLUGIN_LICENSE_GPL,
+  pbxt_init_statistics,       /* plugin init */
+  pbxt_exit_statistics,       /* plugin deinit */
+  0x0005,
+  NULL,                       /* status variables */
+  NULL,                       /* system variables */
+  "1.0.11-7 Pre-GA",          /* string version */
+  MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
+#endif
 #endif
 
 #if defined(XT_WIN) && defined(XT_COREDUMP)

=== modified file 'storage/pbxt/src/index_xt.cc'
--- a/storage/pbxt/src/index_xt.cc	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/index_xt.cc	2010-09-28 13:05:45 +0000
@@ -272,10 +272,17 @@ static xtBool idx_new_branch(XTOpenTable
 	}
 
 	if ((XT_NODE_ID(wrote_pos) = XT_NODE_ID(tab->tab_ind_free))) {
+		xtIndexNodeID next_node;
+
 		/* Use the block on the free list: */
-		if (!xt_ind_read_bytes(ot, ind, wrote_pos, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block))
+		if (!xt_ind_read_bytes(ot, NULL, wrote_pos, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block))
+			goto failed;
+		XT_NODE_ID(next_node) = (xtIndexNodeID) XT_GET_DISK_8(free_block.if_next_block_8);
+		if (XT_NODE_ID(next_node) >= XT_NODE_ID(tab->tab_ind_eof)) {
+			xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, tab->tab_name);
 			goto failed;
-		XT_NODE_ID(tab->tab_ind_free) = (xtIndexNodeID) XT_GET_DISK_8(free_block.if_next_block_8);
+		}
+		XT_NODE_ID(tab->tab_ind_free) = XT_NODE_ID(next_node);
 		xt_unlock_mutex_ns(&tab->tab_ind_lock);
 		*address = wrote_pos;
 		TRACK_BLOCK_ALLOC(wrote_pos);
@@ -1415,30 +1422,45 @@ static xtBool idx_replace_node_key(XTOpe
 		if (idx_is_item_deleted(iref.ir_branch, &item->i_pos))
 			iref.ir_block->cp_del_count--;
 	}
-	memmove(&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item_size],
-		&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size],
-		item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size);
-	memcpy(&iref.ir_branch->tb_data[item->i_pos.i_item_offset],
-		item_buf, item_size);
-	if (ind->mi_lazy_delete) {
-		if (idx_is_item_deleted(iref.ir_branch, &item->i_pos))
-			iref.ir_block->cp_del_count++;
-	}
-	item->i_pos.i_total_size = item->i_pos.i_total_size + item_size - item->i_pos.i_item_size;
-	XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(item->i_pos.i_total_size));
-	IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2));
-	iref.ir_updated = TRUE;
+
+	if (item->i_pos.i_total_size + item_size - item->i_pos.i_item_size <= XT_INDEX_PAGE_DATA_SIZE) {
+		/* The new item is larger than the old, this can result
+		 * in overflow of the node!
+		 */
+		memmove(&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item_size],
+			&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size],
+			item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size);
+		memcpy(&iref.ir_branch->tb_data[item->i_pos.i_item_offset],
+			item_buf, item_size);
+		if (ind->mi_lazy_delete) {
+			if (idx_is_item_deleted(iref.ir_branch, &item->i_pos))
+				iref.ir_block->cp_del_count++;
+		}
+		item->i_pos.i_total_size = item->i_pos.i_total_size + item_size - item->i_pos.i_item_size;
+		XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(item->i_pos.i_total_size));
+		IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2));
+		iref.ir_updated = TRUE;
 
 #ifdef DEBUG
-	if (ind->mi_lazy_delete)
 		ASSERT_NS(item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE);
 #endif
-	if (item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE)
 		return xt_ind_release(ot, ind, XT_UNLOCK_W_UPDATE, &iref);
+	}
 
 	/* The node has overflowed!! */
 	result.sr_item = item->i_pos;
 
+	memcpy(ot->ot_ind_wbuf.tb_data, iref.ir_branch->tb_data, item->i_pos.i_item_offset);	// First part of the buffer
+	memcpy(&ot->ot_ind_wbuf.tb_data[item->i_pos.i_item_offset], item_buf, item_size);		// The new item
+	memcpy(&ot->ot_ind_wbuf.tb_data[item->i_pos.i_item_offset + item_size],
+		&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size],
+		item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size);
+	item->i_pos.i_total_size += item_size - item->i_pos.i_item_size;
+	item->i_pos.i_item_size = item_size;
+	XT_SET_DISK_2(ot->ot_ind_wbuf.tb_size_2, XT_MAKE_LEAF_SIZE(item->i_pos.i_total_size));
+	IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2));
+	ASSERT_NS(item->i_pos.i_total_size > XT_INDEX_PAGE_DATA_SIZE && item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE*2);
+
 	/* Adjust the stack (we want the parents of the delete node): */
 	for (;;) {
 		if (idx_pop(stack) == item)
@@ -1448,7 +1470,7 @@ static xtBool idx_replace_node_key(XTOpe
 	/* We assume that value can be overwritten (which is the case) */
 	key_value.sv_flags = XT_SEARCH_WHOLE_KEY;
 	key_value.sv_key = key_buf;
-	if (!idx_get_middle_branch_item(ot, ind, iref.ir_branch, &key_value, &result))
+	if (!idx_get_middle_branch_item(ot, ind, &ot->ot_ind_wbuf, &key_value, &result))
 		goto failed_1;
 
 	if (!idx_new_branch(ot, ind, &new_branch))
@@ -1456,7 +1478,6 @@ static xtBool idx_replace_node_key(XTOpe
 
 	/* Split the node: */
 	new_size = result.sr_item.i_total_size - result.sr_item.i_item_offset - result.sr_item.i_item_size;
-	// TODO: Are 2 buffers now required?
 	new_branch_ptr = (XTIdxBranchDPtr) &ot->ot_ind_wbuf.tb_data[XT_INDEX_PAGE_DATA_SIZE];
 	memmove(new_branch_ptr->tb_data, &iref.ir_branch->tb_data[result.sr_item.i_item_offset + result.sr_item.i_item_size], new_size);
 
@@ -1466,10 +1487,10 @@ static xtBool idx_replace_node_key(XTOpe
 		goto failed_2;
 
 	/* Change the size of the old branch: */
-	XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(result.sr_item.i_item_offset));
-	IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2));
+	XT_SET_DISK_2(ot->ot_ind_wbuf.tb_size_2, XT_MAKE_NODE_SIZE(result.sr_item.i_item_offset));
+	IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2));
+	memcpy(iref.ir_branch, &ot->ot_ind_wbuf, offsetof(XTIdxBranchDRec, tb_data) + result.sr_item.i_item_offset);
 	iref.ir_updated = TRUE;
-
 	xt_ind_release(ot, ind, XT_UNLOCK_W_UPDATE, &iref);
 
 	/* Insert the new branch into the parent node, using the new middle key value: */
@@ -2071,6 +2092,11 @@ xtPublic xtBool xt_idx_insert(XTOpenTabl
 	if (!idx_new_branch(ot, ind, &new_branch))
 		goto failed_1;
 
+	if (XT_NODE_ID(current) == XT_NODE_ID(new_branch)) {
+		xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+		goto failed_1;
+	}
+
 	/* Copy and write the rest of the data to the new node: */
 	new_size = result.sr_item.i_total_size - result.sr_item.i_item_offset - result.sr_item.i_item_size;
 	new_branch_ptr = (XTIdxBranchDPtr) &ot->ot_ind_wbuf.tb_data[XT_INDEX_PAGE_DATA_SIZE];
@@ -2723,6 +2749,10 @@ xtPublic xtBool xt_idx_search(XTOpenTabl
 #endif
 	ASSERT_NS(iref.ir_xlock == 2);
 	ASSERT_NS(iref.ir_updated == 2);
+	if (ind->mi_key_corrupted) {
+		xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+		return FAILED;
+	}
 	return OK;
 
 	failed:
@@ -2874,6 +2904,10 @@ xtPublic xtBool xt_idx_search_prev(XTOpe
 	//idx_check_index(ot, ind, TRUE);
 	//idx_check_on_key(ot);
 #endif
+	if (ind->mi_key_corrupted) {
+		xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+		return FAILED;
+	}
 	return OK;
 
 	failed:
@@ -2964,6 +2998,10 @@ xtPublic xtBool xt_idx_next(register XTO
 
 	if (!(XT_NODE_ID(current) = XT_NODE_ID(ind->mi_root))) {
 		XT_INDEX_UNLOCK(ind, ot);
+		if (ind->mi_key_corrupted) {
+			xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+			return FAILED;
+		}
 		return OK;
 	}
 
@@ -3071,6 +3109,10 @@ xtPublic xtBool xt_idx_next(register XTO
 		ot->ot_curr_rec_id = 0;
 		ot->ot_curr_row_id = 0;
 		XT_INDEX_UNLOCK(ind, ot);
+		if (ind->mi_key_corrupted) {
+			xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+			return FAILED;
+		}
 		return OK;
 	}
 
@@ -3112,6 +3154,10 @@ xtPublic xtBool xt_idx_next(register XTO
 	ot->ot_curr_row_id = result.sr_row_id;
 	ot->ot_ind_state = result.sr_item;
 
+	if (ind->mi_key_corrupted) {
+		xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+		return FAILED;
+	}
 	return OK;
 
 	failed:
@@ -3178,6 +3224,10 @@ xtPublic xtBool xt_idx_prev(register XTO
 
 	if (!(XT_NODE_ID(current) = XT_NODE_ID(ind->mi_root))) {
 		XT_INDEX_UNLOCK(ind, ot);
+		if (ind->mi_key_corrupted) {
+			xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+			return FAILED;
+		}
 		return OK;
 	}
 
@@ -3274,6 +3324,10 @@ xtPublic xtBool xt_idx_prev(register XTO
 	ot->ot_curr_row_id = 0;
 
 	XT_INDEX_UNLOCK(ind, ot);
+	if (ind->mi_key_corrupted) {
+		xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+		return FAILED;
+	}
 	return OK;
 
 	unlock_check_on_key:
@@ -3302,6 +3356,10 @@ xtPublic xtBool xt_idx_prev(register XTO
 	ot->ot_curr_rec_id = result.sr_rec_id;
 	ot->ot_curr_row_id = result.sr_row_id;
 	ot->ot_ind_state = result.sr_item;
+	if (ind->mi_key_corrupted) {
+		xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
+		return FAILED;
+	}
 	return OK;
 
 	failed:
@@ -3648,7 +3706,7 @@ xtPublic void xt_check_indices(XTOpenTab
 			track_block_exists(current);
 #endif
 			printf("%d ", (int) XT_NODE_ID(current));
-			if (!xt_ind_read_bytes(ot, *ind, current, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) {
+			if (!xt_ind_read_bytes(ot, NULL, current, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) {
 				xt_log_and_clear_exception_ns();
 				break;
 			}
@@ -4141,11 +4199,18 @@ void XTIndexLogPool::ilp_init(struct XTT
 					if (!ilp_open_log(&il, log_id, FALSE, self))
 						goto failed;
 					if (il->il_tab_id && il->il_log_eof) {
+						char table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
+
 						if (!il->il_open_table(&ot))
 							goto failed;
 						if (ot) {
-							if (!il->il_apply_log(ot))
-								goto failed;
+							xt_tab_make_table_name(ot->ot_table, table_name, sizeof(table_name));
+							xt_logf(XT_NT_INFO, "PBXT: Recovering index, table: %s, bytes to read: %llu\n", table_name, (u_llong) il->il_log_eof);
+							if (!il->il_apply_log(ot)) {
+								/* If recovery of an index fails, then it is corrupt! */
+								xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED);
+								xt_log_and_clear_exception_ns();
+							}
 							ot->ot_thread = self;
 							il->il_close_table(ot);
 						}
@@ -4468,8 +4533,7 @@ xtBool XTIndexLog::il_apply_log(struct X
 			/* Corrupt log?! */
 			if (il_buffer_len < req_size) {
 				xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of));
-				xt_log_and_clear_exception_ns();
-				return OK;
+				return FAILED;
 			}
 			if (!xt_pread_file(il_of, offset, il_buffer_len, il_buffer_len, il_buffer, NULL, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
 				return FAILED;
@@ -4548,8 +4612,7 @@ xtBool XTIndexLog::il_apply_log(struct X
 						/* Corrupt log?! */
 						if (il_buffer_len < req_size) {
 							xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of));
-							xt_log_and_clear_exception_ns();
-							return OK;
+							return FAILED;
 						}
 						if (!xt_pread_file(il_of, offset, il_buffer_len, il_buffer_len, il_buffer, NULL, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
 							return FAILED;
@@ -4597,8 +4660,7 @@ xtBool XTIndexLog::il_apply_log(struct X
 				break;
 			default:
 				xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of));
-				xt_log_and_clear_exception_ns();
-				return OK;
+				return FAILED;
 		}
 	}
 

=== modified file 'storage/pbxt/src/index_xt.h'
--- a/storage/pbxt/src/index_xt.h	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/index_xt.h	2010-09-28 13:05:45 +0000
@@ -312,7 +312,7 @@ typedef struct XTIndex {
 	u_int				mi_flags;
 	u_int				mi_key_size;
 	u_int				mi_max_items;				/* The maximum number of items that can fit in a leaf node. */
-	xtBool				mi_low_byte_first;
+	xtBool				mi_key_corrupted;			/* Set to TRUE if a currupted index key is detected. */
 	xtBool				mi_fix_key;
 	xtBool				mi_lazy_delete;				/* TRUE if index entries are "lazy deleted". */
 	u_int				mi_single_type;				/* Used when the index contains a single field. */

=== modified file 'storage/pbxt/src/myxt_xt.cc'
--- a/storage/pbxt/src/myxt_xt.cc	2010-05-12 14:27:18 +0000
+++ b/storage/pbxt/src/myxt_xt.cc	2010-09-28 13:05:45 +0000
@@ -1088,7 +1088,10 @@ xtPublic u_int myxt_get_key_length(XTInd
 	}
 
 	end:
-	return (xtWord1 *) key_data - key_buf;
+	u_int ilen = (xtWord1 *) key_data - key_buf;
+	if (ilen > XT_INDEX_MAX_KEY_SIZE)
+		ind->mi_key_corrupted = TRUE;
+	return ilen;
 }
 
 /* Derived from ha_key_cmp */
@@ -2183,7 +2186,8 @@ static XTIndexPtr my_create_index(XTThre
 	xt_spinlock_init_with_autoname(self, &ind->mi_dirty_lock);
 	ind->mi_index_no = idx;
 	ind->mi_flags = (index->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL | HA_UNIQUE_CHECK));
-	ind->mi_low_byte_first = TS(table_arg)->db_low_byte_first;
+	//ind->mi_low_byte_first = TS(table_arg)->db_low_byte_first;
+	ind->mi_key_corrupted = FALSE;
 	ind->mi_fix_key = TRUE;
 	ind->mi_select_total = 0;
 	ind->mi_subset_of = 0;

=== modified file 'storage/pbxt/src/myxt_xt.h'
--- a/storage/pbxt/src/myxt_xt.h	2009-11-27 15:37:02 +0000
+++ b/storage/pbxt/src/myxt_xt.h	2010-09-28 13:05:45 +0000
@@ -69,17 +69,17 @@ void		myxt_free_dictionary(XTThreadPtr s
 void		myxt_move_dictionary(XTDictionaryPtr dic, XTDictionaryPtr source_dic);
 XTDDTable	*myxt_create_table_from_table(XTThreadPtr self, STRUCT_TABLE *my_tab);
 
-void		myxt_static_convert_identifier(XTThreadPtr self, struct charset_info_st *cs, char *from, char *to, size_t to_len);
-char		*myxt_convert_identifier(XTThreadPtr self, struct charset_info_st *cs, char *from);
+void		myxt_static_convert_identifier(XTThreadPtr self, MX_CONST_CHARSET_INFO *cs, char *from, char *to, size_t to_len);
+char		*myxt_convert_identifier(XTThreadPtr self, MX_CONST_CHARSET_INFO *cs, char *from);
 void		myxt_static_convert_table_name(XTThreadPtr self, char *from, char *to, size_t to_len);
 void		myxt_static_convert_file_name(char *from, char *to, size_t to_len);
 char		*myxt_convert_table_name(XTThreadPtr self, char *from);
 int			myxt_strcasecmp(char * a, char *b);
-int			myxt_isspace(struct charset_info_st *cs, char a);
-int			myxt_ispunct(struct charset_info_st *cs, char a);
-int			myxt_isdigit(struct charset_info_st *cs, char a);
+int			myxt_isspace(MX_CONST_CHARSET_INFO *cs, char a);
+int			myxt_ispunct(MX_CONST_CHARSET_INFO *cs, char a);
+int			myxt_isdigit(MX_CONST_CHARSET_INFO *cs, char a);
 
-struct charset_info_st *myxt_getcharset(bool convert);
+MX_CONST_CHARSET_INFO *myxt_getcharset(bool convert);
 
 void		*myxt_create_thread();
 void		myxt_destroy_thread(void *thread, xtBool end_threads);

=== modified file 'storage/pbxt/src/restart_xt.cc'
--- a/storage/pbxt/src/restart_xt.cc	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/restart_xt.cc	2010-09-28 13:05:45 +0000
@@ -1359,6 +1359,57 @@ static xtBool xres_sync_operations(XTThr
 	return op_synced;
 }
 
+#ifdef XT_CORRECT_TABLE_FREE_COUNT
+#define CORRECT_COUNT		TRUE
+#else
+#define CORRECT_COUNT		FALSE
+#endif
+#ifdef XT_CHECK_RECORD_FREE_COUNT
+#define CHECK_RECS			TRUE
+#else
+#define CHECK_RECS			FALSE
+#endif
+#if defined(XT_CHECK_RECORD_FREE_COUNT) || defined(XT_CHECK_ROW_FREE_COUNT)
+#define RECOVER_FREE_COUNTS
+#endif
+
+#ifdef RECOVER_FREE_COUNTS
+/* {CORRECTED-ROW-COUNT}
+ * This error can be repeated by crashing the server during
+ * high activitity, after flush table writes the table header
+ * 
+ * On recovery, the free count "from the future" is used as
+ * the starting point for subsequent allocation and frees.
+ * The count is wrong after that point.
+ *
+ * The recovery of the count only works correctly if a
+ * checkpoint is complete successfully after that table
+ * header is flushed. Basically the writing of the table
+ * header should be synchronsized with the writing of the
+ * end of the checkpoint.
+ *
+ * Another solution would be to log the count, along with
+ * the allocate and free commannds.
+ *
+ * The 3rd solution is the one used here. The count is corrected
+ * after recovery.
+ */
+static void xres_recover_table_free_counts(XTThreadPtr self, XTDatabaseHPtr db, XTWriterStatePtr ws)
+{
+	u_int			edx;
+	XTTableEntryPtr	te_ptr;
+	XTTableHPtr		tab;
+
+	xt_enum_tables_init(&edx);
+	while ((te_ptr = xt_enum_tables_next(self, db, &edx))) {
+		if ((tab = te_ptr->te_table)) {
+			if (xres_open_table(self, ws, te_ptr->te_tab_id))
+				xt_tab_check_free_lists(self, ws->ws_ot, CHECK_RECS, CORRECT_COUNT);
+		}
+	}
+}
+#endif
+
 /*
  * Operations from the log are applied in sequence order.
  * If the operations are out of sequence, they are buffered
@@ -2175,6 +2226,13 @@ xtBool XTXactRestart::xres_restart(XTThr
 			/* This is true because if no transaction was placed in RAM then
 			 * the next transaction in RAM will have the next ID: */
 			db->db_xn_min_ram_id = db->db_xn_curr_id + 1;
+
+#ifdef RECOVER_FREE_COUNTS
+		if (xres_cp_log_id != *log_id || xres_cp_log_offset != *log_offset) {
+			/* Recovery took place, correct the row count! */
+			xres_recover_table_free_counts(self, db, &ws);
+		}
+#endif
 	}
 
 	failed:

=== modified file 'storage/pbxt/src/strutil_xt.cc'
--- a/storage/pbxt/src/strutil_xt.cc	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/strutil_xt.cc	2010-09-28 13:05:45 +0000
@@ -380,7 +380,7 @@ xtPublic void xt_int8_to_byte_size(xtInt
 /* Version number must also be set in configure.in! */
 xtPublic c_char *xt_get_version(void)
 {
-	return "1.0.11 Pre-GA";
+	return "1.0.11-7 Pre-GA";
 }
 
 /* Copy and URL decode! */

=== modified file 'storage/pbxt/src/table_xt.cc'
--- a/storage/pbxt/src/table_xt.cc	2010-05-14 11:56:14 +0000
+++ b/storage/pbxt/src/table_xt.cc	2010-09-28 13:05:45 +0000
@@ -80,6 +80,65 @@
 
 /*
  * -----------------------------------------------------------------------
+ * Handle Error Detected in a Table
+ */
+
+struct XTTableError {
+	xtTableID		ter_tab_id;
+	xtRecordID		ter_rec_id;
+};
+
+static int tab_comp_tab_error(XTThreadPtr XT_UNUSED(self), register const void *XT_UNUSED(thunk), register const void *a, register const void *b)
+{
+	XTTableError	*ter_a = ((XTTableError *) a);
+	XTTableError	*ter_b = (XTTableError *) b;
+
+	if (ter_a->ter_tab_id < ter_b->ter_tab_id)
+		return -1;
+	if (ter_a->ter_tab_id == ter_b->ter_tab_id) {
+		if (ter_a->ter_rec_id < ter_b->ter_rec_id)
+			return -1;
+		if (ter_a->ter_rec_id == ter_b->ter_rec_id)
+			return 0;
+		return 1;
+	}
+	return 1;
+}
+
+static xtBool tab_record_corrupt(XTOpenTablePtr ot, xtRowID row_id, xtRecordID rec_id, bool not_valid, int where)
+{
+	XTTableHPtr		tab = ot->ot_table;
+	XTDatabaseHPtr	db = tab->tab_db;
+	XTTableError	ter;
+	XTTableError	*ter_ptr;
+	
+	ter.ter_tab_id = tab->tab_id;
+	ter.ter_rec_id = rec_id;
+	
+	xt_sl_lock_ns(db->db_error_list, ot->ot_thread);
+	if (!(ter_ptr = (XTTableError *) xt_sl_find(NULL, db->db_error_list, &ter))) {
+		xtBool	ok;
+		char	table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
+
+		ok = xt_sl_insert(NULL, db->db_error_list, &ter, &ter);
+		xt_sl_unlock_ns(db->db_error_list);
+		if (!ok)
+			return FAILED;
+		xt_tab_set_table_repair_pending(tab);
+		xt_tab_make_table_name(tab, table_name, sizeof(table_name));
+		xt_logf(XT_NT_ERROR, "#%d Table %s: row %llu, record %llu, is %s, REPAIR TABLE required.\n", where,
+			table_name, 
+			(u_llong) row_id,
+			(u_llong) rec_id,
+			not_valid ? "not valid" : "free");
+	}
+	else
+		xt_sl_unlock_ns(db->db_error_list);
+	return OK;
+}
+
+/*
+ * -----------------------------------------------------------------------
  * Compare paths:
  */
 
@@ -425,6 +484,7 @@ xtPublic void xt_tab_init_db(XTThreadPtr
 		db->db_tables = xt_new_hashtable(self, tab_list_comp, tab_list_hash, tab_list_free, TRUE, TRUE);
 	db->db_table_by_id = xt_new_sortedlist(self, sizeof(XTTableEntryRec), 20, 20, tab_comp_by_id, db, tab_free_by_id, FALSE, FALSE);
 	db->db_table_paths = xt_new_sortedlist(self, sizeof(XTTablePathPtr), 20, 20, tab_comp_path, db, tab_free_path, FALSE, FALSE);
+	db->db_error_list = xt_new_sortedlist(self, sizeof(XTTableError), 20, 20, tab_comp_tab_error, db, NULL, TRUE, FALSE);
 
 	if (db->db_multi_path) {
 		XTOpenFilePtr	of;
@@ -649,6 +709,10 @@ xtPublic void xt_tab_exit_db(XTThreadPtr
 		xt_free_sortedlist(self, db->db_table_paths);
 		db->db_table_paths = NULL;
 	}
+	if (db->db_error_list) {
+		xt_free_sortedlist(self, db->db_error_list);
+		db->db_error_list = NULL;
+	}
 }
 
 static void tab_check_table(XTThreadPtr self, XTTableHPtr XT_UNUSED(tab))
@@ -1713,6 +1777,116 @@ xtPublic void xt_drop_table(XTThreadPtr
 	exit_();
 }
 
+xtPublic void xt_tab_check_free_lists(XTThreadPtr self, XTOpenTablePtr ot, bool check_recs, bool correct_count)
+{
+	char					table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
+	register XTTableHPtr	tab = ot->ot_table;
+	xtRowID					prev_row_id;
+	xtRowID					row_id;
+	xtRefID					next_row_id;
+	u_llong					free_count;
+
+	xt_tab_make_table_name(tab, table_name, sizeof(table_name));
+	if (check_recs) {
+		xtRecordID		prev_rec_id;
+		xtRecordID		rec_id;
+		XTTabRecExtDRec	rec_buf;
+
+		xt_lock_mutex_ns(&tab->tab_rec_lock);
+		/* Checking the free list: */
+		prev_rec_id = 0;
+		free_count = 0;
+		rec_id = tab->tab_rec_free_id;
+		while (rec_id) {
+			if (rec_id >= tab->tab_rec_eof_id) {
+				xt_logf(XT_NT_ERROR, "Table %s: invalid reference on free list: %llu, ", table_name, (u_llong) rec_id);
+				if (prev_rec_id)
+					xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_rec_id);
+				else
+					xt_logf(XT_NT_ERROR, "reference by list head pointer\n");
+				xt_tab_set_table_repair_pending(tab);
+				break;
+			}
+			if (!xt_tab_get_rec_data(ot, rec_id, XT_REC_FIX_HEADER_SIZE, (xtWord1 *) &rec_buf)) {
+				if (self)
+					xt_throw(self);
+				else
+					xt_log_and_clear_warning(ot->ot_thread);
+				break;
+			}
+			if ((rec_buf.tr_rec_type_1 & XT_TAB_STATUS_MASK) != XT_TAB_STATUS_FREED)
+				xt_logf(XT_NT_INFO, "Table %s: record, %llu, on free list is not free\n", table_name, (u_llong) rec_id);
+			free_count++;
+			prev_rec_id = rec_id;
+			rec_id = XT_GET_DISK_4(rec_buf.tr_prev_rec_id_4);
+		}
+		if (free_count != tab->tab_rec_fnum) {
+			if (correct_count) {
+				tab->tab_rec_fnum = free_count;
+				tab->tab_head_rec_fnum = free_count;
+				tab->tab_flush_pending = TRUE;
+				xt_logf(XT_NT_INFO, "Table %s: free record count (%llu) has been set to the number of records on the list: %llu\n", table_name, (u_llong) tab->tab_rec_fnum, (u_llong) free_count);
+			}
+			else
+				xt_logf(XT_NT_INFO, "Table %s: free record count (%llu) differs from the number of records on the list: %llu\n", table_name, (u_llong) tab->tab_rec_fnum, (u_llong) free_count);
+		}
+		xt_unlock_mutex_ns(&tab->tab_rec_lock);
+	}
+
+	/* Check the row free list: */
+	xt_lock_mutex_ns(&tab->tab_row_lock);
+
+	prev_row_id = 0;
+	free_count = 0;
+	row_id = tab->tab_row_free_id;
+	while (row_id) {
+		if (row_id >= tab->tab_row_eof_id) {
+			xt_logf(XT_NT_ERROR, "Table %s: invalid reference on free row: %llu, ", table_name, (u_llong) row_id);
+			if (prev_row_id)
+				xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_row_id);
+			else
+				xt_logf(XT_NT_ERROR, "reference by list head pointer\n");
+			xt_tab_set_table_repair_pending(tab);
+			break;
+		}
+		if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, row_id, &next_row_id, ot->ot_thread)) {
+			if (self)
+				xt_throw(self);
+			else
+				xt_log_and_clear_warning(ot->ot_thread);
+			break;
+		}
+		free_count++;
+		prev_row_id = row_id;
+		row_id = next_row_id;
+	}
+	if (free_count != tab->tab_row_fnum) {
+		if (correct_count) {
+			/* tab_row_fnum is the current value, and tab_head_row_fnum is the value on
+			 * disk. tab_head_row_fnum is set by the writer as the changes are applied
+			 * to the database.
+			 *
+			 * This is the value then stored in the header of the file. This value
+			 * is in sync with other changes to the file.
+			 *
+			 * So the fact that I am setting both value means this will not work at
+			 * runtime, unless all changes have been applied by the writer.
+			 *
+			 * The correct way to do this at run time would be to add the change to the
+			 * transaction log, so that it is applied by the writer.
+			 */
+			tab->tab_row_fnum = free_count;
+			tab->tab_head_row_fnum = free_count;
+			tab->tab_flush_pending = TRUE;
+			xt_logf(XT_NT_INFO, "Table %s: free row count (%llu) has been set to the number of rows on the list: %llu\n", table_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count);
+		}
+		else
+			xt_logf(XT_NT_INFO, "Table %s: free row count (%llu) differs from the number of rows on the list: %llu\n", table_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count);
+	}
+
+	xt_unlock_mutex_ns(&tab->tab_row_lock);
+}
+
 /*
  * Record buffer size:
  * -------------------
@@ -2010,7 +2184,7 @@ xtPublic void xt_check_table(XTThreadPtr
 		prec_id = rec_id;
 		rec_id = XT_GET_DISK_4(rec_buf->tr_prev_rec_id_4);
 	}
-	if (free_count2 < free_rec_count)
+	if (free_count2 != free_rec_count)
 		xt_logf(XT_INFO, "Table %s: not all free blocks (%llu) on free list: %llu\n", tab->tab_name, (u_llong) free_rec_count, (u_llong) free_count2);
 
 	freer_(); // xt_unlock_mutex_ns(&tab->tab_rec_lock);
@@ -2042,6 +2216,29 @@ xtPublic void xt_check_table(XTThreadPtr
 		rec_id++;
 	}
 
+	prec_id = 0;
+	free_count2 = 0;
+	row_id = tab->tab_row_free_id;
+	while (row_id) {
+		if (row_id >= tab->tab_row_eof_id) {
+			xt_logf(XT_INFO, "Table %s: invalid reference on free row: %llu, ", tab->tab_name, (u_llong) row_id);
+			if (prec_id)
+				xt_logf(XT_INFO, "reference by: %llu\n", (u_llong) prec_id);
+			else
+				xt_logf(XT_INFO, "reference by list head pointer\n");
+			break;
+		}
+		if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, row_id, &ref_id, self)) {
+			xt_log_and_clear_exception(self);
+			break;
+		}
+		free_count2++;
+		prec_id = row_id;
+		row_id = ref_id;
+	}
+	if (free_count2 != tab->tab_row_fnum)
+		xt_logf(XT_INFO, "Table %s: free row count (%llu) differs from the number of row on the list: %llu\n", tab->tab_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count2);
+
 	freer_(); // xt_unlock_mutex(&tab->tab_row_lock);
 
 #ifdef CHECK_INDEX_ON_CHECK_TABLE
@@ -3117,10 +3314,18 @@ static int tab_visible(register XTOpenTa
 #endif
 				break;
 			case XT_XN_REREAD:
+				/* {RETRY-READ}
+				 * TODO: This is not as "correct" as it could be.
+				 * Such records should be considered to be aborted,
+				 * and removed from the list.
+				 */
 				if (invalid_rec != var_rec_id) {
 					invalid_rec = var_rec_id;
 					goto retry_3;
 				}
+				if (!tab_record_corrupt(ot, row_id, var_rec_id, true, 1))
+					goto failed;
+
 				/* Assume end of list. */
 #ifdef XT_CRASH_DEBUG
 				/* Should not happen! */
@@ -3308,6 +3513,8 @@ xtPublic int xt_tab_visible(XTOpenTableP
 			/* Avoid infinite loop: */
 			if (read_again) {
 				/* Should not happen! */
+				if (!tab_record_corrupt(ot, row_id, ot->ot_curr_rec_id, true, 2))
+					return XT_ERR;
 #ifdef XT_CRASH_DEBUG
 				/* Generate a core dump! */
 				xt_crash_me();
@@ -3364,6 +3571,8 @@ xtPublic int xt_tab_read_record(register
 			/* Avoid infinite loop: */
 			if (read_again) {
 				/* Should not happen! */
+				if (!tab_record_corrupt(ot, XT_GET_DISK_4(((XTTabRecHeadDPtr) ot->ot_row_rbuffer)->tr_row_id_4), ot->ot_curr_rec_id, true, 3))
+					return XT_ERR;
 #ifdef XT_CRASH_DEBUG
 				/* Generate a core dump! */
 				xt_crash_me();
@@ -3580,6 +3789,7 @@ xtPublic xtBool xt_tab_free_row(XTOpenTa
 	}
 	tab->tab_row_free_id = row_id;
 	tab->tab_row_fnum++;
+	ASSERT_NS(tab->tab_row_fnum < tab->tab_row_eof_id);
 	xt_unlock_mutex_ns(&tab->tab_row_lock);
 
 	if (!xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_ROW_FREED, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &free_row, ot->ot_thread))
@@ -3776,7 +3986,7 @@ xtPublic int xt_tab_remove_record(XTOpen
 		xt_lock_mutex_ns(&tab->tab_db->db_co_ext_lock);
 		if (!xt_tab_get_rec_data(ot, rec_id, XT_REC_EXT_HEADER_SIZE, ot->ot_row_rbuffer)) {
 			xt_unlock_mutex_ns(&tab->tab_db->db_co_ext_lock);
-			return FAILED;
+			return XT_ERR;
 		}
 		xt_unlock_mutex_ns(&tab->tab_db->db_co_ext_lock);
 
@@ -3824,7 +4034,7 @@ xtPublic int xt_tab_remove_record(XTOpen
 	XT_SET_DISK_4(free_rec->rf_next_rec_id_4, prev_rec_id);
 	if (!xt_tab_put_rec_data(ot, rec_id, sizeof(XTTabRecFreeDRec), ot->ot_row_rbuffer, &op_seq)) {
 		xt_unlock_mutex_ns(&tab->tab_rec_lock);
-		return FAILED;
+		return XT_ERR;
 	}
 	tab->tab_rec_free_id = rec_id;
 	ASSERT_NS(tab->tab_rec_free_id < tab->tab_rec_eof_id);
@@ -3832,7 +4042,9 @@ xtPublic int xt_tab_remove_record(XTOpen
 	xt_unlock_mutex_ns(&tab->tab_rec_lock);
 
 	free_rec->rf_rec_type_1 = old_rec_type;
-	return xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_REC_REMOVED_BI, op_seq, (xtRecordID) new_rec_type, rec_id, rec_size, ot->ot_row_rbuffer, ot->ot_thread);
+	if (!xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_REC_REMOVED_BI, op_seq, (xtRecordID) new_rec_type, rec_id, rec_size, ot->ot_row_rbuffer, ot->ot_thread))
+		return XT_ERR;
+	return OK;
 }
 
 static xtRowID tab_new_row(XTOpenTablePtr ot, XTTableHPtr tab)
@@ -3851,6 +4063,7 @@ static xtRowID tab_new_row(XTOpenTablePt
 			return 0;
 		}
 		tab->tab_row_free_id = next_row_id;
+		ASSERT_NS(tab->tab_row_fnum > 0);
 		tab->tab_row_fnum--;
 	}
 	else {
@@ -4170,9 +4383,12 @@ static xtBool tab_wait_for_rollback(XTOp
 			return FAILED;
 		if (XT_REC_IS_CLEAN(var_head.tr_rec_type_1))
 			goto locked;
-		if (XT_REC_IS_FREE(var_head.tr_rec_type_1))
+		if (XT_REC_IS_FREE(var_head.tr_rec_type_1)) {
 			/* Should not happen: */
+			if (!tab_record_corrupt(ot, row_id, var_rec_id, false, 4))
+				return FAILED;
 			goto record_invalid;
+		}
 		xn_id = XT_GET_DISK_4(var_head.tr_xact_id_4);
 		switch (xt_xn_status(ot, xn_id, var_rec_id)) {
 			case XT_XN_VISIBLE:
@@ -4195,6 +4411,8 @@ static xtBool tab_wait_for_rollback(XTOp
 				XT_TAB_ROW_WRITE_LOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);
 				goto retry;
 			case XT_XN_REREAD:
+				if (!tab_record_corrupt(ot, row_id, var_rec_id, true, 5))
+					return FAILED;
 				goto record_invalid;
 		}
 		var_rec_id = XT_GET_DISK_4(var_head.tr_prev_rec_id_4);
@@ -4206,9 +4424,10 @@ static xtBool tab_wait_for_rollback(XTOp
 	return FAILED;
 	
 	record_invalid:
+	/* {RETRY-READ} */
 	/* Prevent an infinite loop due to a bad record: */
 	if (invalid_rec != var_rec_id) {
-		var_rec_id = invalid_rec;
+		invalid_rec = var_rec_id;
 		goto retry;
 	}
 	/* The record is invalid, it will be "overwritten"... */
@@ -4280,9 +4499,12 @@ xtPublic int xt_tab_maybe_committed(XTOp
 #ifdef TRACE_VARIATIONS_IN_DUP_CHECK
 				t_type="Re-read";
 #endif
+				/* {RETRY-READ} */
 				/* Avoid infinite loop: */
 				if (invalid_rec == rec_id) {
 					/* Should not happen! */
+					if (!tab_record_corrupt(ot, XT_GET_DISK_4(rec_head.tr_row_id_4), rec_id, true, 6))
+						goto failed;
 #ifdef XT_CRASH_DEBUG
 					/* Generate a core dump! */
 					xt_crash_me();
@@ -4327,7 +4549,7 @@ xtPublic int xt_tab_maybe_committed(XTOp
 		if (XT_REC_IS_FREE(rec_head.tr_rec_type_1)) {
 			/* Should not happen: */
 			if (invalid_rec != var_rec_id) {
-				var_rec_id = invalid_rec;
+				invalid_rec = var_rec_id;
 				goto retry;
 			}
 			/* Assume end of list. */
@@ -4364,11 +4586,14 @@ xtPublic int xt_tab_maybe_committed(XTOp
 				}
 				break;
 			case XT_XN_REREAD:
+				/* {RETRY-READ} */
 				if (invalid_rec != var_rec_id) {
-					var_rec_id = invalid_rec;
+					invalid_rec = var_rec_id;
 					goto retry;
 				}
 				/* Assume end of list. */
+				if (!tab_record_corrupt(ot, row_id, invalid_rec, true, 7))
+					goto failed;
 #ifdef XT_CRASH_DEBUG
 				/* Should not happen! */
 				xt_crash_me();
@@ -5068,6 +5293,8 @@ xtPublic xtBool xt_tab_seq_next(XTOpenTa
 				ot->ot_on_page = FALSE;
 				goto next_page;
 			}
+			if (!tab_record_corrupt(ot, XT_GET_DISK_4(((XTTabRecHeadDPtr) buff_ptr)->tr_row_id_4), invalid_rec, true, 8))
+				return XT_ERR;
 #ifdef XT_CRASH_DEBUG
 			/* Should not happen! */
 			xt_crash_me();
@@ -5240,7 +5467,7 @@ static xtBool tab_exec_repair_pending(XT
 	return FALSE;
 }
 
-static void tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size)
+xtPublic void xt_tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size)
 {
 	char	*nptr;
 
@@ -5316,7 +5543,7 @@ xtPublic xtBool xt_tab_is_table_repair_p
 {
 	char table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
 
-	tab_make_table_name(tab, table_name, sizeof(table_name));
+	xt_tab_make_table_name(tab, table_name, sizeof(table_name));
 	return tab_exec_repair_pending(tab->tab_db, REP_FIND, table_name);
 }
 
@@ -5326,7 +5553,7 @@ xtPublic void xt_tab_table_repaired(XTTa
 		char table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
 
 		tab->tab_repair_pending = FALSE;
-		tab_make_table_name(tab, table_name, sizeof(table_name));
+		xt_tab_make_table_name(tab, table_name, sizeof(table_name));
 		tab_exec_repair_pending(tab->tab_db, REP_DEL, table_name);
 	}
 }
@@ -5337,7 +5564,7 @@ xtPublic void xt_tab_set_table_repair_pe
 		char table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
 
 		tab->tab_repair_pending = TRUE;
-		tab_make_table_name(tab, table_name, sizeof(table_name));
+		xt_tab_make_table_name(tab, table_name, sizeof(table_name));
 		tab_exec_repair_pending(tab->tab_db, REP_ADD, table_name);
 	}
 }

=== modified file 'storage/pbxt/src/table_xt.h'
--- a/storage/pbxt/src/table_xt.h	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/table_xt.h	2010-09-28 13:05:45 +0000
@@ -507,6 +507,7 @@ int					xt_tab_compare_names(const char
 int					xt_tab_compare_paths(char *n1, char *n2);
 void				xt_tab_init_db(struct XTThread *self, struct XTDatabase *db);
 void				xt_tab_exit_db(struct XTThread *self, struct XTDatabase *db);
+void				xt_tab_check_free_lists(struct XTThread *self, XTOpenTablePtr ot, bool check_recs, bool correct_count);
 void				xt_check_tables(struct XTThread *self);
 
 char				*xt_tab_file_to_name(size_t size, char *tab_name, char *file_name);
@@ -572,6 +573,7 @@ xtBool				xt_tab_get_rec_data(register X
 void				xt_tab_disable_index(XTTableHPtr tab, u_int ind_error);
 void				xt_tab_set_index_error(XTTableHPtr tab);
 
+void				xt_tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size);
 xtBool				xt_tab_is_table_repair_pending(XTTableHPtr tab);
 void				xt_tab_table_repaired(XTTableHPtr tab);
 void				xt_tab_set_table_repair_pending(XTTableHPtr tab);

=== modified file 'storage/pbxt/src/thread_xt.cc'
--- a/storage/pbxt/src/thread_xt.cc	2010-05-06 12:42:28 +0000
+++ b/storage/pbxt/src/thread_xt.cc	2010-09-28 13:05:45 +0000
@@ -224,11 +224,16 @@ static void thr_log_va(XTThreadPtr self,
 #else
 	/* Use the buffer, unless it is too small */
 	va_list ap2;
+	int bufsize;
 
 	va_copy(ap2, ap);
-	if (vsnprintf(buffer, DEFAULT_LOG_BUFFER_SIZE, fmt, ap) >= DEFAULT_LOG_BUFFER_SIZE) {
-		if (vasprintf(&log_string, fmt, ap2) == -1)
+	bufsize = vsnprintf(buffer, DEFAULT_LOG_BUFFER_SIZE, fmt, ap);
+	if (bufsize >= DEFAULT_LOG_BUFFER_SIZE) {
+		log_string = (char *) malloc(bufsize + 1);
+		if (vsnprintf(log_string, bufsize + 1, fmt, ap2) > bufsize) {
+			free(log_string);
 			log_string = NULL;
+		}
 	}
 	else
 		log_string = buffer;

=== modified file 'storage/pbxt/src/xaction_xt.cc'
--- a/storage/pbxt/src/xaction_xt.cc	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/xaction_xt.cc	2010-09-28 13:05:45 +0000
@@ -1558,6 +1558,8 @@ xtPublic int xt_xn_status(XTOpenTablePtr
 		 * Because we are only here because the record was valid but not
 		 * clean (you can confirm this by looking at the code that
 		 * calls this function).
+		 *
+		 * See {RETRY-READ}
 		 */
 		return XT_XN_REREAD;
 	}
@@ -1743,7 +1745,7 @@ xtPublic xtWord8 xt_xn_bytes_to_sweep(XT
 			}
 			else {
 				xn_log_id = x_log_id;
-				x_log_offset = x_log_offset;
+				xn_log_offset = x_log_offset;
 			}
 		}
 		xn_id++;

=== modified file 'storage/pbxt/src/xt_defs.h'
--- a/storage/pbxt/src/xt_defs.h	2010-05-05 10:59:57 +0000
+++ b/storage/pbxt/src/xt_defs.h	2010-09-28 13:05:45 +0000
@@ -397,6 +397,24 @@ typedef struct XTPathStr {
  */
 #define XT_XLOG_FLUSH_FREQ				1000
 
+/*
+ * Define here if you want to check (and correct) the table free list
+ * counts. The free list counts are not durable, because they are not
+ * written to the log.
+ *
+ * The row free count is most critical because it can be used to
+ * estimate the the of rows in the record.
+ */
+#define XT_CHECK_ROW_FREE_COUNT
+#ifdef DEBUG
+#define XT_CHECK_RECORD_FREE_COUNT
+#endif
+#define XT_CORRECT_TABLE_FREE_COUNT 
+
+#if defined(XT_CHECK_ROW_FREE_COUNT) && defined(XT_CORRECT_TABLE_FREE_COUNT)
+#define XT_ROW_COUNT_CORRECTED
+#endif
+
 /* ----------------------------------------------------------------------
  * GLOBAL CONSTANTS
  */
@@ -873,7 +891,11 @@ extern "C" void session_mark_transaction
 #define MX_ULONGLONG_T						ulonglong
 #define MX_LONGLONG_T						longlong
 #define MX_CHARSET_INFO						CHARSET_INFO
-#define MX_CONST_CHARSET_INFO				struct charset_info_st			
+#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID > 50200
+#define MX_CONST_CHARSET_INFO				const struct charset_info_st
+#else
+#define MX_CONST_CHARSET_INFO				struct charset_info_st
+#endif			
 #define MX_CONST							
 #define MX_BITMAP							MY_BITMAP
 #define MX_BIT_SIZE()						n_bits



More information about the commits mailing list