Merge lp:~paul-mccullagh/maria/pbxt-1.0.11 into lp:~maria-captains/maria/5.1-converting

Proposed by Paul McCullagh
Status: Merged
Merged at revision: 2860
Proposed branch: lp:~paul-mccullagh/maria/pbxt-1.0.11
Merge into: lp:~maria-captains/maria/5.1-converting
Diff against target: 5018 lines (+1575/-531)
44 files modified
mysql-test/suite/pbxt/r/func_str.result (+1/-1)
mysql-test/suite/pbxt/r/group_min_max.result (+42/-42)
mysql-test/suite/pbxt/r/join_nested.result (+1/-1)
mysql-test/suite/pbxt/r/negation_elimination.result (+1/-1)
mysql-test/suite/pbxt/r/null.result (+1/-1)
mysql-test/suite/pbxt/r/order_by.result (+4/-4)
mysql-test/suite/pbxt/r/pbxt_ref_int.result (+2/-2)
mysql-test/suite/pbxt/r/range.result (+1/-1)
mysql-test/suite/pbxt/r/select.result (+19/-19)
storage/pbxt/ChangeLog (+105/-0)
storage/pbxt/src/backup_xt.cc (+3/-3)
storage/pbxt/src/cache_xt.cc (+87/-8)
storage/pbxt/src/cache_xt.h (+9/-5)
storage/pbxt/src/database_xt.cc (+7/-1)
storage/pbxt/src/database_xt.h (+5/-0)
storage/pbxt/src/datadic_xt.cc (+75/-49)
storage/pbxt/src/datadic_xt.h (+1/-2)
storage/pbxt/src/datalog_xt.cc (+6/-1)
storage/pbxt/src/filesys_xt.h (+1/-1)
storage/pbxt/src/ha_pbxt.cc (+213/-64)
storage/pbxt/src/index_xt.cc (+68/-24)
storage/pbxt/src/index_xt.h (+3/-3)
storage/pbxt/src/lock_xt.cc (+161/-16)
storage/pbxt/src/lock_xt.h (+61/-5)
storage/pbxt/src/locklist_xt.cc (+4/-0)
storage/pbxt/src/myxt_xt.cc (+29/-6)
storage/pbxt/src/pthread_xt.cc (+83/-19)
storage/pbxt/src/pthread_xt.h (+41/-36)
storage/pbxt/src/restart_xt.cc (+138/-6)
storage/pbxt/src/restart_xt.h (+4/-0)
storage/pbxt/src/strutil_xt.cc (+1/-1)
storage/pbxt/src/tabcache_xt.cc (+84/-30)
storage/pbxt/src/tabcache_xt.h (+3/-1)
storage/pbxt/src/table_xt.cc (+145/-101)
storage/pbxt/src/table_xt.h (+8/-3)
storage/pbxt/src/thread_xt.cc (+17/-10)
storage/pbxt/src/thread_xt.h (+6/-3)
storage/pbxt/src/trace_xt.cc (+17/-6)
storage/pbxt/src/trace_xt.h (+2/-0)
storage/pbxt/src/xaction_xt.cc (+24/-14)
storage/pbxt/src/xaction_xt.h (+2/-2)
storage/pbxt/src/xactlog_xt.cc (+69/-30)
storage/pbxt/src/xactlog_xt.h (+6/-2)
storage/pbxt/src/xt_defs.h (+15/-7)
To merge this branch: bzr merge lp:~paul-mccullagh/maria/pbxt-1.0.11
Reviewer Review Type Date Requested Status
Maria-captains Pending
Review via email: mp+24882@code.launchpad.net

Description of the change

This branch contains PBXT 1.0.11 "Pre-GA". I plan to release this version within the next 2 weeks.

All tests in the PBXT suite run through on Mac and Linux, except for one error under Linux, which is a bit weird (see below).

Nevertheless I would like to get this merged, because it is definitely a good step forward, from the previous version of PBXT in MariaDB.

I have also tested PBXT 1.0.11 with MySQL 4.1.46. All tests run through on Mac.

------------------

pbxt.select_safe [ fail ]
        Test ended at 2010-05-06 17:19:13

CURRENT_TEST: pbxt.select_safe
mysqltest: At line 19: query 'select 1 from t1,t1 as t2,t1 as t3' failed: 1104: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay

The result from queries just before the failure was:
drop table if exists t1;
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9;
create table t1 (a int auto_increment primary key, b char(20));
insert into t1 values(1,"test");
SELECT SQL_BUFFER_RESULT * from t1;
a b
1 test
update t1 set b="a" whe

To post a comment you must log in.
Revision history for this message
Kristian Nielsen (knielsen) wrote :

Paul McCullagh <email address hidden> writes:

> Paul McCullagh has proposed merging lp:~paul-mccullagh/maria/pbxt-1.0.11 into lp:maria.
>
> Requested reviews:
> Maria-captains (maria-captains)
>
>
> This branch contains PBXT 1.0.11 "Pre-GA". I plan to release this version within the next 2 weeks.

Thanks, Paul! I merged this without any issues.

This is scheduled to be included in upcoming MariaDB 5.1.46 release.

> All tests in the PBXT suite run through on Mac and Linux, except for one error under Linux, which is a bit weird (see below).

> ------------------
>
> pbxt.select_safe [ fail ]
> Test ended at 2010-05-06 17:19:13
>
> CURRENT_TEST: pbxt.select_safe
> mysqltest: At line 19: query 'select 1 from t1,t1 as t2,t1 as t3' failed: 1104: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
>
> The result from queries just before the failure was:
> drop table if exists t1;
> SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9;
> create table t1 (a int auto_increment primary key, b char(20));
> insert into t1 values(1,"test");
> SELECT SQL_BUFFER_RESULT * from t1;
> a b
> 1 test
> update t1 set b="a" whe

Yes, looks wierd. I did not get this test failure on my Linux build.

We fixed some regressions after merging with MySQL 5.1.46, maybe those also
fixed this case. Or maybe it is a random failure, and Buildbot will have more
to say on the issue.

 - Kristian.

Revision history for this message
Kristian Nielsen (knielsen) wrote :

Kristian Nielsen <email address hidden> writes:

> Paul McCullagh <email address hidden> writes:

>> All tests in the PBXT suite run through on Mac and Linux, except for one error under Linux, which is a bit weird (see below).
>
>> ------------------
>>
>> pbxt.select_safe [ fail ]
>> Test ended at 2010-05-06 17:19:13
>>
>> CURRENT_TEST: pbxt.select_safe
>> mysqltest: At line 19: query 'select 1 from t1,t1 as t2,t1 as t3' failed: 1104: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
>>
>> The result from queries just before the failure was:
>> drop table if exists t1;
>> SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9;
>> create table t1 (a int auto_increment primary key, b char(20));
>> insert into t1 values(1,"test");
>> SELECT SQL_BUFFER_RESULT * from t1;
>> a b
>> 1 test
>> update t1 set b="a" whe
>
> Yes, looks wierd. I did not get this test failure on my Linux build.
>
> We fixed some regressions after merging with MySQL 5.1.46, maybe those also
> fixed this case. Or maybe it is a random failure, and Buildbot will have more
> to say on the issue.

Hm, I can repeat it in a --valgrind run, but not in a normal run (which is
also wierd). I will take a look.

 - Kristian.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mysql-test/suite/pbxt/r/func_str.result'
2--- mysql-test/suite/pbxt/r/func_str.result 2009-08-17 15:57:58 +0000
3+++ mysql-test/suite/pbxt/r/func_str.result 2010-05-07 08:52:27 +0000
4@@ -1362,7 +1362,7 @@
5 WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00');
6 id select_type table type possible_keys key key_len ref rows filtered Extra
7 1 SIMPLE t2 const PRIMARY PRIMARY 12 const 1 100.00 Using index
8-1 SIMPLE t1 ref code code 13 const 1 100.00 Using where; Using index
9+1 SIMPLE t1 ref code code 13 const 3 100.00 Using where; Using index
10 Warnings:
11 Note 1003 select `test`.`t1`.`code` AS `code`,'a12' AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = 'a12') and (length(`test`.`t1`.`code`) = 5))
12 DROP TABLE t1,t2;
13
14=== modified file 'mysql-test/suite/pbxt/r/group_min_max.result'
15--- mysql-test/suite/pbxt/r/group_min_max.result 2009-11-24 10:19:08 +0000
16+++ mysql-test/suite/pbxt/r/group_min_max.result 2010-05-07 08:52:27 +0000
17@@ -287,52 +287,52 @@
18 b m422 p422
19 explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
20 id select_type table type possible_keys key key_len ref rows Extra
21-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
22+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
23 explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
24 id select_type table type possible_keys key key_len ref rows Extra
25-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
26+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
27 explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
28 id select_type table type possible_keys key key_len ref rows Extra
29-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 2 Using where; Using index for group-by
30+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
31 explain select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
32 id select_type table type possible_keys key key_len ref rows Extra
33-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 2 Using where; Using index for group-by
34+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
35 explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
36 id select_type table type possible_keys key key_len ref rows Extra
37 1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 129 Using where; Using index for group-by
38 explain select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
39 id select_type table type possible_keys key key_len ref rows Extra
40-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 3 Using where; Using index
41+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 96 Using where; Using index
42 explain select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
43 id select_type table type possible_keys key key_len ref rows Extra
44-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 3 Using where; Using index
45+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 96 Using where; Using index
46 explain select a1,a2,b, max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
47 id select_type table type possible_keys key key_len ref rows Extra
48-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 Using where; Using index
49+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 Using where; Using index
50 explain select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
51 id select_type table type possible_keys key key_len ref rows Extra
52-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 Using where; Using index
53+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 Using where; Using index
54 explain select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
55 id select_type table type possible_keys key key_len ref rows Extra
56-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
57+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
58 explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
59 id select_type table type possible_keys key key_len ref rows Extra
60-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 3 Using where; Using index
61+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 96 Using where; Using index
62 explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
63 id select_type table type possible_keys key key_len ref rows Extra
64-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where
65+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
66 explain select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b;
67 id select_type table type possible_keys key key_len ref rows Extra
68-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where
69+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
70 explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
71 id select_type table type possible_keys key key_len ref rows Extra
72-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where
73+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
74 explain select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
75 id select_type table type possible_keys key key_len ref rows Extra
76-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
77+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
78 explain select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
79 id select_type table type possible_keys key key_len ref rows Extra
80-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
81+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
82 explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
83 id select_type table type possible_keys key key_len ref rows Extra
84 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
85@@ -350,7 +350,7 @@
86 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL # Using where; Using index
87 explain select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
88 id select_type table type possible_keys key key_len ref rows Extra
89-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where
90+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
91 explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
92 id select_type table type possible_keys key key_len ref rows Extra
93 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
94@@ -1377,13 +1377,13 @@
95 1 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by
96 explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
97 id select_type table type possible_keys key key_len ref rows Extra
98-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 2 Using where; Using index for group-by
99+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
100 explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
101 id select_type table type possible_keys key key_len ref rows Extra
102-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 2 Using where; Using index for group-by
103+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
104 explain select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
105 id select_type table type possible_keys key key_len ref rows Extra
106-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
107+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
108 explain select a1,a2,b,min(c) from t1 where (ord(a1) > 97) and (ord(a2) + ord(a1) > 194) and (b = 'c') group by a1,a2,b;
109 id select_type table type possible_keys key key_len ref rows Extra
110 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using where; Using index for group-by
111@@ -1398,13 +1398,13 @@
112 1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
113 explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
114 id select_type table type possible_keys key key_len ref rows Extra
115-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
116+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
117 explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
118 id select_type table type possible_keys key key_len ref rows Extra
119-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
120+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
121 explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
122 id select_type table type possible_keys key key_len ref rows Extra
123-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where
124+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
125 select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
126 a1 a2 b min(c) max(c)
127 a a b e112 h112
128@@ -1500,7 +1500,7 @@
129 1 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by
130 explain select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
131 id select_type table type possible_keys key key_len ref rows Extra
132-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1 Using where
133+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 Using where; Using index
134 explain select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
135 id select_type table type possible_keys key key_len ref rows Extra
136 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where; Using index for group-by
137@@ -1512,7 +1512,7 @@
138 1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
139 explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
140 id select_type table type possible_keys key key_len ref rows Extra
141-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where
142+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where; Using index
143 select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
144 a1 a2 b
145 a a b
146@@ -1565,7 +1565,7 @@
147 Note 1003 select distinct `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`c` = 'i121') and (`test`.`t1`.`b` = 'a') and (`test`.`t1`.`a2` >= 'b'))
148 explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
149 id select_type table type possible_keys key key_len ref rows Extra
150-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1 Using where
151+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 Using where; Using index
152 explain select distinct b from t1 where (a2 >= 'b') and (b = 'a');
153 id select_type table type possible_keys key key_len ref rows Extra
154 1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
155@@ -1582,7 +1582,7 @@
156 Note 1003 select distinct `test`.`t2`.`a1` AS `a1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where ((`test`.`t2`.`c` = 'i121') and (`test`.`t2`.`b` = 'a') and (`test`.`t2`.`a2` >= 'b'))
157 explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
158 id select_type table type possible_keys key key_len ref rows Extra
159-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where
160+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where; Using index
161 explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');
162 id select_type table type possible_keys key key_len ref rows Extra
163 1 SIMPLE t2 index NULL idx_t2_2 146 NULL 164 Using where; Using index
164@@ -1711,7 +1711,7 @@
165 1 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by
166 explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
167 id select_type table type possible_keys key key_len ref rows Extra
168-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1 Using where
169+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 Using where; Using index
170 explain select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
171 id select_type table type possible_keys key key_len ref rows Extra
172 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using where; Using index for group-by; Using temporary; Using filesort
173@@ -1726,7 +1726,7 @@
174 1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
175 explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
176 id select_type table type possible_keys key key_len ref rows Extra
177-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where
178+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where; Using index
179 explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
180 id select_type table type possible_keys key key_len ref rows Extra
181 1 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort
182@@ -1806,7 +1806,7 @@
183 1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
184 explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
185 id select_type table type possible_keys key key_len ref rows filtered Extra
186-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_0 65 NULL 1 100.00 Using where
187+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
188 Warnings:
189 Note 1003 select count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`b` = 'c') and (`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
190 explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
191@@ -1814,7 +1814,7 @@
192 1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
193 explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
194 id select_type table type possible_keys key key_len ref rows filtered Extra
195-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_0 65 NULL 1 100.00 Using where
196+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
197 Warnings:
198 Note 1003 select (ord(`test`.`t1`.`a1`) + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`)) AS `ord(a1) + count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
199 select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
200@@ -1834,16 +1834,16 @@
201 104
202 explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
203 id select_type table type possible_keys key key_len ref rows Extra
204-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
205+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
206 explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
207 id select_type table type possible_keys key key_len ref rows Extra
208-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
209+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
210 explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
211 id select_type table type possible_keys key key_len ref rows Extra
212-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
213+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
214 explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
215 id select_type table type possible_keys key key_len ref rows Extra
216-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where
217+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
218 explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
219 id select_type table type possible_keys key key_len ref rows Extra
220 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using index for group-by
221@@ -1922,19 +1922,19 @@
222 explain extended select a1,a2,min(b),max(b) from t1
223 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;
224 id select_type table type possible_keys key key_len ref rows filtered Extra
225-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 100.00 Using where; Using index
226+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 100.00 Using where; Using index
227 Warnings:
228 Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,min(`test`.`t1`.`b`) AS `min(b)`,max(`test`.`t1`.`b`) AS `max(b)` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`c` > 'a111')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`
229 explain extended select a1,a2,b,min(c),max(c) from t1
230 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;
231 id select_type table type possible_keys key key_len ref rows filtered Extra
232-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 130 NULL 4 100.00 Using where
233+1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 50.00 Using where; Using temporary; Using filesort
234 Warnings:
235 Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,min(`test`.`t1`.`c`) AS `min(c)`,max(`test`.`t1`.`c`) AS `max(c)` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`d` > 'xy2')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
236 explain extended select a1,a2,b,c from t1
237 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;
238 id select_type table type possible_keys key key_len ref rows filtered Extra
239-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 100.00 Using where
240+1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 50.00 Using where; Using temporary; Using filesort
241 Warnings:
242 Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`d` > 'xy2')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`,`test`.`t1`.`c`
243 explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;
244@@ -1942,7 +1942,7 @@
245 1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
246 explain extended select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b;
247 id select_type table type possible_keys key key_len ref rows filtered Extra
248-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 100.00 Using where; Using index
249+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 100.00 Using where; Using index
250 Warnings:
251 Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`c` > 'a111')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
252 explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
253@@ -1966,12 +1966,12 @@
254 1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using index
255 explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
256 id select_type table type possible_keys key key_len ref rows filtered Extra
257-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 100.00 Using where
258+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
259 Warnings:
260 Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,count(`test`.`t1`.`a2`) AS `count(a2)` from `test`.`t1` where (`test`.`t1`.`a1` > 'a') group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
261 explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
262 id select_type table type possible_keys key key_len ref rows filtered Extra
263-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 100.00 Using where
264+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
265 Warnings:
266 Note 1003 select sum(ord(`test`.`t1`.`a1`)) AS `sum(ord(a1))` from `test`.`t1` where (`test`.`t1`.`a1` > 'a') group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
267 explain select distinct(a1) from t1 where ord(a2) = 98;
268@@ -2047,10 +2047,10 @@
269 BB
270 EXPLAIN SELECT a FROM t1 WHERE a='AA' GROUP BY a;
271 id select_type table type possible_keys key key_len ref rows Extra
272-1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 1 Using where; Using index
273+1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 3 Using where; Using index
274 EXPLAIN SELECT a FROM t1 WHERE a='BB' GROUP BY a;
275 id select_type table type possible_keys key key_len ref rows Extra
276-1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 1 Using where; Using index
277+1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 3 Using where; Using index
278 SELECT DISTINCT a FROM t1 WHERE a='BB';
279 a
280 BB
281
282=== modified file 'mysql-test/suite/pbxt/r/join_nested.result'
283--- mysql-test/suite/pbxt/r/join_nested.result 2009-12-27 16:48:27 +0000
284+++ mysql-test/suite/pbxt/r/join_nested.result 2010-05-07 08:52:27 +0000
285@@ -1055,7 +1055,7 @@
286 (t8.b=t9.b OR t8.c IS NULL) AND
287 (t9.a=1);
288 id select_type table type possible_keys key key_len ref rows Extra
289-1 SIMPLE t0 ref idx_a idx_a 5 const 1
290+1 SIMPLE t0 ref idx_a idx_a 5 const 2
291 1 SIMPLE t1 ref idx_b idx_b 5 test.t0.b 1
292 1 SIMPLE t2 ALL NULL NULL NULL NULL 3
293 1 SIMPLE t3 ALL NULL NULL NULL NULL 2
294
295=== modified file 'mysql-test/suite/pbxt/r/negation_elimination.result'
296--- mysql-test/suite/pbxt/r/negation_elimination.result 2009-11-24 10:19:08 +0000
297+++ mysql-test/suite/pbxt/r/negation_elimination.result 2010-05-07 08:52:27 +0000
298@@ -388,7 +388,7 @@
299 test.t1 analyze status OK
300 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));
301 id select_type table type possible_keys key key_len ref rows filtered Extra
302-1 SIMPLE t1 index NULL a 5 NULL 5 100.00 Using where; Using index
303+1 SIMPLE t1 index NULL a 5 NULL 21 100.00 Using where; Using index
304 Warnings:
305 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`
306 drop table t1;
307
308=== modified file 'mysql-test/suite/pbxt/r/null.result'
309--- mysql-test/suite/pbxt/r/null.result 2009-08-17 15:57:58 +0000
310+++ mysql-test/suite/pbxt/r/null.result 2010-05-07 08:52:27 +0000
311@@ -179,7 +179,7 @@
312 Warning 1265 Data truncated for column 'i' at row 513
313 explain select * from t1 where i=2 or i is null;
314 id select_type table type possible_keys key key_len ref rows Extra
315-1 SIMPLE t1 ref i i 4 const 1 Using index
316+1 SIMPLE t1 ref i i 4 const 25 Using index
317 select count(*) from t1 where i=2 or i is null;
318 count(*)
319 9
320
321=== modified file 'mysql-test/suite/pbxt/r/order_by.result'
322--- mysql-test/suite/pbxt/r/order_by.result 2009-04-02 10:03:14 +0000
323+++ mysql-test/suite/pbxt/r/order_by.result 2010-05-07 08:52:27 +0000
324@@ -401,14 +401,14 @@
325 1 0
326 explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
327 id select_type table type possible_keys key key_len ref rows Extra
328-1 SIMPLE t1 index a a 20 NULL 11 Using where; Using index
329+1 SIMPLE t1 range a a 20 NULL 7 Using where; Using index
330 select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
331 a b c
332 1 1 b
333 1 1 b
334 explain select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
335 id select_type table type possible_keys key key_len ref rows Extra
336-1 SIMPLE t1 range a a 4 NULL 1 Using where; Using index
337+1 SIMPLE t1 range a a 4 NULL 6 Using where; Using index
338 select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
339 a b c
340 1 1 b
341@@ -432,7 +432,7 @@
342 1 1
343 explain select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
344 id select_type table type possible_keys key key_len ref rows Extra
345-1 SIMPLE t1 range a a 8 NULL 1 Using where; Using index
346+1 SIMPLE t1 range a a 8 NULL 6 Using where; Using index
347 select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
348 a b c
349 2 1 b
350@@ -444,7 +444,7 @@
351 1 0
352 explain select * from t1 where a between 0 and 1 order by a desc, b desc;
353 id select_type table type possible_keys key key_len ref rows Extra
354-1 SIMPLE t1 range a a 4 NULL 1 Using where; Using index
355+1 SIMPLE t1 range a a 4 NULL 6 Using where; Using index
356 select * from t1 where a between 0 and 1 order by a desc, b desc;
357 a b c
358 1 3 b
359
360=== modified file 'mysql-test/suite/pbxt/r/pbxt_ref_int.result'
361--- mysql-test/suite/pbxt/r/pbxt_ref_int.result 2009-08-17 15:57:58 +0000
362+++ mysql-test/suite/pbxt/r/pbxt_ref_int.result 2010-05-07 08:52:27 +0000
363@@ -14,7 +14,7 @@
364 drop table t1;
365 set foreign_key_checks = 1;
366 INSERT INTO t2 VALUES(2);
367-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `t1` not found)
368+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `test.t1` not found)
369 drop table if exists parent, child, child_child;
370 CREATE TABLE parent (
371 id INT NOT NULL,
372@@ -370,7 +370,7 @@
373 CREATE TABLE t2 (s1 INT DEFAULT NULL, FOREIGN KEY (s1) REFERENCES t1 (s1));
374 set foreign_key_checks = 1;
375 insert into t2 values (1);
376-ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `t1` not found)
377+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `test.t1` not found)
378 set foreign_key_checks = 0;
379 insert into t2 values (1);
380 CREATE TABLE t1 (s1 INT PRIMARY KEY);
381
382=== modified file 'mysql-test/suite/pbxt/r/range.result'
383--- mysql-test/suite/pbxt/r/range.result 2009-08-17 15:57:58 +0000
384+++ mysql-test/suite/pbxt/r/range.result 2010-05-07 08:52:27 +0000
385@@ -964,5 +964,5 @@
386 In following EXPLAIN the access method should be ref, #rows~=500 (and not 2)
387 explain select * from t2 where a=1000 and b<11;
388 id select_type table type possible_keys key key_len ref rows Extra
389-1 SIMPLE t2 range a a 10 NULL 1 Using where
390+1 SIMPLE t2 range a a 10 NULL 2 Using where
391 drop table t1, t2;
392
393=== modified file 'mysql-test/suite/pbxt/r/select.result'
394--- mysql-test/suite/pbxt/r/select.result 2009-10-07 16:56:11 +0000
395+++ mysql-test/suite/pbxt/r/select.result 2010-05-07 08:52:27 +0000
396@@ -1384,52 +1384,52 @@
397 test.t2 analyze status OK
398 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
399 id select_type table type possible_keys key key_len ref rows Extra
400-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
401+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
402 1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
403 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;
404 id select_type table type possible_keys key key_len ref rows Extra
405-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
406+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
407 1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
408 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
409 id select_type table type possible_keys key key_len ref rows Extra
410-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
411+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
412 1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
413 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
414 id select_type table type possible_keys key key_len ref rows Extra
415 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
416-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
417+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
418 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
419 id select_type table type possible_keys key key_len ref rows Extra
420 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
421-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
422+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
423 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
424 id select_type table type possible_keys key key_len ref rows Extra
425 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
426-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
427+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
428 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
429 id select_type table type possible_keys key key_len ref rows Extra
430 1 SIMPLE t4 ALL NULL NULL NULL NULL 12
431-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
432+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
433 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;
434 id select_type table type possible_keys key key_len ref rows Extra
435 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12
436-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
437+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
438 explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;
439 id select_type table type possible_keys key key_len ref rows Extra
440 1 SIMPLE t4 ALL NULL NULL NULL NULL 12
441-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
442+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
443 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
444 id select_type table type possible_keys key key_len ref rows Extra
445 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
446-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
447+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
448 explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
449 id select_type table type possible_keys key key_len ref rows Extra
450 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
451-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
452+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
453 explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
454 id select_type table type possible_keys key key_len ref rows Extra
455 1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
456-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
457+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
458 select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
459 companynr companynr
460 37 36
461@@ -1437,7 +1437,7 @@
462 explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
463 id select_type table type possible_keys key key_len ref rows Extra
464 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary
465-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer
466+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Using join buffer
467 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;
468 fld1 companynr fld3 period
469 038008 37 reporters 1008
470@@ -1511,7 +1511,7 @@
471 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
472 explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
473 id select_type table type possible_keys key key_len ref rows filtered Extra
474-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 100.00 Using where
475+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 100.00 Using where
476 Warnings:
477 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` <> ''))
478 select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
479@@ -1955,7 +1955,7 @@
480 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
481 explain select fld3 from t2 where fld1=fld1;
482 id select_type table type possible_keys key key_len ref rows Extra
483-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
484+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
485 select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
486 companynr fld1
487 34 250501
488@@ -2007,7 +2007,7 @@
489 4181
490 explain select min(fld1),max(fld1),count(*) from t2;
491 id select_type table type possible_keys key key_len ref rows Extra
492-1 SIMPLE t2 index NULL fld1 4 NULL 1199 Using index
493+1 SIMPLE t2 index NULL fld1 4 NULL 1200 Using index
494 select min(fld1),max(fld1),count(*) from t2;
495 min(fld1) max(fld1) count(*)
496 0 1232609 1199
497@@ -2093,9 +2093,9 @@
498 Field Type Collation Null Key Default Extra Privileges Comment
499 show keys from t2;
500 Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
501-t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE
502-t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE
503-t2 1 fld3 1 fld3 A 1199 NULL NULL BTREE
504+t2 0 PRIMARY 1 auto A 1200 NULL NULL BTREE
505+t2 0 fld1 1 fld1 A 1200 NULL NULL BTREE
506+t2 1 fld3 1 fld3 A 1200 NULL NULL BTREE
507 drop table t4, t3, t2, t1;
508 DO 1;
509 DO benchmark(100,1+1),1,1;
510
511=== modified file 'storage/pbxt/ChangeLog'
512--- storage/pbxt/ChangeLog 2009-12-21 13:13:15 +0000
513+++ storage/pbxt/ChangeLog 2010-05-07 08:52:27 +0000
514@@ -1,6 +1,111 @@
515 PBXT Release Notes
516 ==================
517
518++------- 1.0.11 Pre-GA - 2010-05-11
519+
520+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.
521+
522+RN321: Added "Extended record count" to the CHECK TABLE output. This indicates the number of records that have a data log component.
523+
524+RN320: All tests now run with MySQL 5.1.46.
525+
526+------- 1.0.10n RC4 - 2010-04-28
527+
528+RN319: Fix RN1/3 and RN1/4 back-ported from 1.1: Fixed a deadlock that could occur during low index cache situations and added some checks for index corruption, and added the try lock variation for R/W locks.
529+
530+RN318: Fixed a bug in the atomic R/W lock. This bug occurred on multi-core Linux when under extrem load. The affect was that an index lookup could fail. The index was not corrupted.
531+
532+------- 1.0.10m RC4 - 2010-03-29
533+
534+RN317: This change prevents a unscheduled checkpoint from occurring when the sweeper has work to do. Checkpoint required due to the Checkpoint threshold reached are done as usual.
535+
536+------- 1.0.10k RC4 - 2010-03-29
537+
538+RN316: Set the maximum delay, while waiting for previous transactions to commit to 1/100s. This situation occurs when cleanup begins of a long running transaction.
539+
540+RN315: Fixed a bug that could lead to a data log error, for example: Data log not found: '.../dlog-129602.xt'. This error occurred after a duplicate key error, dending on the table structure, because the row buffer was not restored after writing an extended record.
541+
542+RN314: Server startup time could be very long when data logs become large because the log size was not save in the header when a data log is full.
543+
544+------- 1.0.10j RC4 - 2010-03-24
545+
546+RN313: Fixed an error in the calculation of the handle data record (.xtd files) size when AVG_ROW_LENGTH is set explicitly to a value less than 12. For example:
547+
548+CREATE TABLE objs (
549+ id int(10) unsigned NOT NULL,
550+ objdata mediumblob NOT NULL,
551+ PRIMARY KEY (id)
552+) ENGINE=PBXT AVG_ROW_LENGTH=10
553+
554+This table definition previously lead to corruption of the table because the handle data record was set to 24 (14+10), which is less than the minimum (for variable length records) handle data record size of 26.
555+
556+This minimum consists of 14 byte record header and 12 bytes reference to the extended record data (the part of the record in the data log).
557+
558+Tip: when setting AVG_ROW_LENGTH you should normally add 12 to the average row length estimate to ensure that the average length part of the record is always in the handle data file. This is important, for example if you wish to make sure that the rows used to build indexes are in the handle data file. CHECK TABLE tells you how many rows are in the "fixed length part" of the record (output in MySQL error log). In the example above, this would be AVG_ROW_LENGTH=17.
559+
560+The maximum size of a field can be calculated adding the maximum byte size as described here: http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html, and then add the following values, depending on the byte size:
561+
562+byte size <= 240, add 1
563+byte size < 2^16 (65536), add 3
564+byte size < 2^24 (16777216), add 4
565+byte size > 2^24, add 5
566+
567+------- 1.0.10i RC4 - 2010-03-17
568+
569+RN312: Fixed bug #534361: Valgrind error: write of uninitialised bytes in xt_flush_indices()
570+
571+RN311: Fixed ilog corruption when running out of disk space during an index flush operation, which lead to corruption of the index.
572+
573+------- 1.0.10h RC4 - 2010-02-25
574+
575+RN310: Fixed Windows atomic INC/DEC operations, which lead to atomic R/W lock not working correctly. The result was that some index entries were not foound.
576+
577+RN309: Fixed a bug that caused a crash when the index was corrupted. The crash occurs if the index page in not completely written, and an item in the index has a bad length.
578+
579+RN308: Fixed bug #509803: can't run tpcc (cannot compare FKs that rely on indexes of different length).
580+
581+------- 1.0.10g RC4 - 2010-02-11
582+
583+RN307: 2010-02-15: Set the internal version number 1.0.10g.
584+
585+RN306: All tests now run with MySQL 5.1.42.
586+
587+RN305: Fixed a bug that could cause a crash in filesort. The problem was that the return row estimate was incorrect, which caused the result of estimate_rows_upper_bound() to overflow to zero. Row estimate has been changed, and no longer takes into account deleted rows (so the row estimate is now a maximum).
588+
589+RN304: Fixed bug #513012: On a table with a trigger the same record is updated more than once in one statement
590+
591+------- 1.0.10f RC4 - 2010-01-29
592+
593+RN303: Fix RN1/10 back-ported from 1.1: Fixed a bug in the record cache that caused PBXT to think it had run out of cache memory. The effect was that PBXT used less and less cache over time. The bug occurs during heavy concurrent access on the record cache. The affect is the PBXT gets slower and slower.
594+
595+RN302: Fix RN1/11 back-ported from 1.1: Corrected a problem that sometimes caused a pause in activity when the record cache was full.
596+
597+------- 1.0.10e RC4 - 2010-01-25
598+
599+RN301: Fixed index statistics calculation. This bug lead to the wrong indices being selected by the optimizer because all indices returned the same cost.
600+
601+RN300: Fixed bug #509968: START TRANSACTION WITH CONSISTENT SNAPSHOT breaks transactional flow.
602+
603+RN299: Fixed bug #509218: Server asserts with Assertion `mutex->__data.__owner == 0' failed on high concurrency OLTP test.
604+
605+------- 1.0.10d RC4 - 2010-01-11
606+
607+RN298: Fixed a bug that caused huge amounts of transaction log to be written when pbxt_flush_log_at_trx_commit = 2.
608+
609+------- 1.0.10c RC4 - 2009-12-29
610+
611+RN297: Updated "LOCK TABLES ... READ LOCAL" behavior to be more restrictive and compatible with InnoDB
612+
613+RN296: Fixed bug #499026: START TRANSACTION WITH CONSISTENT SNAPSHOT does not work for PBXT
614+
615+------- 1.0.10 RC4 - 2009-12-18
616+
617+RN295: PBXT tests now all run with MySQL 5.1.41.
618+
619+RN294: Fixed bug #483714: a broken table can prevent other tables from opening
620+
621+RN293: Added system variable pbxt_flush_log_at_trx_commit. The value of this variable determines whether the transaction log is written and/or flushed when a transaction is ended. A value of 0 means don't write or flush the transaction log, 1 means write and flush and 2 means write, but do not flush. No matter what the setting is choosen, the transaction log is written and flushed at least once per second.
622+
623 ------- 1.0.09g RC3 - 2009-12-16
624
625 RN292: Fixed a bug that resulted in 2-phase commit not being used between PBXT and the binlog. This bug was a result of a hack which as added to solve a problem in an pre-release version of MySQL 5.1. The hack was removed.
626
627=== modified file 'storage/pbxt/src/backup_xt.cc'
628--- storage/pbxt/src/backup_xt.cc 2009-11-24 10:55:06 +0000
629+++ storage/pbxt/src/backup_xt.cc 2010-05-07 08:52:27 +0000
630@@ -287,7 +287,7 @@
631 bd_table_no++;
632 try_(a) {
633 xt_ha_open_database_of_table(self, (XTPathStrPtr) path);
634- tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);
635+ tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE);
636 pushr_(xt_heap_release, tab);
637 if (!(bd_ot = xt_db_open_table_using_tab(tab, bd_thread)))
638 xt_throw(self);
639@@ -403,7 +403,7 @@
640 bd_thread->st_abort_trans = FALSE;
641 bd_thread->st_stat_ended = FALSE;
642 bd_thread->st_stat_trans = FALSE;
643- bd_thread->st_is_update = FALSE;
644+ bd_thread->st_is_update = NULL;
645 if (!xt_xn_begin(bd_thread))
646 return backup::ERROR;
647 bd_state = BUP_STATE_AFTER_LOCK;
648@@ -562,7 +562,7 @@
649 m_tables[rd_table_no-1].internal_name(path, sizeof(path));
650 try_(a) {
651 xt_ha_open_database_of_table(self, (XTPathStrPtr) path);
652- tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);
653+ tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE);
654 pushr_(xt_heap_release, tab);
655 if (!(rd_ot = xt_db_open_table_using_tab(tab, rd_thread)))
656 xt_throw(self);
657
658=== modified file 'storage/pbxt/src/cache_xt.cc'
659--- storage/pbxt/src/cache_xt.cc 2009-11-24 10:55:06 +0000
660+++ storage/pbxt/src/cache_xt.cc 2010-05-07 08:52:27 +0000
661@@ -90,7 +90,7 @@
662 #define IDX_CAC_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, &(i)->cs_lock)
663 #define IDX_CAC_FREE_LOCK(s, i) xt_spinxslock_free(s, &(i)->cs_lock)
664 #define IDX_CAC_READ_LOCK(i, s) xt_spinxslock_slock(&(i)->cs_lock, (s)->t_id)
665-#define IDX_CAC_WRITE_LOCK(i, s) xt_spinxslock_xlock(&(i)->cs_lock, (s)->t_id)
666+#define IDX_CAC_WRITE_LOCK(i, s) xt_spinxslock_xlock(&(i)->cs_lock, FALSE, (s)->t_id)
667 #define IDX_CAC_UNLOCK(i, s) xt_spinxslock_unlock(&(i)->cs_lock, (s)->t_id)
668 #endif
669
670@@ -178,6 +178,7 @@
671 KEY_CACHE my_cache;
672 #undef pthread_rwlock_rdlock
673 #undef pthread_rwlock_wrlock
674+#undef pthread_rwlock_try_wrlock
675 #undef pthread_rwlock_unlock
676 #undef pthread_mutex_lock
677 #undef pthread_mutex_unlock
678@@ -410,7 +411,7 @@
679 /* Because of the lock order, I have to release the
680 * handle before I get a lock on the cache block.
681 *
682- * But, by doing this, thie cache block may be gone!
683+ * But, by doing this, this cache block may be gone!
684 */
685 if (block) {
686 IDX_CAC_READ_LOCK(seg, thread);
687@@ -420,6 +421,11 @@
688 /* Found the block...
689 * {HANDLE-COUNT-SLOCK}
690 * 04.05.2009, changed to slock.
691+ * The xlock causes too much contention
692+ * on the cache block for read only loads.
693+ *
694+ * Is it safe?
695+ * See below...
696 */
697 XT_IPAGE_READ_LOCK(&block->cb_lock);
698 goto block_found;
699@@ -691,6 +697,9 @@
700 }
701 }
702
703+ /* Must be done before freeing the blocks! */
704+ ind_handle_exit(self);
705+
706 if (ind_cac_globals.cg_blocks) {
707 xt_free(self, ind_cac_globals.cg_blocks);
708 ind_cac_globals.cg_blocks = NULL;
709@@ -702,7 +711,6 @@
710 ind_cac_globals.cg_buffer = NULL;
711 }
712 #endif
713- ind_handle_exit(self);
714
715 memset(&ind_cac_globals, 0, sizeof(ind_cac_globals));
716 }
717@@ -882,7 +890,58 @@
718 while (xblock) {
719 if (block == xblock) {
720 /* Found the block... */
721- XT_IPAGE_WRITE_LOCK(&block->cb_lock, ot->ot_thread->t_id);
722+ /* It is possible that a thread enters this code holding a
723+ * lock on a page. This can cause a deadlock:
724+ *
725+ * #0 0x91faa2ce in semaphore_wait_signal_trap
726+ * #1 0x91fb1da5 in pthread_mutex_lock
727+ * #2 0x00e2ec13 in xt_p_mutex_lock at pthread_xt.cc:544
728+ * #3 0x00e6c30a in xt_xsmutex_xlock at lock_xt.cc:1547
729+ * #4 0x00dee402 in ind_free_block at cache_xt.cc:879
730+ * #5 0x00dee76a in ind_cac_free_lru_blocks at cache_xt.cc:1033
731+ * #6 0x00def8d1 in xt_ind_reserve at cache_xt.cc:1513
732+ * #7 0x00e22118 in xt_idx_insert at index_xt.cc:2047
733+ * #8 0x00e4d7ee in xt_tab_new_record at table_xt.cc:4702
734+ * #9 0x00e0ff0b in ha_pbxt::write_row at ha_pbxt.cc:2340
735+ * #10 0x0023a00f in handler::ha_write_row at handler.cc:4570
736+ * #11 0x001a32c8 in write_record at sql_insert.cc:1568
737+ * #12 0x001ab635 in mysql_insert at sql_insert.cc:812
738+ * #13 0x0010e068 in mysql_execute_command at sql_parse.cc:3066
739+ * #14 0x0011480d in mysql_parse at sql_parse.cc:5787
740+ * #15 0x00115afb in dispatch_command at sql_parse.cc:1200
741+ * #16 0x00116de2 in do_command at sql_parse.cc:857
742+ * #17 0x00101ee4 in handle_one_connection at sql_connect.cc:1115
743+ * #18 0x91fdb155 in _pthread_start
744+ * #19 0x91fdb012 in thread_start
745+ *
746+ * #0 0x91fb146e in __semwait_signal
747+ * #1 0x91fb12ef in nanosleep$UNIX2003
748+ * #2 0x91fb1236 in usleep$UNIX2003
749+ * #3 0x00e52112 in xt_yield at thread_xt.cc:1274
750+ * #4 0x00e6c0eb in xt_spinxslock_xlock at lock_xt.cc:1456
751+ * #5 0x00dee444 in ind_free_block at cache_xt.cc:886
752+ * #6 0x00dee76a in ind_cac_free_lru_blocks at cache_xt.cc:1033
753+ * #7 0x00deeaf0 in ind_cac_fetch at cache_xt.cc:1130
754+ * #8 0x00def604 in xt_ind_fetch at cache_xt.cc:1386
755+ * #9 0x00e2159a in xt_idx_update_row_id at index_xt.cc:2489
756+ * #10 0x00e603c8 in xn_sw_clean_indices at xaction_xt.cc:1932
757+ * #11 0x00e606d4 in xn_sw_cleanup_variation at xaction_xt.cc:2056
758+ * #12 0x00e60e29 in xn_sw_cleanup_xact at xaction_xt.cc:2276
759+ * #13 0x00e615ed in xn_sw_main at xaction_xt.cc:2433
760+ * #14 0x00e61919 in xn_sw_run_thread at xaction_xt.cc:2564
761+ * #15 0x00e53f80 in thr_main at thread_xt.cc:1017
762+ * #16 0x91fdb155 in _pthread_start
763+ * #17 0x91fdb012 in thread_start
764+ *
765+ * So we back off if a lock is held!
766+ */
767+ if (!XT_IPAGE_WRITE_TRY_LOCK(&block->cb_lock, ot->ot_thread->t_id)) {
768+ IDX_CAC_UNLOCK(seg, ot->ot_thread);
769+#ifdef DEBUG_CHECK_IND_CACHE
770+ xt_ind_check_cache(NULL);
771+#endif
772+ return FALSE;
773+ }
774 if (block->cb_state != IDX_CAC_BLOCK_CLEAN) {
775 /* This block cannot be freeed: */
776 XT_IPAGE_UNLOCK(&block->cb_lock, TRUE);
777@@ -1376,6 +1435,7 @@
778 register XTIndBlockPtr block;
779 DcSegmentPtr seg;
780 xtWord2 branch_size;
781+ u_int rec_size;
782 xtBool xlock = FALSE;
783
784 #ifdef DEBUG
785@@ -1386,10 +1446,24 @@
786 return FAILED;
787
788 branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2);
789- if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) {
790- IDX_CAC_UNLOCK(seg, ot->ot_thread);
791- xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
792- return FAILED;
793+ rec_size = XT_GET_INDEX_BLOCK_LEN(branch_size);
794+ if (rec_size < 2 || rec_size > XT_INDEX_PAGE_SIZE)
795+ goto failed_corrupt;
796+ if (ind->mi_fix_key) {
797+ rec_size -= 2;
798+ if (XT_IS_NODE(branch_size)) {
799+ if (rec_size != 0) {
800+ if (rec_size < XT_NODE_REF_SIZE)
801+ goto failed_corrupt;
802+ rec_size -= XT_NODE_REF_SIZE;
803+ if ((rec_size % (ind->mi_key_size + XT_RECORD_REF_SIZE + XT_NODE_REF_SIZE)) != 0)
804+ goto failed_corrupt;
805+ }
806+ }
807+ else {
808+ if ((rec_size % (ind->mi_key_size + XT_RECORD_REF_SIZE)) != 0)
809+ goto failed_corrupt;
810+ }
811 }
812
813 switch (ltype) {
814@@ -1450,6 +1524,11 @@
815 iref->ir_block = block;
816 iref->ir_branch = (XTIdxBranchDPtr) block->cb_data;
817 return OK;
818+
819+ failed_corrupt:
820+ IDX_CAC_UNLOCK(seg, ot->ot_thread);
821+ xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
822+ return FAILED;
823 }
824
825 xtPublic xtBool xt_ind_release(XTOpenTablePtr ot, XTIndexPtr ind, XTPageUnlockType XT_NDEBUG_UNUSED(utype), XTIndReferencePtr iref)
826
827=== modified file 'storage/pbxt/src/cache_xt.h'
828--- storage/pbxt/src/cache_xt.h 2009-11-24 10:55:06 +0000
829+++ storage/pbxt/src/cache_xt.h 2010-05-07 08:52:27 +0000
830@@ -58,7 +58,8 @@
831 #define XT_IPAGE_INIT_LOCK(s, i) xt_atomicrwlock_init_with_autoname(s, i)
832 #define XT_IPAGE_FREE_LOCK(s, i) xt_atomicrwlock_free(s, i)
833 #define XT_IPAGE_READ_LOCK(i) xt_atomicrwlock_slock(i)
834-#define XT_IPAGE_WRITE_LOCK(i, o) xt_atomicrwlock_xlock(i, o)
835+#define XT_IPAGE_WRITE_LOCK(i, o) xt_atomicrwlock_xlock(i, FALSE, o)
836+#define XT_IPAGE_WRITE_TRY_LOCK(i, o) xt_atomicrwlock_xlock(i, TRUE, o)
837 #define XT_IPAGE_UNLOCK(i, x) xt_atomicrwlock_unlock(i, x)
838 #elif defined(XT_IPAGE_USE_PTHREAD_RW)
839 #define XT_IPAGE_LOCK_TYPE xt_rwlock_type
840@@ -66,20 +67,23 @@
841 #define XT_IPAGE_FREE_LOCK(s, i) xt_free_rwlock(i)
842 #define XT_IPAGE_READ_LOCK(i) xt_slock_rwlock_ns(i)
843 #define XT_IPAGE_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i)
844+#define XT_IPAGE_WRITE_TRY_LOCK(i, s) xt_xlock_try_rwlock_ns(i)
845 #define XT_IPAGE_UNLOCK(i, x) xt_unlock_rwlock_ns(i)
846 #elif defined(XT_IPAGE_USE_SPINXSLOCK)
847 #define XT_IPAGE_LOCK_TYPE XTSpinXSLockRec
848 #define XT_IPAGE_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
849 #define XT_IPAGE_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
850 #define XT_IPAGE_READ_LOCK(i) xt_spinxslock_slock(i)
851-#define XT_IPAGE_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, o)
852+#define XT_IPAGE_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, FALSE, o)
853+#define XT_IPAGE_WRITE_TRY_LOCK(i, o) xt_spinxslock_xlock(i, TRUE, o)
854 #define XT_IPAGE_UNLOCK(i, x) xt_spinxslock_unlock(i, x)
855 #else // XT_IPAGE_USE_SKEW_RW
856 #define XT_IPAGE_LOCK_TYPE XTSkewRWLockRec
857 #define XT_IPAGE_INIT_LOCK(s, i) xt_skewrwlock_init_with_autoname(s, i)
858 #define XT_IPAGE_FREE_LOCK(s, i) xt_skewrwlock_free(s, i)
859 #define XT_IPAGE_READ_LOCK(i) xt_skewrwlock_slock(i)
860-#define XT_IPAGE_WRITE_LOCK(i, o) xt_skewrwlock_xlock(i, o)
861+#define XT_IPAGE_WRITE_LOCK(i, o) xt_skewrwlock_xlock(i, FALSE, o)
862+#define XT_IPAGE_WRITE_TRY_LOCK(i, o) xt_skewrwlock_xlock(i, TRUE, o)
863 #define XT_IPAGE_UNLOCK(i, x) xt_skewrwlock_unlock(i, x)
864 #endif
865
866@@ -103,10 +107,10 @@
867 struct XTIndBlock *cb_lr_used; /* Less recently used blocks. */
868 /* Protected by cb_lock: */
869 XT_IPAGE_LOCK_TYPE cb_lock;
870- xtWord1 cb_state; /* Block status. */
871+ xtWord4 cp_flush_seq;
872 xtWord2 cb_handle_count; /* TRUE if this page is referenced by a handle. */
873- xtWord2 cp_flush_seq;
874 xtWord2 cp_del_count; /* Number of deleted entries. */
875+ xtWord1 cb_state; /* Block status. */
876 #ifdef XT_USE_DIRECT_IO_ON_INDEX
877 xtWord1 *cb_data;
878 #else
879
880=== modified file 'storage/pbxt/src/database_xt.cc'
881--- storage/pbxt/src/database_xt.cc 2009-11-24 10:55:06 +0000
882+++ storage/pbxt/src/database_xt.cc 2010-05-07 08:52:27 +0000
883@@ -68,6 +68,7 @@
884 xtPublic int xt_db_auto_increment_mode; /* 0 = MySQL compatible, 1 = PrimeBase Compatible. */
885 xtPublic int xt_db_offline_log_function; /* 0 = recycle logs, 1 = delete logs, 2 = keep logs */
886 xtPublic int xt_db_sweeper_priority; /* 0 = low (default), 1 = normal, 2 = high */
887+xtPublic int xt_db_flush_log_at_trx_commit; /* 0 = no-write/no-flush, 1 = yes, 2 = write/no-flush */
888
889 xtPublic XTSortedListPtr xt_db_open_db_by_id = NULL;
890 xtPublic XTHashTabPtr xt_db_open_databases = NULL;
891@@ -288,6 +289,7 @@
892 /* Wait for the checkpointer: */
893 xt_wait_for_checkpointer(self, db);
894 }
895+ xt_stop_flusher(self, db);
896 xt_stop_checkpointer(self, db);
897 xt_stop_writer(self, db);
898 xt_stop_sweeper(self, db);
899@@ -317,6 +319,7 @@
900 {
901 XTDatabaseHPtr db = (XTDatabaseHPtr) x;
902
903+ xt_stop_flusher(self, db);
904 xt_stop_checkpointer(self, db);
905 xt_stop_compactor(self, db);
906 xt_stop_sweeper(self, db);
907@@ -475,6 +478,8 @@
908 xt_start_compactor(self, db);
909 xt_start_writer(self, db);
910 xt_start_checkpointer(self, db);
911+ if (xt_db_flush_log_at_trx_commit == 0 || xt_db_flush_log_at_trx_commit == 2)
912+ xt_start_flusher(self, db);
913
914 popr_();
915 xt_ht_put(self, xt_db_open_databases, db);
916@@ -574,6 +579,7 @@
917 pushr_(xt_ht_unlock, xt_db_open_databases);
918
919 /* Shutdown the database daemons: */
920+ xt_stop_flusher(self, db);
921 xt_stop_checkpointer(self, db);
922 xt_stop_sweeper(self, db);
923 xt_stop_compactor(self, db);
924@@ -902,7 +908,7 @@
925 XTTableHPtr tab;
926 xtTableID tab_id;
927
928- pushsr_(tab, xt_heap_release, xt_use_table(self, tab_name, no_load, missing_ok, NULL));
929+ pushsr_(tab, xt_heap_release, xt_use_table(self, tab_name, no_load, missing_ok));
930 if (!tab) {
931 freer_(); // xt_heap_release(tab)
932 return NULL;
933
934=== modified file 'storage/pbxt/src/database_xt.h'
935--- storage/pbxt/src/database_xt.h 2009-11-24 10:55:06 +0000
936+++ storage/pbxt/src/database_xt.h 2010-05-07 08:52:27 +0000
937@@ -60,6 +60,7 @@
938 extern int xt_db_auto_increment_mode;
939 extern int xt_db_offline_log_function;
940 extern int xt_db_sweeper_priority;
941+extern int xt_db_flush_log_at_trx_commit;
942
943 extern XTSortedListPtr xt_db_open_db_by_id;
944 extern XTHashTabPtr xt_db_open_databases;
945@@ -187,6 +188,10 @@
946 xt_mutex_type db_cp_lock;
947 xt_cond_type db_cp_cond; /* Writer condition when idle (must bw woken by log flush! */
948 XTCheckPointStateRec db_cp_state; /* The checkpoint state. */
949+
950+ /* The "flusher" thread (used when pbxt_flush_log_at_trx_commit = 0 or 2) */
951+ struct XTThread *db_fl_thread; /* The flusher thread (flushes the transation log). */
952+ xt_mutex_type db_fl_lock;
953 } XTDatabaseRec, *XTDatabaseHPtr; /* Heap pointer */
954
955 #define XT_FOR_USER 0
956
957=== modified file 'storage/pbxt/src/datadic_xt.cc'
958--- storage/pbxt/src/datadic_xt.cc 2009-11-24 10:55:06 +0000
959+++ storage/pbxt/src/datadic_xt.cc 2010-05-07 08:52:27 +0000
960@@ -1142,8 +1142,8 @@
961
962 void XTParseTable::parseReferenceDefinition(XTThreadPtr self, u_int req_cols)
963 {
964- int on_delete = XT_KEY_ACTION_DEFAULT;
965- int on_update = XT_KEY_ACTION_DEFAULT;
966+ int on_delete = XT_KEY_ACTION_RESTRICT;
967+ int on_update = XT_KEY_ACTION_RESTRICT;
968 char name[XT_IDENTIFIER_NAME_SIZE];
969 char parent_name[XT_IDENTIFIER_NAME_SIZE];
970 u_int cols = 0;
971@@ -1437,7 +1437,7 @@
972 XTTableHPtr tab;
973
974 /* Find the table... */
975- pushsr_(tab, xt_heap_release, xt_use_table(self, (XTPathStrPtr) path, FALSE, TRUE, NULL));
976+ pushsr_(tab, xt_heap_release, xt_use_table(self, (XTPathStrPtr) path, FALSE, TRUE));
977
978 /* Clone the foreign key definitions: */
979 if (tab && tab->tab_dic.dic_table) {
980@@ -2027,24 +2027,52 @@
981 void XTDDTableRef::deleteAllRows(XTThreadPtr self)
982 {
983 XTOpenTablePtr ot;
984- xtInt8 row_count;
985+ xtBool eof;
986+ xtWord1 *buffer;
987
988 if (!tr_fkey->getReferenceIndexPtr())
989- throw_();
990+ xt_throw(self);
991
992 if (!tr_fkey->getIndexPtr())
993- throw_();
994+ xt_throw(self);
995
996 if (!(ot = xt_db_open_table_using_tab(tr_fkey->co_table->dt_table, self)))
997- throw_();
998+ xt_throw(self);
999
1000+ /* {FREE-ROWS-BAD} */
1001+ /*
1002 row_count = ((xtInt8) ot->ot_table->tab_row_eof_id) - 1;
1003 row_count -= (xtInt8) ot->ot_table->tab_row_fnum;
1004+ */
1005+ /* Check if there are any rows in the referencing table: */
1006+ if (!xt_tab_seq_init(ot))
1007+ goto failed;
1008+
1009+ if (!(buffer = (xtWord1 *) xt_malloc(self, ot->ot_table->tab_dic.dic_mysql_buf_size)))
1010+ goto failed_1;
1011+
1012+ if (!xt_tab_seq_next(ot, buffer, &eof))
1013+ goto failed_2;
1014+
1015+ xt_free(self, buffer);
1016+
1017+ xt_tab_seq_exit(ot);
1018
1019 xt_db_return_table_to_pool_ns(ot);
1020
1021- if (row_count > 0)
1022+ if (!eof)
1023 xt_throw_ixterr(XT_CONTEXT, XT_ERR_ROW_IS_REFERENCED, tr_fkey->co_name);
1024+ return;
1025+
1026+ failed_2:
1027+ xt_free(self, buffer);
1028+
1029+ failed_1:
1030+ xt_tab_seq_exit(ot);
1031+
1032+ failed:
1033+ xt_db_return_table_to_pool_ns(ot);
1034+ xt_throw(self);
1035 }
1036
1037 void XTDDIndex::init(XTThreadPtr self, XTObject *obj)
1038@@ -2117,7 +2145,7 @@
1039 }
1040 xt_sb_concat(self, sb, "`)");
1041
1042- if (fk_on_delete != XT_KEY_ACTION_DEFAULT && fk_on_delete != XT_KEY_ACTION_RESTRICT) {
1043+ if (fk_on_delete != XT_KEY_ACTION_RESTRICT) {
1044 xt_sb_concat(self, sb, " ON DELETE ");
1045 switch (fk_on_delete) {
1046 case XT_KEY_ACTION_CASCADE: xt_sb_concat(self, sb, "CASCADE"); break;
1047@@ -2126,10 +2154,9 @@
1048 case XT_KEY_ACTION_NO_ACTION: xt_sb_concat(self, sb, "NO ACTION"); break;
1049 }
1050 }
1051- if (fk_on_update != XT_KEY_ACTION_DEFAULT && fk_on_update != XT_KEY_ACTION_RESTRICT) {
1052+ if (fk_on_update != XT_KEY_ACTION_RESTRICT) {
1053 xt_sb_concat(self, sb, " ON UPDATE ");
1054 switch (fk_on_update) {
1055- case XT_KEY_ACTION_DEFAULT: xt_sb_concat(self, sb, "RESTRICT"); break;
1056 case XT_KEY_ACTION_RESTRICT: xt_sb_concat(self, sb, "RESTRICT"); break;
1057 case XT_KEY_ACTION_CASCADE: xt_sb_concat(self, sb, "CASCADE"); break;
1058 case XT_KEY_ACTION_SET_NULL: xt_sb_concat(self, sb, "SET NULL"); break;
1059@@ -2259,8 +2286,8 @@
1060 {
1061 XTDDTable *ref_tab;
1062
1063- xt_xlock_rwlock(self, &co_table->dt_ref_lock);
1064- pushr_(xt_unlock_rwlock, &co_table->dt_ref_lock);
1065+ xt_recurrwlock_xlock(self, &co_table->dt_ref_lock);
1066+ pushr_(xt_recurrwlock_unxlock, &co_table->dt_ref_lock);
1067
1068 if ((ref_tab = fk_ref_table)) {
1069 fk_ref_table = NULL;
1070@@ -2270,7 +2297,7 @@
1071
1072 fk_ref_index = UINT_MAX;
1073
1074- freer_(); // xt_unlock_rwlock(&co_table->dt_ref_lock);
1075+ freer_(); // xt_recurrwlock_unxlock(&co_table->dt_ref_lock);
1076 }
1077
1078 /*
1079@@ -2289,7 +2316,7 @@
1080 /* This lock ensures that the foreign key references are not
1081 * changed.
1082 */
1083- xt_slock_rwlock_ns(&co_table->dt_ref_lock);
1084+ xt_recurrwlock_slock_ns(&co_table->dt_ref_lock);
1085
1086 if (!(loc_ind = getIndexPtr()))
1087 goto failed;
1088@@ -2374,11 +2401,11 @@
1089 xt_db_return_table_to_pool_ns(ot);
1090
1091 failed:
1092- xt_unlock_rwlock_ns(&co_table->dt_ref_lock);
1093+ xt_recurrwlock_unslock_ns(&co_table->dt_ref_lock);
1094 return false;
1095
1096 success:
1097- xt_unlock_rwlock_ns(&co_table->dt_ref_lock);
1098+ xt_recurrwlock_unslock_ns(&co_table->dt_ref_lock);
1099 return true;
1100 }
1101
1102@@ -2389,7 +2416,6 @@
1103 {
1104 switch (action)
1105 {
1106- case XT_KEY_ACTION_DEFAULT:
1107 case XT_KEY_ACTION_RESTRICT:
1108 return "RESTRICT";
1109 case XT_KEY_ACTION_CASCADE:
1110@@ -2407,7 +2433,7 @@
1111
1112 void XTDDTable::init(XTThreadPtr self)
1113 {
1114- xt_init_rwlock_with_autoname(self, &dt_ref_lock);
1115+ xt_recurrwlock_init_with_autoname(self, &dt_ref_lock);
1116 dt_trefs = NULL;
1117 }
1118
1119@@ -2444,7 +2470,7 @@
1120 ptr->release(self);
1121 }
1122
1123- xt_free_rwlock(&dt_ref_lock);
1124+ xt_recurrwlock_free(&dt_ref_lock);
1125 }
1126
1127 XTDDColumn *XTDDTable::findColumn(char *name)
1128@@ -2520,8 +2546,8 @@
1129 throw_();
1130 }
1131
1132- xt_xlock_rwlock(self, &dt_ref_lock);
1133- pushr_(xt_unlock_rwlock, &dt_ref_lock);
1134+ xt_recurrwlock_xlock(self, &dt_ref_lock);
1135+ pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
1136
1137 if (!(tr = new XTDDTableRef()))
1138 xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
1139@@ -2536,7 +2562,7 @@
1140 */
1141 xt_heap_reference(self, fk->co_table->dt_table);
1142
1143- freer_(); // xt_unlock_rwlock(&dt_ref_lock);
1144+ freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
1145 }
1146
1147 /*
1148@@ -2546,8 +2572,8 @@
1149 {
1150 XTDDTableRef *tr, *prev_tr = NULL;
1151
1152- xt_xlock_rwlock(self, &dt_ref_lock);
1153- pushr_(xt_unlock_rwlock, &dt_ref_lock);
1154+ xt_recurrwlock_xlock(self, &dt_ref_lock);
1155+ pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
1156
1157 tr = dt_trefs;
1158 while (tr) {
1159@@ -2561,7 +2587,7 @@
1160 prev_tr = tr;
1161 tr = tr->tr_next;
1162 }
1163- freer_(); // xt_unlock_rwlock(&dt_ref_lock);
1164+ freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
1165 if (tr)
1166 tr->release(self);
1167 }
1168@@ -2588,8 +2614,8 @@
1169
1170 dt->attachReference(self, fk);
1171
1172- xt_xlock_rwlock(self, &dt_ref_lock);
1173- pushr_(xt_unlock_rwlock, &dt_ref_lock);
1174+ xt_recurrwlock_xlock(self, &dt_ref_lock);
1175+ pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
1176 /* Referenced the table, not the index!
1177 * We do this because we know that if the table is referenced, the
1178 * index will remain valid!
1179@@ -2599,7 +2625,7 @@
1180 */
1181 xt_heap_reference(self, dt->dt_table);
1182 fk->fk_ref_table = dt;
1183- freer_(); // xt_unlock_rwlock(&dt_ref_lock);
1184+ freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
1185 }
1186 }
1187 }
1188@@ -2626,7 +2652,7 @@
1189 /* get pointer to the referenced table, load it if needed
1190 * cyclic references are being handled, absent table is ignored
1191 */
1192- tab = xt_use_table_no_lock(self, db, fk->fk_ref_tab_name, /*TRUE*/FALSE, /*FALSE*/TRUE, NULL, NULL);
1193+ tab = xt_use_table_no_lock(self, db, fk->fk_ref_tab_name, /*TRUE*/FALSE, /*FALSE*/TRUE, NULL);
1194
1195 if (tab) {
1196 pushr_(xt_heap_release, tab);
1197@@ -2663,8 +2689,8 @@
1198 XTDDTableRef *tr;
1199 XTDDTable *tab;
1200
1201- xt_xlock_rwlock(self, &dt_ref_lock);
1202- pushr_(xt_unlock_rwlock, &dt_ref_lock);
1203+ xt_recurrwlock_xlock(self, &dt_ref_lock);
1204+ pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
1205
1206 for (u_int i=0; i<dt_fkeys.size(); i++) {
1207 fk = dt_fkeys.itemAt(i);
1208@@ -2675,13 +2701,13 @@
1209 /* To avoid deadlock we do not hold more than
1210 * one lock at a time!
1211 */
1212- freer_(); // xt_unlock_rwlock(&dt_ref_lock);
1213+ freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
1214
1215 tab->removeReference(self, fk);
1216 xt_heap_release(self, tab->dt_table); /* We referenced the table, not the index! */
1217
1218- xt_xlock_rwlock(self, &dt_ref_lock);
1219- pushr_(xt_unlock_rwlock, &dt_ref_lock);
1220+ xt_recurrwlock_xlock(self, &dt_ref_lock);
1221+ pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
1222 }
1223 }
1224 }
1225@@ -2689,13 +2715,13 @@
1226 while (dt_trefs) {
1227 tr = dt_trefs;
1228 dt_trefs = tr->tr_next;
1229- freer_(); // xt_unlock_rwlock(&dt_ref_lock);
1230+ freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
1231 tr->release(self);
1232- xt_xlock_rwlock(self, &dt_ref_lock);
1233- pushr_(xt_unlock_rwlock, &dt_ref_lock);
1234+ xt_recurrwlock_xlock(self, &dt_ref_lock);
1235+ pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
1236 }
1237
1238- freer_(); // xt_unlock_rwlock(&dt_ref_lock);
1239+ freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
1240 }
1241
1242 void XTDDTable::checkForeignKeys(XTThreadPtr self, bool temp_table)
1243@@ -2727,7 +2753,7 @@
1244 // TODO: dont close table immediately so it can be possibly reused in this loop
1245 XTTable *ref_tab;
1246
1247- pushsr_(ref_tab, xt_heap_release, xt_use_table(self, fk->fk_ref_tab_name, FALSE, TRUE, NULL));
1248+ pushsr_(ref_tab, xt_heap_release, xt_use_table(self, fk->fk_ref_tab_name, FALSE, TRUE));
1249 if (ref_tab && !fk->checkReferencedTypes(ref_tab->tab_dic.dic_table))
1250 throw_();
1251 freer_();
1252@@ -2845,7 +2871,7 @@
1253 return false;
1254 rec_ptr = rec_buf.ib_db.db_data;
1255
1256- xt_slock_rwlock_ns(&dt_ref_lock);
1257+ xt_recurrwlock_slock_ns(&dt_ref_lock);
1258 tr = dt_trefs;
1259 while (tr) {
1260 if (!tr->checkReference(rec_ptr, ot->ot_thread)) {
1261@@ -2854,7 +2880,7 @@
1262 }
1263 tr = tr->tr_next;
1264 }
1265- xt_unlock_rwlock_ns(&dt_ref_lock);
1266+ xt_recurrwlock_unslock_ns(&dt_ref_lock);
1267 xt_ib_free(NULL, &rec_buf);
1268 return ok;
1269 }
1270@@ -2875,7 +2901,7 @@
1271 rec_ptr = rec_buf.ib_db.db_data;
1272
1273 }
1274- xt_slock_rwlock_ns(&dt_ref_lock);
1275+ xt_recurrwlock_slock_ns(&dt_ref_lock);
1276 tr = dt_trefs;
1277 while (tr) {
1278 if (!tr->modifyRow(ot, rec_ptr, NULL, ot->ot_thread)) {
1279@@ -2884,7 +2910,7 @@
1280 }
1281 tr = tr->tr_next;
1282 }
1283- xt_unlock_rwlock_ns(&dt_ref_lock);
1284+ xt_recurrwlock_unslock_ns(&dt_ref_lock);
1285 xt_ib_free(NULL, &rec_buf);
1286 return ok;
1287 }
1288@@ -2893,8 +2919,8 @@
1289 {
1290 XTDDTableRef *tr;
1291
1292- xt_slock_rwlock(self, &dt_ref_lock);
1293- pushr_(xt_unlock_rwlock, &dt_ref_lock);
1294+ xt_recurrwlock_slock(self, &dt_ref_lock);
1295+ pushr_(xt_recurrwlock_unslock, &dt_ref_lock);
1296
1297 tr = dt_trefs;
1298 while (tr) {
1299@@ -2902,7 +2928,7 @@
1300 tr = tr->tr_next;
1301 }
1302
1303- freer_(); // xt_unlock_rwlock(&dt_ref_lock);
1304+ freer_(); // xt_recurrwlock_unslock(&dt_ref_lock);
1305 }
1306
1307 bool XTDDTable::updateRow(XTOpenTablePtr ot, xtWord1 *before, xtWord1 *after)
1308@@ -2932,7 +2958,7 @@
1309 ok = true;
1310 before_buf.ib_free = FALSE;
1311
1312- xt_slock_rwlock_ns(&dt_ref_lock);
1313+ xt_recurrwlock_slock_ns(&dt_ref_lock);
1314 if ((tr = dt_trefs)) {
1315 if (!before) {
1316 if (!xt_tab_load_record(ot, ot->ot_curr_rec_id, &before_buf))
1317@@ -2948,7 +2974,7 @@
1318 tr = tr->tr_next;
1319 }
1320 }
1321- xt_unlock_rwlock_ns(&dt_ref_lock);
1322+ xt_recurrwlock_unslock_ns(&dt_ref_lock);
1323
1324 xt_ib_free(NULL, &before_buf);
1325 return ok;
1326
1327=== modified file 'storage/pbxt/src/datadic_xt.h'
1328--- storage/pbxt/src/datadic_xt.h 2009-08-18 07:46:53 +0000
1329+++ storage/pbxt/src/datadic_xt.h 2010-05-07 08:52:27 +0000
1330@@ -45,7 +45,6 @@
1331 #define XT_DD_KEY_PRIMARY 2
1332 #define XT_DD_KEY_FOREIGN 3
1333
1334-#define XT_KEY_ACTION_DEFAULT 0
1335 #define XT_KEY_ACTION_RESTRICT 1
1336 #define XT_KEY_ACTION_CASCADE 2
1337 #define XT_KEY_ACTION_SET_NULL 3
1338@@ -259,7 +258,7 @@
1339 XTList<XTDDColumn> dt_cols;
1340 XTList<XTDDIndex> dt_indexes;
1341
1342- xt_rwlock_type dt_ref_lock; /* The lock for adding and using references. */
1343+ XTRecurRWLockRec dt_ref_lock; /* The lock for adding and using references. */
1344 XTList<XTDDForeignKey> dt_fkeys; /* The foreign keys on this table. */
1345 XTDDTableRef *dt_trefs; /* A list of tables that reference this table. */
1346
1347
1348=== modified file 'storage/pbxt/src/datalog_xt.cc'
1349--- storage/pbxt/src/datalog_xt.cc 2009-11-24 10:55:06 +0000
1350+++ storage/pbxt/src/datalog_xt.cc 2010-05-07 08:52:27 +0000
1351@@ -1148,6 +1148,11 @@
1352 xtBool XTDataLogBuffer::dlb_close_log(XTThreadPtr thread)
1353 {
1354 if (dlb_data_log) {
1355+ if (dlb_data_log->dlf_log_file) {
1356+ if (!dl_write_log_header(dlb_data_log, dlb_data_log->dlf_log_file, 0, thread))
1357+ return FAILED;
1358+ }
1359+
1360 /* Flush and commit the data in the old log: */
1361 if (!dlb_flush_log(TRUE, thread))
1362 return FAILED;
1363@@ -1952,7 +1957,7 @@
1364 log_rec.xl_status_1 = XT_LOG_ENT_DEL_LOG;
1365 log_rec.xl_checksum_1 = XT_CHECKSUM_1(data_log->dlf_log_id);
1366 XT_SET_DISK_4(log_rec.xl_log_id_4, data_log->dlf_log_id);
1367- if (!xt_xlog_log_data(self, sizeof(XTXactNewLogEntryDRec), (XTXactLogBufferDPtr) &log_rec, TRUE)) {
1368+ if (!xt_xlog_log_data(self, sizeof(XTXactNewLogEntryDRec), (XTXactLogBufferDPtr) &log_rec, XT_XLOG_WRITE_AND_FLUSH)) {
1369 db->db_datalogs.dls_set_log_state(data_log, XT_DL_TO_COMPACT);
1370 xt_throw(self);
1371 }
1372
1373=== modified file 'storage/pbxt/src/filesys_xt.h'
1374--- storage/pbxt/src/filesys_xt.h 2009-11-24 10:55:06 +0000
1375+++ storage/pbxt/src/filesys_xt.h 2010-05-07 08:52:27 +0000
1376@@ -119,7 +119,7 @@
1377 #define FILE_MAP_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
1378 #define FILE_MAP_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
1379 #define FILE_MAP_READ_LOCK(i, o) xt_spinxslock_slock(i, o)
1380-#define FILE_MAP_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, o)
1381+#define FILE_MAP_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, FALSE, o)
1382 #define FILE_MAP_UNLOCK(i, o) xt_spinxslock_unlock(i, o)
1383 #endif
1384
1385
1386=== modified file 'storage/pbxt/src/ha_pbxt.cc'
1387--- storage/pbxt/src/ha_pbxt.cc 2010-01-06 21:27:53 +0000
1388+++ storage/pbxt/src/ha_pbxt.cc 2010-05-07 08:52:27 +0000
1389@@ -113,6 +113,7 @@
1390 static int pbxt_recover(handlerton *hton, XID *xid_list, uint len);
1391 static int pbxt_commit_by_xid(handlerton *hton, XID *xid);
1392 static int pbxt_rollback_by_xid(handlerton *hton, XID *xid);
1393+static int pbxt_start_consistent_snapshot(handlerton *hton, THD *thd);
1394 #endif
1395 static void ha_aquire_exclusive_use(XTThreadPtr self, XTSharePtr share, ha_pbxt *mine);
1396 static void ha_release_exclusive_use(XTThreadPtr self, XTSharePtr share);
1397@@ -286,7 +287,7 @@
1398 char func_buf[50], *ptr;
1399 XTThreadPtr thread = xt_get_self();
1400
1401- if ((ptr = strchr(function, '('))) {
1402+ if ((ptr = const_cast<char *>(strchr(function, '(')))) {
1403 ptr--;
1404 while (ptr > function) {
1405 if (!(isalnum(*ptr) || *ptr == '_'))
1406@@ -345,13 +346,13 @@
1407 return xt_ht_casehash(share->sh_table_path->ps_path);
1408 }
1409
1410-static void ha_open_share(XTThreadPtr self, XTShareRec *share, xtBool *tabled_opened)
1411+static void ha_open_share(XTThreadPtr self, XTShareRec *share)
1412 {
1413 xt_lock_mutex(self, (xt_mutex_type *) share->sh_ex_mutex);
1414 pushr_(xt_unlock_mutex, share->sh_ex_mutex);
1415
1416 if (!share->sh_table) {
1417- share->sh_table = xt_use_table(self, share->sh_table_path, FALSE, FALSE, tabled_opened);
1418+ share->sh_table = xt_use_table(self, share->sh_table_path, FALSE, FALSE);
1419 share->sh_dic_key_count = share->sh_table->tab_dic.dic_key_count;
1420 share->sh_dic_keys = share->sh_table->tab_dic.dic_keys;
1421 share->sh_recalc_selectivity = FALSE;
1422@@ -411,7 +412,7 @@
1423 * This structure contains information that is common to all handles.
1424 * (i.e. it is table specific).
1425 */
1426-static XTSharePtr ha_get_share(XTThreadPtr self, const char *table_path, bool open_table, xtBool *tabled_opened)
1427+static XTSharePtr ha_get_share(XTThreadPtr self, const char *table_path, bool open_table)
1428 {
1429 XTShareRec *share;
1430
1431@@ -433,7 +434,7 @@
1432 share->sh_table_path = (XTPathStrPtr) xt_dup_string(self, table_path);
1433
1434 if (open_table)
1435- ha_open_share(self, share, tabled_opened);
1436+ ha_open_share(self, share);
1437
1438 popr_(); // Discard ha_cleanup_share(share);
1439
1440@@ -476,6 +477,25 @@
1441 return removed;
1442 }
1443
1444+static inline void thd_init_xact(THD *thd, XTThreadPtr self, bool set_table_trans)
1445+{
1446+ self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ;
1447+ self->st_ignore_fkeys = (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) != 0;
1448+ self->st_auto_commit = (thd_test_options(thd,(OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0;
1449+ if (set_table_trans) {
1450+#ifdef DRIZZLED
1451+ self->st_table_trans = FALSE;
1452+#else
1453+ self->st_table_trans = thd_sql_command(thd) == SQLCOM_LOCK_TABLES;
1454+#endif
1455+ }
1456+ self->st_abort_trans = FALSE;
1457+ self->st_stat_ended = FALSE;
1458+ self->st_stat_trans = FALSE;
1459+ XT_PRINT0(self, "xt_xn_begin\n");
1460+ xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
1461+}
1462+
1463 /*
1464 * -----------------------------------------------------------------------
1465 * PUBLIC FUNCTIONS
1466@@ -1146,6 +1166,7 @@
1467 pbxt_hton->show_status = pbxt_show_status;
1468 pbxt_hton->flags = HTON_NO_FLAGS; /* HTON_CAN_RECREATE - Without this flags TRUNCATE uses delete_all_rows() */
1469 pbxt_hton->slot = (uint)-1; /* assign invald value, so we know when it's inited later */
1470+ pbxt_hton->start_consistent_snapshot = pbxt_start_consistent_snapshot;
1471 #if defined(MYSQL_SUPPORTS_BACKUP) && defined(XT_ENABLE_ONLINE_BACKUP)
1472 pbxt_hton->get_backup_engine = pbxt_backup_engine;
1473 #endif
1474@@ -1175,13 +1196,8 @@
1475 * +1 Temporary thread (e.g. TempForClose, TempForEnd)
1476 */
1477 #ifndef DRIZZLED
1478- if (pbxt_max_threads == 0) {
1479- // Embedded server sets max_connections=1
1480- if (max_connections > 1)
1481- pbxt_max_threads = max_connections + 7;
1482- else
1483- pbxt_max_threads = 100;
1484- }
1485+ if (pbxt_max_threads == 0)
1486+ pbxt_max_threads = max_connections + 7;
1487 #endif
1488 self = xt_init_threading(pbxt_max_threads); /* Create the main self: */
1489 if (!self)
1490@@ -1294,7 +1310,7 @@
1491 #6 0x000debe1 in THD::THD at sql_class.cc:631
1492 #7 0x00e207a4 in myxt_create_thread at myxt_xt.cc:2666
1493 #8 0x00e3134b in tabc_fr_run_thread at tabcache_xt.cc:982
1494- #9 0x00e422ca in thr_main_pbxt at thread_xt.cc:1006
1495+ #9 0x00e422ca in xt_thread_main at thread_xt.cc:1006
1496 #10 0x91ff7c55 in _pthread_start
1497 #11 0x91ff7b12 in thread_start
1498 *
1499@@ -1427,8 +1443,43 @@
1500 *
1501 * 3. If in BEGIN/END we must call ha_rollback() if we abort the transaction
1502 * internally.
1503+ *
1504+ * NOTE ON CONSISTENT SNAPSHOTS:
1505+ *
1506+ * PBXT itself doesn't need this functiona as its transaction mechanism provides
1507+ * consistent snapshots for all transactions by default. This function is needed
1508+ * only for multi-engine cases like this:
1509+ *
1510+ * CREATE TABLE t1 ... ENGINE=INNODB
1511+ * CREATE TABLE t2 ... ENGINE=PBXT
1512+ * START TRANSACTION WITH CONSISTENT SNAPSHOT
1513+ * SELECT * FROM t1 <-- at this point we need to know about the snapshot
1514 */
1515
1516+static int pbxt_start_consistent_snapshot(handlerton *hton, THD *thd)
1517+{
1518+ int err = 0;
1519+ XTThreadPtr self = ha_set_current_thread(thd, &err);
1520+
1521+ if (!self->st_database && pbxt_database) {
1522+ xt_ha_open_database_of_table(self, (XTPathStrPtr) NULL);
1523+ }
1524+
1525+ thd_init_xact(thd, self, true);
1526+
1527+ if (xt_xn_begin(self)) {
1528+ trans_register_ha(thd, TRUE, hton);
1529+ } else {
1530+ err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
1531+ }
1532+
1533+ /*
1534+ * As of MySQL 5.1.41 the return value is not checked, so the server might assume
1535+ * everything is fine even it isn't. InnoDB returns 0 on success.
1536+ */
1537+ return err;
1538+}
1539+
1540 /*
1541 * Commit the PBXT transaction of the given thread.
1542 * thd is the MySQL thread structure.
1543@@ -1557,7 +1608,7 @@
1544 return err;
1545 }
1546
1547-static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, const char *thread_name, int *err)
1548+static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, char *thread_name, int *err)
1549 {
1550 THD *thd;
1551 XTThreadPtr self = NULL;
1552@@ -1870,7 +1921,6 @@
1553 THD *thd = current_thd;
1554 int err = 0;
1555 XTThreadPtr self;
1556- xtBool tabled_opened = FALSE;
1557
1558 if (!(self = ha_set_current_thread(thd, &err)))
1559 return xt_ha_pbxt_to_mysql_error(err);
1560@@ -1878,24 +1928,30 @@
1561 try_(a) {
1562 xt_ha_open_database_of_table(self, pb_share->sh_table_path);
1563
1564- ha_open_share(self, pb_share, &tabled_opened);
1565+ ha_open_share(self, pb_share);
1566
1567 if (!(pb_open_tab = xt_db_open_table_using_tab(pb_share->sh_table, self)))
1568 xt_throw(self);
1569 pb_open_tab->ot_thread = self;
1570
1571- if (tabled_opened) {
1572+ /* {TABLE-STATS}
1573+ * We no longer use the information that a table
1574+ * was opened in order to know when to calculate
1575+ * statistics.
1576+ */
1577+ if (!pb_open_tab->ot_table->tab_ind_stat_calc_time) {
1578 #ifdef LOAD_TABLE_ON_OPEN
1579 xt_tab_load_table(self, pb_open_tab);
1580 #else
1581 xt_tab_load_row_pointers(self, pb_open_tab);
1582 #endif
1583- xt_ind_set_index_selectivity(self, pb_open_tab);
1584+ xt_ind_set_index_selectivity(pb_open_tab, self);
1585 /* If the number of rows is less than 150 we will recalculate the
1586 * selectity of the indices, as soon as the number of rows
1587 * exceeds 200 (see [**])
1588 */
1589- pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;
1590+ /* {FREE-ROWS-BAD} */
1591+ pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
1592 }
1593
1594 /* I am not doing this anymore because it was only required
1595@@ -2269,7 +2325,6 @@
1596 THD *thd = current_thd;
1597 int err = 0;
1598 XTThreadPtr self;
1599- xtBool tabled_opened = FALSE;
1600
1601 ref_length = XT_RECORD_OFFS_SIZE;
1602
1603@@ -2282,28 +2337,30 @@
1604 try_(a) {
1605 xt_ha_open_database_of_table(self, (XTPathStrPtr) table_path);
1606
1607- pb_share = ha_get_share(self, table_path, true, &tabled_opened);
1608+ pb_share = ha_get_share(self, table_path, false);
1609 ha_add_to_handler_list(self, pb_share, this);
1610 if (pb_share->sh_table_lock) {
1611 if (!ha_wait_for_shared_use(this, pb_share))
1612 xt_throw(self);
1613 }
1614
1615- ha_open_share(self, pb_share, &tabled_opened);
1616+ ha_open_share(self, pb_share);
1617
1618 thr_lock_data_init(&pb_share->sh_lock, &pb_lock, NULL);
1619 if (!(pb_open_tab = xt_db_open_table_using_tab(pb_share->sh_table, self)))
1620 xt_throw(self);
1621 pb_open_tab->ot_thread = self;
1622
1623- if (tabled_opened) {
1624+ /* {TABLE-STATS} */
1625+ if (!pb_open_tab->ot_table->tab_ind_stat_calc_time) {
1626 #ifdef LOAD_TABLE_ON_OPEN
1627 xt_tab_load_table(self, pb_open_tab);
1628 #else
1629 xt_tab_load_row_pointers(self, pb_open_tab);
1630 #endif
1631- xt_ind_set_index_selectivity(self, pb_open_tab);
1632- pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;
1633+ xt_ind_set_index_selectivity(pb_open_tab, self);
1634+ /* {FREE-ROWS-BAD} */
1635+ pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
1636 }
1637
1638 init_auto_increment(0);
1639@@ -2411,7 +2468,7 @@
1640 self->st_abort_trans = FALSE;
1641 self->st_stat_ended = FALSE;
1642 self->st_stat_trans = FALSE;
1643- self->st_is_update = FALSE;
1644+ self->st_is_update = NULL;
1645 if (!xt_xn_begin(self)) {
1646 xt_spinlock_unlock(&tab->tab_ainc_lock);
1647 xt_throw(self);
1648@@ -2651,8 +2708,14 @@
1649 * and if it gets dup-key error it tries UPDATE, so the same row can be overwriten multiple
1650 * times within the same statement
1651 */
1652- if (err == HA_ERR_FOUND_DUPP_KEY && pb_open_tab->ot_thread->st_is_update)
1653- pb_open_tab->ot_thread->st_update_id++;
1654+ if (err == HA_ERR_FOUND_DUPP_KEY && pb_open_tab->ot_thread->st_is_update) {
1655+ /* Pop the update stack: */
1656+ //pb_open_tab->ot_thread->st_update_id++;
1657+ XTOpenTablePtr curr = pb_open_tab->ot_thread->st_is_update;
1658+
1659+ pb_open_tab->ot_thread->st_is_update = curr->ot_prev_update;
1660+ curr->ot_prev_update = NULL;
1661+ }
1662 }
1663
1664 done:
1665@@ -2720,9 +2783,12 @@
1666
1667 xt_xlog_check_long_writer(self);
1668
1669- if (!self->st_is_update) {
1670- self->st_is_update = TRUE;
1671- self->st_update_id++;
1672+ /* {UPDATE-STACK} */
1673+ if (self->st_is_update != pb_open_tab) {
1674+ /* Push the update stack: */
1675+ pb_open_tab->ot_prev_update = self->st_is_update;
1676+ self->st_is_update = pb_open_tab;
1677+ pb_open_tab->ot_update_id++;
1678 }
1679
1680 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1681@@ -3120,6 +3186,7 @@
1682 active_index = idx;
1683
1684 if (pb_open_tab->ot_table->tab_dic.dic_disable_index) {
1685+ active_index = MAX_KEY;
1686 xt_tab_set_index_error(pb_open_tab->ot_table);
1687 return ha_log_pbxt_thread_error_for_mysql(pb_ignore_dup_key);
1688 }
1689@@ -3270,6 +3337,10 @@
1690 int prefix = 0;
1691 XTIdxSearchKeyRec search_key;
1692
1693+ if (idx == MAX_KEY) {
1694+ err = HA_ERR_WRONG_INDEX;
1695+ goto done;
1696+ }
1697 #ifdef XT_TRACK_RETURNED_ROWS
1698 ha_start_scan(pb_open_tab, idx);
1699 #endif
1700@@ -3320,6 +3391,7 @@
1701 ha_return_row(pb_open_tab, idx);
1702 #endif
1703 XT_DISABLED_TRACE(("search tx=%d val=%d err=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(key), err));
1704+ done:
1705 if (err)
1706 table->status = STATUS_NOT_FOUND;
1707 else {
1708@@ -3364,6 +3436,10 @@
1709 //statistic_increment(ha_read_next_count,&LOCK_status);
1710 ASSERT_NS(pb_ex_in_use);
1711
1712+ if (active_index == MAX_KEY) {
1713+ err = HA_ERR_WRONG_INDEX;
1714+ goto done;
1715+ }
1716 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];
1717
1718 if (!xt_idx_next(pb_open_tab, ind, NULL))
1719@@ -3376,6 +3452,7 @@
1720 if (!err)
1721 ha_return_row(pb_open_tab, active_index);
1722 #endif
1723+ done:
1724 if (err)
1725 table->status = STATUS_NOT_FOUND;
1726 else {
1727@@ -3406,6 +3483,10 @@
1728 //statistic_increment(ha_read_next_count,&LOCK_status);
1729 ASSERT_NS(pb_ex_in_use);
1730
1731+ if (active_index == MAX_KEY) {
1732+ err = HA_ERR_WRONG_INDEX;
1733+ goto done;
1734+ }
1735 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];
1736
1737 search_key.sk_key_value.sv_flags = HA_READ_KEY_EXACT;
1738@@ -3425,6 +3506,7 @@
1739 if (!err)
1740 ha_return_row(pb_open_tab, active_index);
1741 #endif
1742+ done:
1743 if (err)
1744 table->status = STATUS_NOT_FOUND;
1745 else {
1746@@ -3446,6 +3528,10 @@
1747 //statistic_increment(ha_read_prev_count,&LOCK_status);
1748 ASSERT_NS(pb_ex_in_use);
1749
1750+ if (active_index == MAX_KEY) {
1751+ err = HA_ERR_WRONG_INDEX;
1752+ goto done;
1753+ }
1754 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];
1755
1756 if (!xt_idx_prev(pb_open_tab, ind, NULL))
1757@@ -3458,6 +3544,7 @@
1758 if (!err)
1759 ha_return_row(pb_open_tab, active_index);
1760 #endif
1761+ done:
1762 if (err)
1763 table->status = STATUS_NOT_FOUND;
1764 else {
1765@@ -3480,6 +3567,18 @@
1766 //statistic_increment(ha_read_first_count,&LOCK_status);
1767 ASSERT_NS(pb_ex_in_use);
1768
1769+ /* This is required because MySQL ignores the error returned
1770+ * init init_index sometimes, for example:
1771+ *
1772+ * if (!table->file->inited)
1773+ * table->file->ha_index_init(tab->index, tab->sorted);
1774+ * if ((error=tab->table->file->index_first(tab->table->record[0])))
1775+ */
1776+ if (active_index == MAX_KEY) {
1777+ err = HA_ERR_WRONG_INDEX;
1778+ goto done;
1779+ }
1780+
1781 #ifdef XT_TRACK_RETURNED_ROWS
1782 ha_start_scan(pb_open_tab, active_index);
1783 #endif
1784@@ -3498,6 +3597,7 @@
1785 if (!err)
1786 ha_return_row(pb_open_tab, active_index);
1787 #endif
1788+ done:
1789 if (err)
1790 table->status = STATUS_NOT_FOUND;
1791 else {
1792@@ -3520,6 +3620,11 @@
1793 //statistic_increment(ha_read_last_count,&LOCK_status);
1794 ASSERT_NS(pb_ex_in_use);
1795
1796+ if (active_index == MAX_KEY) {
1797+ err = HA_ERR_WRONG_INDEX;
1798+ goto done;
1799+ }
1800+
1801 #ifdef XT_TRACK_RETURNED_ROWS
1802 ha_start_scan(pb_open_tab, active_index);
1803 #endif
1804@@ -3538,6 +3643,7 @@
1805 if (!err)
1806 ha_return_row(pb_open_tab, active_index);
1807 #endif
1808+ done:
1809 if (err)
1810 table->status = STATUS_NOT_FOUND;
1811 else {
1812@@ -3825,8 +3931,34 @@
1813
1814 if ((ot = pb_open_tab)) {
1815 if (flag & HA_STATUS_VARIABLE) {
1816- stats.deleted = ot->ot_table->tab_row_fnum;
1817- stats.records = (ha_rows) (ot->ot_table->tab_row_eof_id - 1 - stats.deleted);
1818+ /* {FREE-ROWS-BAD}
1819+ * Free row count is not reliable, so ignore it.
1820+ * The problem is if tab_row_fnum > tab_row_eof_id - 1 then
1821+ * we have a very bad result.
1822+ *
1823+ * If stats.records+EXTRA_RECORDS == 0 as returned by
1824+ * estimate_rows_upper_bound(), then filesort will crash here:
1825+ *
1826+ * make_sortkey(param,sort_keys[idx++],ref_pos);
1827+ *
1828+ * #0 0x000bf69c in Field_long::sort_string at field.cc:3766
1829+ * #1 0x0022e1f1 in make_sortkey at filesort.cc:769
1830+ * #2 0x0022f1cf in find_all_keys at filesort.cc:619
1831+ * #3 0x00230eec in filesort at filesort.cc:243
1832+ * #4 0x001b9d89 in mysql_update at sql_update.cc:415
1833+ * #5 0x0010db12 in mysql_execute_command at sql_parse.cc:2959
1834+ * #6 0x0011480d in mysql_parse at sql_parse.cc:5787
1835+ * #7 0x00115afb in dispatch_command at sql_parse.cc:1200
1836+ * #8 0x00116de2 in do_command at sql_parse.cc:857
1837+ * #9 0x00101ee4 in handle_one_connection at sql_connect.cc:1115
1838+ *
1839+ * The problem is that sort_keys is allocated to handle just 1 vector.
1840+ * Sorting one vector crashes. Although I could not find a check for
1841+ * the actual number of vectors. But it must assume that it has at
1842+ * least EXTRA_RECORDS vectors.
1843+ */
1844+ stats.deleted = /* ot->ot_table->tab_row_fnum */ 0;
1845+ stats.records = (ha_rows) (ot->ot_table->tab_row_eof_id - 1 /* - stats.deleted */);
1846 stats.data_file_length = xt_rec_id_to_rec_offset(ot->ot_table, ot->ot_table->tab_rec_eof_id);
1847 stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof);
1848 stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size;
1849@@ -4454,11 +4586,13 @@
1850 }
1851
1852 if (pb_share->sh_recalc_selectivity) {
1853- if ((pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) >= 200) {
1854+ /* {FREE-ROWS-BAD} */
1855+ if ((pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) >= 200) {
1856 /* [**] */
1857 pb_share->sh_recalc_selectivity = FALSE;
1858- xt_ind_set_index_selectivity(self, pb_open_tab);
1859- pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;
1860+ xt_ind_set_index_selectivity(pb_open_tab, self);
1861+ /* {FREE-ROWS-BAD} */
1862+ pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
1863 }
1864 }
1865 }
1866@@ -4497,7 +4631,7 @@
1867 if (!pb_share->sh_table) {
1868 xt_ha_open_database_of_table(self, pb_share->sh_table_path);
1869
1870- ha_open_share(self, pb_share, NULL);
1871+ ha_open_share(self, pb_share);
1872 }
1873 }
1874 catch_(a) {
1875@@ -4603,8 +4737,8 @@
1876 cont_(b);
1877 }
1878
1879- /* See {IS-UPDATE-STAT} */
1880- self->st_is_update = FALSE;
1881+ /* See {IS-UPDATE-STAT} nad {UPDATE-STACK} */
1882+ self->st_is_update = NULL;
1883
1884 /* Auto begin a transaction (if one is not already running): */
1885 if (!self->st_xact_data) {
1886@@ -4612,19 +4746,8 @@
1887 (void) ASSERT_NS(ISO_READ_UNCOMMITTED == XT_XACT_UNCOMMITTED_READ);
1888 (void) ASSERT_NS(ISO_SERIALIZABLE == XT_XACT_SERIALIZABLE);
1889
1890- self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ;
1891- self->st_ignore_fkeys = (thd_test_options(thd,OPTION_NO_FOREIGN_KEY_CHECKS)) != 0;
1892- self->st_auto_commit = (thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0;
1893-#ifdef DRIZZLED
1894- self->st_table_trans = FALSE;
1895-#else
1896- self->st_table_trans = thd_sql_command(thd) == SQLCOM_LOCK_TABLES;
1897-#endif
1898- self->st_abort_trans = FALSE;
1899- self->st_stat_ended = FALSE;
1900- self->st_stat_trans = FALSE;
1901- XT_PRINT0(self, "xt_xn_begin\n");
1902- xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
1903+ thd_init_xact(thd, self, true);
1904+
1905 if (!xt_xn_begin(self)) {
1906 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
1907 pb_ex_in_use = 0;
1908@@ -4847,19 +4970,27 @@
1909 * are nested within an open close of the select t1
1910 * statement.
1911 */
1912- self->st_is_update = FALSE;
1913+ /* {UPDATE-STACK}
1914+ * Add to this I add the following:
1915+ * A trigger in the middle of an update also causes nested
1916+ * statements. If I reset st_is_update, then then
1917+ * when the trigger returns the system thinks we
1918+ * are in a different update statement, and may
1919+ * update the same row again.
1920+ */
1921+ if (self->st_is_update == pb_open_tab) {
1922+ /* Pop the update stack: */
1923+ XTOpenTablePtr curr = pb_open_tab->ot_thread->st_is_update;
1924+
1925+ pb_open_tab->ot_thread->st_is_update = curr->ot_prev_update;
1926+ curr->ot_prev_update = NULL;
1927+ }
1928
1929 /* See comment {START-TRANS} */
1930 if (!self->st_xact_data) {
1931- self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ;
1932- self->st_ignore_fkeys = (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) != 0;
1933- self->st_auto_commit = (thd_test_options(thd,(OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0;
1934- /* self->st_table_trans = not set here! */
1935- self->st_abort_trans = FALSE;
1936- self->st_stat_ended = FALSE;
1937- self->st_stat_trans = FALSE;
1938- XT_PRINT0(self, "xt_xn_begin\n");
1939- xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
1940+
1941+ thd_init_xact(thd, self, false);
1942+
1943 if (!xt_xn_begin(self)) {
1944 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
1945 goto complete;
1946@@ -4915,6 +5046,18 @@
1947 */
1948 THR_LOCK_DATA **ha_pbxt::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type)
1949 {
1950+ /*
1951+ * TL_READ means concurrent INSERTs are allowed. This is a problem as in this mode
1952+ * PBXT is not compatible with MyISAM which allows INSERTs but isolates them from
1953+ * current "transaction" (started by LOCK TABLES, ended by UNLOCK TABLES). PBXT
1954+ * used to allow INSERTs and made them visible to the locker (on commit).
1955+ * While MySQL manual doesn't state anything regarding row visibility limitations
1956+ * we choose to convert local locks into normal read locks for better compatibility
1957+ * with MyISAM.
1958+ */
1959+ if (lock_type == TL_READ)
1960+ lock_type = TL_READ_NO_INSERT;
1961+
1962 if (lock_type != TL_IGNORE && pb_lock.type == TL_UNLOCK) {
1963 /* Set to TRUE for operations that require a table lock: */
1964 switch (thd_sql_command(thd)) {
1965@@ -5112,7 +5255,7 @@
1966 * We also cannot use pb_share because the handler used
1967 * to delete a table is not openned correctly.
1968 */
1969- share = ha_get_share(self, table_path, false, NULL);
1970+ share = ha_get_share(self, table_path, false);
1971 pushr_(ha_unget_share, share);
1972 ha_aquire_exclusive_use(self, share, NULL);
1973 pushr_(ha_release_exclusive_use, share);
1974@@ -5271,7 +5414,7 @@
1975 * called without correctly initializing
1976 * the handler!
1977 */
1978- share = ha_get_share(self, from, true, NULL);
1979+ share = ha_get_share(self, from, true);
1980 pushr_(ha_unget_share, share);
1981 ha_aquire_exclusive_use(self, share, NULL);
1982 pushr_(ha_release_exclusive_use, share);
1983@@ -5852,6 +5995,11 @@
1984 NULL, NULL, FALSE);
1985 #endif
1986
1987+static MYSQL_SYSVAR_INT(flush_log_at_trx_commit, xt_db_flush_log_at_trx_commit,
1988+ PLUGIN_VAR_OPCMDARG,
1989+ "Determines whether the transaction log is written and/or flushed when a transaction is committed (no matter what the setting the log is written and flushed once per second), 0 = no write & no flush, 1 = write & flush (default), 2 = write & no flush.",
1990+ NULL, NULL, 1, 0, 2, 1);
1991+
1992 static struct st_mysql_sys_var* pbxt_system_variables[] = {
1993 MYSQL_SYSVAR(index_cache_size),
1994 MYSQL_SYSVAR(record_cache_size),
1995@@ -5870,6 +6018,7 @@
1996 MYSQL_SYSVAR(sweeper_priority),
1997 MYSQL_SYSVAR(max_threads),
1998 MYSQL_SYSVAR(support_xa),
1999+ MYSQL_SYSVAR(flush_log_at_trx_commit),
2000 NULL
2001 };
2002 #endif
2003
2004=== modified file 'storage/pbxt/src/index_xt.cc'
2005--- storage/pbxt/src/index_xt.cc 2009-11-24 10:55:06 +0000
2006+++ storage/pbxt/src/index_xt.cc 2010-05-07 08:52:27 +0000
2007@@ -1328,10 +1328,12 @@
2008 XT_SET_DISK_2(leaf->tb_size_2, XT_MAKE_NODE_SIZE(result->sr_item.i_total_size));
2009 }
2010
2011-static void idx_get_middle_branch_item(XTIndexPtr ind, XTIdxBranchDPtr branch, XTIdxKeyValuePtr value, XTIdxResultPtr result)
2012+static xtBool idx_get_middle_branch_item(XTOpenTablePtr ot, XTIndexPtr ind, XTIdxBranchDPtr branch, XTIdxKeyValuePtr value, XTIdxResultPtr result)
2013 {
2014 xtWord1 *bitem;
2015
2016+ ASSERT_NS(result->sr_item.i_node_ref_size == 0 || result->sr_item.i_node_ref_size == XT_NODE_REF_SIZE);
2017+ ASSERT_NS((int) result->sr_item.i_total_size >= 0 && result->sr_item.i_total_size <= XT_INDEX_PAGE_SIZE*2);
2018 if (ind->mi_fix_key) {
2019 u_int full_item_size = result->sr_item.i_item_size + result->sr_item.i_node_ref_size;
2020
2021@@ -1346,18 +1348,25 @@
2022 }
2023 else {
2024 u_int node_ref_size;
2025- u_int ilen;
2026+ u_int ilen, tlen;
2027 xtWord1 *bend;
2028
2029 node_ref_size = result->sr_item.i_node_ref_size;
2030- bitem = branch->tb_data + node_ref_size;;
2031+ bitem = branch->tb_data + node_ref_size;
2032 bend = &branch->tb_data[(result->sr_item.i_total_size - node_ref_size) / 2 + node_ref_size];
2033 ilen = 0;
2034 if (bitem < bend) {
2035+ tlen = 0;
2036 for (;;) {
2037 ilen = myxt_get_key_length(ind, bitem);
2038- if (bitem + ilen + XT_RECORD_REF_SIZE + node_ref_size >= bend)
2039+ tlen += ilen + XT_RECORD_REF_SIZE + node_ref_size;
2040+ if (bitem + ilen + XT_RECORD_REF_SIZE + node_ref_size >= bend) {
2041+ if (ilen > XT_INDEX_PAGE_SIZE || tlen > result->sr_item.i_total_size) {
2042+ xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
2043+ return FAILED;
2044+ }
2045 break;
2046+ }
2047 bitem += ilen + XT_RECORD_REF_SIZE + node_ref_size;
2048 }
2049 }
2050@@ -1370,6 +1379,7 @@
2051 xt_get_record_ref(bitem + ilen, &value->sv_rec_id, &value->sv_row_id);
2052 memcpy(value->sv_key, bitem, value->sv_length);
2053 }
2054+ return OK;
2055 }
2056
2057 static size_t idx_write_branch_item(XTIndexPtr XT_UNUSED(ind), xtWord1 *item, XTIdxKeyValuePtr value)
2058@@ -1438,7 +1448,8 @@
2059 /* We assume that value can be overwritten (which is the case) */
2060 key_value.sv_flags = XT_SEARCH_WHOLE_KEY;
2061 key_value.sv_key = key_buf;
2062- idx_get_middle_branch_item(ind, iref.ir_branch, &key_value, &result);
2063+ if (!idx_get_middle_branch_item(ot, ind, iref.ir_branch, &key_value, &result))
2064+ goto failed_1;
2065
2066 if (!idx_new_branch(ot, ind, &new_branch))
2067 goto failed_1;
2068@@ -1567,7 +1578,8 @@
2069 ASSERT_NS(result.sr_item.i_total_size > XT_INDEX_PAGE_DATA_SIZE);
2070
2071 /* We assume that value can be overwritten (which is the case) */
2072- idx_get_middle_branch_item(ind, &ot->ot_ind_wbuf, key_value, &result);
2073+ if (!idx_get_middle_branch_item(ot, ind, &ot->ot_ind_wbuf, key_value, &result))
2074+ goto failed_1;
2075
2076 if (!idx_new_branch(ot, ind, &new_branch))
2077 goto failed_1;
2078@@ -2041,7 +2053,7 @@
2079 memcpy(&ot->ot_ind_wbuf, iref.ir_branch, offsetof(XTIdxBranchDRec, tb_data) + result.sr_item.i_total_size);
2080 idx_insert_leaf_item(ind, &ot->ot_ind_wbuf, &key_value, &result);
2081 IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2));
2082- ASSERT_NS(result.sr_item.i_total_size > XT_INDEX_PAGE_DATA_SIZE);
2083+ ASSERT_NS(result.sr_item.i_total_size > XT_INDEX_PAGE_DATA_SIZE && result.sr_item.i_total_size <= XT_INDEX_PAGE_DATA_SIZE*2);
2084
2085 /* This is the number of potential writes. In other words, the total number
2086 * of blocks that may be accessed.
2087@@ -2053,7 +2065,8 @@
2088 goto failed_1;
2089
2090 /* Key does not fit, must split... */
2091- idx_get_middle_branch_item(ind, &ot->ot_ind_wbuf, &key_value, &result);
2092+ if (!idx_get_middle_branch_item(ot, ind, &ot->ot_ind_wbuf, &key_value, &result))
2093+ goto failed_1;
2094
2095 if (!idx_new_branch(ot, ind, &new_branch))
2096 goto failed_1;
2097@@ -3317,7 +3330,7 @@
2098 return FALSE;
2099 }
2100
2101-static void idx_set_index_selectivity(XTThreadPtr self, XTOpenTablePtr ot, XTIndexPtr ind)
2102+static void idx_set_index_selectivity(XTOpenTablePtr ot, XTIndexPtr ind, XTThreadPtr thread)
2103 {
2104 static const xtRecordID MAX_RECORDS = 100;
2105
2106@@ -3368,7 +3381,7 @@
2107 last_rec = ot->ot_curr_rec_id;
2108
2109 key_len = ot->ot_ind_state.i_item_size - XT_RECORD_REF_SIZE;
2110- xt_ind_unlock_handle(ot->ot_ind_rhandle);
2111+ xt_ind_lock_handle(ot->ot_ind_rhandle);
2112 memcpy(key_buf, ot->ot_ind_rhandle->ih_branch->tb_data + ot->ot_ind_state.i_item_offset, key_len);
2113 xt_ind_unlock_handle(ot->ot_ind_rhandle);
2114 }
2115@@ -3410,7 +3423,7 @@
2116 last_iter_rec = last_rec;
2117
2118 if (ot->ot_ind_rhandle) {
2119- xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, self);
2120+ xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, thread);
2121 ot->ot_ind_rhandle = NULL;
2122 }
2123 }
2124@@ -3431,8 +3444,10 @@
2125 return;
2126
2127 failed_1:
2128- xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, self);
2129- ot->ot_ind_rhandle = NULL;
2130+ if (ot->ot_ind_rhandle) {
2131+ xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, thread);
2132+ ot->ot_ind_rhandle = NULL;
2133+ }
2134
2135 failed:
2136 xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED);
2137@@ -3440,16 +3455,23 @@
2138 return;
2139 }
2140
2141-xtPublic void xt_ind_set_index_selectivity(XTThreadPtr self, XTOpenTablePtr ot)
2142+xtPublic void xt_ind_set_index_selectivity(XTOpenTablePtr ot, XTThreadPtr thread)
2143 {
2144 XTTableHPtr tab = ot->ot_table;
2145 XTIndexPtr *ind;
2146 u_int i;
2147+ time_t now;
2148
2149- if (!tab->tab_dic.dic_disable_index) {
2150- for (i=0, ind=tab->tab_dic.dic_keys; i<tab->tab_dic.dic_key_count; i++, ind++)
2151- idx_set_index_selectivity(self, ot, *ind);
2152+ now = time(NULL);
2153+ xt_lock_mutex_ns(&tab->tab_ind_stat_lock);
2154+ if (tab->tab_ind_stat_calc_time < now) {
2155+ if (!tab->tab_dic.dic_disable_index) {
2156+ for (i=0, ind=tab->tab_dic.dic_keys; i<tab->tab_dic.dic_key_count; i++, ind++)
2157+ idx_set_index_selectivity(ot, *ind, thread);
2158+ }
2159+ tab->tab_ind_stat_calc_time = time(NULL);
2160 }
2161+ xt_unlock_mutex_ns(&tab->tab_ind_stat_lock);
2162 }
2163
2164 /*
2165@@ -3740,7 +3762,8 @@
2166 static xtBool idx_flush_dirty_list(XTIndexLogPtr il, XTOpenTablePtr ot, u_int *flush_count, XTIndBlockPtr *flush_list)
2167 {
2168 for (u_int i=0; i<*flush_count; i++)
2169- il->il_write_block(ot, flush_list[i]);
2170+ if (!il->il_write_block(ot, flush_list[i]))
2171+ return FAILED;
2172 *flush_count = 0;
2173 return OK;
2174 }
2175@@ -3793,7 +3816,7 @@
2176 xtIndexNodeID ind_free;
2177 xtBool something_to_free = FALSE;
2178 xtIndexNodeID last_address, next_address;
2179- xtWord2 curr_flush_seq;
2180+ xtWord4 curr_flush_seq;
2181 XTIndFreeListPtr list_ptr;
2182 u_int dirty_blocks;
2183 XTCheckPointTablePtr cp_tab;
2184@@ -3810,8 +3833,9 @@
2185 if (!tab->tab_db->db_indlogs.ilp_get_log(&il, ot->ot_thread))
2186 goto failed_3;
2187
2188- il->il_reset(tab->tab_id);
2189- if (!il->il_write_byte(ot, XT_DT_FREE_LIST))
2190+ if (!il->il_reset(ot))
2191+ goto failed_2;
2192+ if (!il->il_write_byte(ot, XT_DT_LOG_HEAD))
2193 goto failed_2;
2194 if (!il->il_write_word4(ot, tab->tab_id))
2195 goto failed_2;
2196@@ -3849,7 +3873,7 @@
2197 wrote_something = TRUE;
2198 while (block) {
2199 ASSERT_NS(block->cb_state == IDX_CAC_BLOCK_DIRTY);
2200- ASSERT_NS(block->cp_flush_seq == curr_flush_seq);
2201+ ASSERT_NS((block->cp_flush_seq == curr_flush_seq) || xt_xn_is_before(block->cp_flush_seq, curr_flush_seq));
2202 if (!ind_add_to_dirty_list(il, ot, &flush_count, flush_list, block))
2203 goto failed;
2204 block = block->cb_dirty_next;
2205@@ -4023,7 +4047,7 @@
2206 fblock = block;
2207 block = block->cb_dirty_next;
2208 ASSERT_NS(fblock->cb_state == IDX_CAC_BLOCK_DIRTY);
2209- if (fblock->cp_flush_seq == curr_flush_seq) {
2210+ if (fblock->cp_flush_seq == curr_flush_seq || xt_xn_is_before(fblock->cp_flush_seq, curr_flush_seq)) {
2211 /* Take the block off the dirty list: */
2212 if (fblock->cb_dirty_next)
2213 fblock->cb_dirty_next->cb_dirty_prev = fblock->cb_dirty_prev;
2214@@ -4254,12 +4278,32 @@
2215 xt_unlock_mutex_ns(&ilp_lock);
2216 }
2217
2218-void XTIndexLog::il_reset(xtTableID tab_id)
2219+xtBool XTIndexLog::il_reset(XTOpenTable *ot)
2220 {
2221+ XTIndLogHeadDRec log_head;
2222+ xtTableID tab_id = ot->ot_table->tab_id;
2223+
2224 il_tab_id = tab_id;
2225 il_log_eof = 0;
2226 il_buffer_len = 0;
2227 il_buffer_offset = 0;
2228+
2229+ /* We must write the header and flush here or the "previous" status (from the
2230+ * last flush run) could remain. Failure to write the file completely leave the
2231+ * old header in place, and other parts of the file changed.
2232+ * This would lead to index corruption.
2233+ */
2234+ log_head.ilh_data_type = XT_DT_LOG_HEAD;
2235+ XT_SET_DISK_4(log_head.ilh_tab_id_4, tab_id);
2236+ XT_SET_DISK_4(log_head.ilh_log_eof_4, 0);
2237+
2238+ if (!xt_pwrite_file(il_of, 0, sizeof(XTIndLogHeadDRec), (xtWord1 *) &log_head, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
2239+ return FAILED;
2240+
2241+ if (!xt_flush_file(il_of, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
2242+ return FAILED;
2243+
2244+ return OK;
2245 }
2246
2247 void XTIndexLog::il_close(xtBool delete_it)
2248
2249=== modified file 'storage/pbxt/src/index_xt.h'
2250--- storage/pbxt/src/index_xt.h 2009-08-17 11:12:36 +0000
2251+++ storage/pbxt/src/index_xt.h 2010-05-07 08:52:27 +0000
2252@@ -30,6 +30,7 @@
2253 #include <mysql_version.h>
2254 #include <my_bitmap.h>
2255 #endif
2256+#include <time.h>
2257
2258 #include "thread_xt.h"
2259 #include "linklist_xt.h"
2260@@ -293,7 +294,6 @@
2261 */
2262 typedef struct XTIndex {
2263 u_int mi_index_no; /* The index number (used by MySQL). */
2264- xt_mutex_type mi_flush_lock; /* Lock the index during flushing. */
2265
2266 /* Protected by the mi_rwlock lock: */
2267 XT_INDEX_LOCK_TYPE mi_rwlock; /* This lock protects the structure of the index.
2268@@ -407,7 +407,7 @@
2269 off_t il_buffer_offset;
2270
2271
2272- void il_reset(xtTableID tab_id);
2273+ xtBool il_reset(XTOpenTable *ot);
2274 void il_close(xtBool delete_it);
2275 void il_release();
2276
2277@@ -478,7 +478,7 @@
2278 xtBool xt_idx_next(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
2279 xtBool xt_idx_prev(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
2280 xtBool xt_idx_read(struct XTOpenTable *ot, struct XTIndex *ind, xtWord1 *rec_buf);
2281-void xt_ind_set_index_selectivity(XTThreadPtr self, struct XTOpenTable *ot);
2282+void xt_ind_set_index_selectivity(struct XTOpenTable *ot, XTThreadPtr thread);
2283 void xt_check_indices(struct XTOpenTable *ot);
2284 void xt_load_indices(XTThreadPtr self, struct XTOpenTable *ot);
2285 void xt_ind_count_deleted_items(struct XTTable *ot, struct XTIndex *ind, struct XTIndBlock *block);
2286
2287=== modified file 'storage/pbxt/src/lock_xt.cc'
2288--- storage/pbxt/src/lock_xt.cc 2009-11-24 10:55:06 +0000
2289+++ storage/pbxt/src/lock_xt.cc 2010-05-07 08:52:27 +0000
2290@@ -1444,7 +1444,7 @@
2291 #endif
2292 }
2293
2294-xtPublic xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtThreadID XT_NDEBUG_UNUSED(thd_id))
2295+xtPublic xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtBool try_lock, xtThreadID XT_NDEBUG_UNUSED(thd_id))
2296 {
2297 register xtWord2 set;
2298
2299@@ -1453,6 +1453,8 @@
2300 set = xt_atomic_tas2(&sxs->sxs_xlocked, 1);
2301 if (!set)
2302 break;
2303+ if (try_lock)
2304+ return FALSE;
2305 xt_yield();
2306 }
2307
2308@@ -1460,9 +1462,25 @@
2309 sxs->sxs_locker = thd_id;
2310 #endif
2311
2312- /* Wait for all the reader to wait! */
2313- while (sxs->sxs_wait_count < sxs->sxs_rlock_count)
2314- xt_yield();
2315+ /* Wait for all the readers to wait! */
2316+ while (sxs->sxs_wait_count < sxs->sxs_rlock_count) {
2317+ sxs->sxs_xwaiter = 1;
2318+ xt_yield(); //*
2319+ /* This should not be required, because there is only one thread
2320+ * accessing this value. However, the lock fails if this
2321+ * is not done with an atomic op.
2322+ *
2323+ * This is because threads on other processors have the
2324+ * value in processor cache. So they do not
2325+ * notice that the value has been set to zero.
2326+ * They think it is still 1 and march through
2327+ * the barrier (sxs->sxs_xwaiter < sxs->sxs_xlocked) below.
2328+ *
2329+ * In the meantime, this X locker has gone on thinking
2330+ * all is OK.
2331+ */
2332+ xt_atomic_tas2(&sxs->sxs_xwaiter, 0);
2333+ }
2334
2335 #ifdef XT_THREAD_LOCK_INFO
2336 xt_thread_lock_info_add_owner(&sxs->sxs_lock_info);
2337@@ -1474,12 +1492,12 @@
2338 {
2339 xt_atomic_inc2(&sxs->sxs_rlock_count);
2340
2341- /* Check if there could be an X locker: */
2342- if (sxs->sxs_xlocked) {
2343- /* I am waiting... */
2344+ /* Wait as long as the locker is not waiting: */
2345+ while (sxs->sxs_xwaiter < sxs->sxs_xlocked) {
2346 xt_atomic_inc2(&sxs->sxs_wait_count);
2347- while (sxs->sxs_xlocked)
2348+ while (sxs->sxs_xwaiter < sxs->sxs_xlocked) {
2349 xt_yield();
2350+ }
2351 xt_atomic_dec2(&sxs->sxs_wait_count);
2352 }
2353
2354@@ -1493,12 +1511,17 @@
2355 {
2356 if (xlocked) {
2357 #ifdef DEBUG
2358+ ASSERT_NS(sxs->sxs_locker && sxs->sxs_xlocked);
2359 sxs->sxs_locker = 0;
2360 #endif
2361 sxs->sxs_xlocked = 0;
2362 }
2363- else
2364+ else {
2365+#ifdef DEBUG
2366+ ASSERT_NS(sxs->sxs_rlock_count > 0);
2367+#endif
2368 xt_atomic_dec2(&sxs->sxs_rlock_count);
2369+ }
2370
2371 #ifdef XT_THREAD_LOCK_INFO
2372 xt_thread_lock_info_release_owner(&sxs->sxs_lock_info);
2373@@ -1698,7 +1721,7 @@
2374 #endif
2375 }
2376
2377-xtPublic xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr arw, xtThreadID XT_NDEBUG_UNUSED(thr_id))
2378+xtPublic xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr arw, xtBool try_lock, xtThreadID XT_NDEBUG_UNUSED(thr_id))
2379 {
2380 register xtWord2 set;
2381
2382@@ -1707,6 +1730,8 @@
2383 set = xt_atomic_tas2(&arw->arw_xlock_set, 1);
2384 if (!set)
2385 break;
2386+ if (try_lock)
2387+ return FALSE;
2388 xt_yield();
2389 }
2390
2391@@ -1721,7 +1746,7 @@
2392 #ifdef XT_THREAD_LOCK_INFO
2393 xt_thread_lock_info_add_owner(&arw->arw_lock_info);
2394 #endif
2395- return OK;
2396+ return TRUE;
2397 }
2398
2399 xtPublic xtBool xt_atomicrwlock_slock(XTAtomicRWLockPtr arw)
2400@@ -1799,7 +1824,7 @@
2401 #endif
2402 }
2403
2404-xtPublic xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr srw, xtThreadID XT_NDEBUG_UNUSED(thr_id))
2405+xtPublic xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr srw, xtBool try_lock, xtThreadID XT_NDEBUG_UNUSED(thr_id))
2406 {
2407 register xtWord2 set;
2408
2409@@ -1808,6 +1833,8 @@
2410 set = xt_atomic_tas2(&srw->srw_xlock_set, 1);
2411 if (!set)
2412 break;
2413+ if (try_lock)
2414+ return FALSE;
2415 xt_yield();
2416 }
2417
2418@@ -1822,7 +1849,7 @@
2419 #ifdef XT_THREAD_LOCK_INFO
2420 xt_thread_lock_info_add_owner(&srw->srw_lock_info);
2421 #endif
2422- return OK;
2423+ return TRUE;
2424 }
2425
2426 xtPublic xtBool xt_skewrwlock_slock(XTSkewRWLockPtr srw)
2427@@ -1869,6 +1896,124 @@
2428
2429 /*
2430 * -----------------------------------------------------------------------
2431+ * RECURSIVE R/W LOCK (allows X lockers to lock again)
2432+ */
2433+
2434+#ifdef XT_THREAD_LOCK_INFO
2435+void xt_recursivemutex_init(XTThreadPtr self, XTRecursiveMutexPtr rm, const char *name)
2436+{
2437+ rm->rm_locker = NULL;
2438+ rm->rm_lock_count = 0;
2439+ xt_init_mutex(self, &rm->rm_mutex, name);
2440+}
2441+#else
2442+xtPublic void xt_recursivemutex_init(XTThreadPtr self, XTRecursiveMutexPtr rm)
2443+{
2444+ rm->rm_locker = NULL;
2445+ rm->rm_lock_count = 0;
2446+ xt_init_mutex(self, &rm->rm_mutex);
2447+}
2448+#endif
2449+
2450+xtPublic void xt_recursivemutex_free(XTRecursiveMutexPtr rm)
2451+{
2452+ xt_free_mutex(&rm->rm_mutex);
2453+#ifdef XT_THREAD_LOCK_INFO
2454+ xt_thread_lock_info_free(&rm->rm_lock_info);
2455+#endif
2456+}
2457+
2458+xtPublic void xt_recursivemutex_lock(XTThreadPtr self, XTRecursiveMutexPtr rm)
2459+{
2460+ if (self != rm->rm_locker) {
2461+ xt_lock_mutex(self, &rm->rm_mutex);
2462+ rm->rm_locker = self;
2463+ }
2464+ rm->rm_lock_count++;
2465+}
2466+
2467+xtPublic void xt_recursivemutex_unlock(XTThreadPtr self, XTRecursiveMutexPtr rm)
2468+{
2469+ ASSERT(self == rm->rm_locker);
2470+ ASSERT(rm->rm_lock_count > 0);
2471+ rm->rm_lock_count--;
2472+ if (!rm->rm_lock_count) {
2473+ rm->rm_locker = NULL;
2474+ xt_unlock_mutex(self, &rm->rm_mutex);
2475+ }
2476+}
2477+
2478+/*
2479+ * -----------------------------------------------------------------------
2480+ * RECURSIVE MUTEX (allows lockers to lock again)
2481+ */
2482+
2483+#ifdef XT_THREAD_LOCK_INFO
2484+void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw, const char *name)
2485+{
2486+ rrw->rrw_locker = NULL;
2487+ rrw->rrw_lock_count = 0;
2488+ xt_init_rwlock(self, &rrw->rrw_lock, name);
2489+}
2490+#else
2491+void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw)
2492+{
2493+ rrw->rrw_locker = NULL;
2494+ rrw->rrw_lock_count = 0;
2495+ xt_init_rwlock(self, &rrw->rrw_lock);
2496+}
2497+#endif
2498+
2499+void xt_recurrwlock_free(XTRecurRWLockPtr rrw)
2500+{
2501+ xt_free_rwlock(&rrw->rrw_lock);
2502+#ifdef XT_THREAD_LOCK_INFO
2503+ xt_thread_lock_info_free(&rrw->rrw_lock_info);
2504+#endif
2505+}
2506+
2507+void xt_recurrwlock_xlock(struct XTThread *self, XTRecurRWLockPtr rrw)
2508+{
2509+ if (self != rrw->rrw_locker) {
2510+ xt_xlock_rwlock(self, &rrw->rrw_lock);
2511+ rrw->rrw_locker = self;
2512+ }
2513+ rrw->rrw_lock_count++;
2514+}
2515+
2516+void xt_recurrwlock_slock(struct XTThread *self, XTRecurRWLockPtr rrw)
2517+{
2518+ xt_slock_rwlock(self, &rrw->rrw_lock);
2519+}
2520+
2521+void xt_recurrwlock_slock_ns(XTRecurRWLockPtr rrw)
2522+{
2523+ xt_slock_rwlock_ns(&rrw->rrw_lock);
2524+}
2525+
2526+void xt_recurrwlock_unxlock(struct XTThread *self, XTRecurRWLockPtr rrw)
2527+{
2528+ ASSERT(self == rrw->rrw_locker);
2529+ ASSERT(rrw->rrw_lock_count > 0);
2530+ rrw->rrw_lock_count--;
2531+ if (!rrw->rrw_lock_count) {
2532+ rrw->rrw_locker = NULL;
2533+ xt_unlock_rwlock(self, &rrw->rrw_lock);
2534+ }
2535+}
2536+
2537+void xt_recurrwlock_unslock(struct XTThread *self, XTRecurRWLockPtr rrw)
2538+{
2539+ xt_unlock_rwlock(self, &rrw->rrw_lock);
2540+}
2541+
2542+void xt_recurrwlock_unslock_ns(XTRecurRWLockPtr rrw)
2543+{
2544+ xt_unlock_rwlock_ns(&rrw->rrw_lock);
2545+}
2546+
2547+/*
2548+ * -----------------------------------------------------------------------
2549 * UNIT TESTS
2550 */
2551
2552@@ -2031,7 +2176,7 @@
2553 xt_rwmutex_unlock(&data->xs_lock, self->t_id);
2554 }
2555 else if (data->xs_which_lock == LOCK_SPINXSLOCK) {
2556- xt_spinxslock_xlock(&data->xs_spinrwlock, self->t_id);
2557+ xt_spinxslock_xlock(&data->xs_spinrwlock, FALSE, self->t_id);
2558 lck_do_job(self, data->xs_which_job, data, FALSE);
2559 xt_spinxslock_unlock(&data->xs_spinrwlock, TRUE);
2560 }
2561@@ -2041,12 +2186,12 @@
2562 xt_xsmutex_unlock(&data->xs_fastrwlock, self->t_id);
2563 }
2564 else if (data->xs_which_lock == LOCK_ATOMICRWLOCK) {
2565- xt_atomicrwlock_xlock(&data->xs_atomicrwlock, self->t_id);
2566+ xt_atomicrwlock_xlock(&data->xs_atomicrwlock, FALSE, self->t_id);
2567 lck_do_job(self, data->xs_which_job, data, FALSE);
2568 xt_atomicrwlock_unlock(&data->xs_atomicrwlock, TRUE);
2569 }
2570 else if (data->xs_which_lock == LOCK_SKEWRWLOCK) {
2571- xt_skewrwlock_xlock(&data->xs_skewrwlock, self->t_id);
2572+ xt_skewrwlock_xlock(&data->xs_skewrwlock, FALSE, self->t_id);
2573 lck_do_job(self, data->xs_which_job, data, FALSE);
2574 xt_skewrwlock_unlock(&data->xs_skewrwlock, TRUE);
2575 }
2576
2577=== modified file 'storage/pbxt/src/lock_xt.h'
2578--- storage/pbxt/src/lock_xt.h 2009-08-17 11:12:36 +0000
2579+++ storage/pbxt/src/lock_xt.h 2010-05-07 08:52:27 +0000
2580@@ -109,7 +109,8 @@
2581 inline void xt_atomic_inc2(volatile xtWord2 *mptr)
2582 {
2583 #ifdef XT_ATOMIC_WIN32_X86
2584- __asm LOCK INC WORD PTR mptr
2585+ __asm MOV ECX, mptr
2586+ __asm LOCK INC WORD PTR [ECX]
2587 #elif defined(XT_ATOMIC_GNUC_X86)
2588 asm volatile ("lock; incw %0" : : "m" (*mptr) : "memory");
2589 #elif defined(XT_ATOMIC_GCC_OPS)
2590@@ -125,7 +126,8 @@
2591 inline void xt_atomic_dec2(volatile xtWord2 *mptr)
2592 {
2593 #ifdef XT_ATOMIC_WIN32_X86
2594- __asm LOCK DEC WORD PTR mptr
2595+ __asm MOV ECX, mptr
2596+ __asm LOCK DEC WORD PTR [ECX]
2597 #elif defined(XT_ATOMIC_GNUC_X86)
2598 asm volatile ("lock; decw %0" : : "m" (*mptr) : "memory");
2599 #elif defined(XT_ATOMIC_GCC_OPS)
2600@@ -427,6 +429,7 @@
2601
2602 typedef struct XTSpinXSLock {
2603 volatile xtWord2 sxs_xlocked;
2604+ volatile xtWord2 sxs_xwaiter;
2605 volatile xtWord2 sxs_rlock_count;
2606 volatile xtWord2 sxs_wait_count; /* The number of readers waiting for the xlocker. */
2607 #ifdef DEBUG
2608@@ -446,7 +449,7 @@
2609 void xt_spinxslock_init(struct XTThread *self, XTSpinXSLockPtr sxs);
2610 #endif
2611 void xt_spinxslock_free(struct XTThread *self, XTSpinXSLockPtr sxs);
2612-xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtThreadID thd_id);
2613+xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtBool try_lock, xtThreadID thd_id);
2614 xtBool xt_spinxslock_slock(XTSpinXSLockPtr sxs);
2615 xtBool xt_spinxslock_unlock(XTSpinXSLockPtr sxs, xtBool xlocked);
2616
2617@@ -500,7 +503,7 @@
2618 void xt_atomicrwlock_init(struct XTThread *self, XTAtomicRWLockPtr xsl);
2619 #endif
2620 void xt_atomicrwlock_free(struct XTThread *self, XTAtomicRWLockPtr xsl);
2621-xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr xsl, xtThreadID thr_id);
2622+xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr xsl, xtBool try_lock, xtThreadID thr_id);
2623 xtBool xt_atomicrwlock_slock(XTAtomicRWLockPtr xsl);
2624 xtBool xt_atomicrwlock_unlock(XTAtomicRWLockPtr xsl, xtBool xlocked);
2625
2626@@ -525,7 +528,7 @@
2627 void xt_skewrwlock_init(struct XTThread *self, XTSkewRWLockPtr xsl);
2628 #endif
2629 void xt_skewrwlock_free(struct XTThread *self, XTSkewRWLockPtr xsl);
2630-xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr xsl, xtThreadID thr_id);
2631+xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr xsl, xtBool try_lock, xtThreadID thr_id);
2632 xtBool xt_skewrwlock_slock(XTSkewRWLockPtr xsl);
2633 xtBool xt_skewrwlock_unlock(XTSkewRWLockPtr xsl, xtBool xlocked);
2634
2635@@ -713,4 +716,57 @@
2636 #define XT_HAVE_LOCK 2
2637 #define XT_WAITING 3
2638
2639+/*
2640+ * -----------------------------------------------------------------------
2641+ * RECURSIVE MUTEX (allows lockers to lock again)
2642+ */
2643+
2644+typedef struct XTRecursiveMutex {
2645+ struct XTThread *rm_locker;
2646+ u_int rm_lock_count;
2647+ xt_mutex_type rm_mutex;
2648+
2649+#ifdef XT_THREAD_LOCK_INFO
2650+ XTThreadLockInfoRec rm_lock_info;
2651+ const char *rm_name;
2652+#endif
2653+} XTRecursiveMutexRec, *XTRecursiveMutexPtr;
2654+
2655+#ifdef XT_THREAD_LOCK_INFO
2656+#define xt_recursivemutex_init_with_autoname(a,b) xt_recursivemutex_init(a,b,LOCKLIST_ARG_SUFFIX(b))
2657+void xt_recursivemutex_init(struct XTThread *self, XTRecursiveMutexPtr rm, const char *name);
2658+#else
2659+#define xt_recursivemutex_init_with_autoname(a,b) xt_recursivemutex_init(a,b)
2660+void xt_recursivemutex_init(struct XTThread *self, XTRecursiveMutexPtr rm);
2661+#endif
2662+void xt_recursivemutex_free(XTRecursiveMutexPtr rm);
2663+void xt_recursivemutex_lock(struct XTThread *self, XTRecursiveMutexPtr rm);
2664+void xt_recursivemutex_unlock(struct XTThread *self, XTRecursiveMutexPtr rm);
2665+
2666+typedef struct XTRecurRWLock {
2667+ struct XTThread *rrw_locker;
2668+ u_int rrw_lock_count;
2669+ xt_rwlock_type rrw_lock;
2670+
2671+#ifdef XT_THREAD_LOCK_INFO
2672+ XTThreadLockInfoRec rrw_lock_info;
2673+ const char *rrw_name;
2674+#endif
2675+} XTRecurRWLockRec, *XTRecurRWLockPtr;
2676+
2677+#ifdef XT_THREAD_LOCK_INFO
2678+#define xt_recurrwlock_init_with_autoname(a,b) xt_recurrwlock_init(a,b,LOCKLIST_ARG_SUFFIX(b))
2679+void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw, const char *name);
2680+#else
2681+#define xt_recurrwlock_init_with_autoname(a,b) xt_recurrwlock_init(a,b)
2682+void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw);
2683+#endif
2684+void xt_recurrwlock_free(XTRecurRWLockPtr rrw);
2685+void xt_recurrwlock_xlock(struct XTThread *self, XTRecurRWLockPtr rrw);
2686+void xt_recurrwlock_slock(struct XTThread *self, XTRecurRWLockPtr rrw);
2687+void xt_recurrwlock_slock_ns(XTRecurRWLockPtr rrw);
2688+void xt_recurrwlock_unxlock(struct XTThread *self, XTRecurRWLockPtr rrw);
2689+void xt_recurrwlock_unslock(struct XTThread *self, XTRecurRWLockPtr rrw);
2690+void xt_recurrwlock_unslock_ns(XTRecurRWLockPtr rrw);
2691+
2692 #endif
2693
2694=== modified file 'storage/pbxt/src/locklist_xt.cc'
2695--- storage/pbxt/src/locklist_xt.cc 2010-04-21 00:25:59 +0000
2696+++ storage/pbxt/src/locklist_xt.cc 2010-05-07 08:52:27 +0000
2697@@ -180,6 +180,10 @@
2698 lock_type = "XTAtomicRWLock";
2699 lock_name = li->li_atomic_rwlock->arw_name;
2700 break;
2701+ case XTThreadLockInfo::SKEW_RW_LOCK:
2702+ lock_type = "XTSkewRWLock";
2703+ lock_name = li->li_skew_rwlock->srw_name;
2704+ break;
2705 }
2706
2707 xt_ttracef(self, " #lock#%d: type: %s name: %s \n", count, lock_type, lock_name);
2708
2709=== modified file 'storage/pbxt/src/myxt_xt.cc'
2710--- storage/pbxt/src/myxt_xt.cc 2009-12-10 11:36:05 +0000
2711+++ storage/pbxt/src/myxt_xt.cc 2010-05-07 08:52:27 +0000
2712@@ -255,6 +255,11 @@
2713 xtWord1 *end;
2714 xtWord1 *start;
2715
2716+#ifdef HAVE_valgrind
2717+ if (ind->mi_fix_key)
2718+ memset((byte*) key, 0,(size_t) (ind->mi_key_size) );
2719+#endif
2720+
2721 start = key;
2722 for (u_int i=0; i<ind->mi_seg_count; i++, keyseg++)
2723 {
2724@@ -531,7 +536,7 @@
2725 key += length;
2726 }
2727
2728- return fkey_ind->mi_fix_key ? fkey_ind->mi_key_size : (u_int) (key - start); /* Return keylength */
2729+ return (u_int) (key - start);
2730 }
2731
2732 /* I may be overcautious here, but can I assume that
2733@@ -2132,10 +2137,10 @@
2734 {
2735 enter_();
2736 /* The dirty list of cache pages should be empty here! */
2737- ASSERT(!mi->mi_dirty_list);
2738+ /* This is not the case if we were not able to flush data. E.g. when running out of disk space */
2739+ //ASSERT(!mi->mi_dirty_list);
2740 ASSERT(!mi->mi_free_list);
2741
2742- xt_free_mutex(&mi->mi_flush_lock);
2743 xt_spinlock_free(self, &mi->mi_dirty_lock);
2744 XT_INDEX_FREE_LOCK(self, mi);
2745 myxt_bitmap_free(self, &mi->mi_col_map);
2746@@ -2174,7 +2179,6 @@
2747 pushsr_(ind, my_deref_index_data, (XTIndexPtr) xt_calloc(self, MX_OFFSETOF(XTIndexRec, mi_seg) + sizeof(XTIndexSegRec) * index->key_parts));
2748
2749 XT_INDEX_INIT_LOCK(self, ind);
2750- xt_init_mutex_with_autoname(self, &ind->mi_flush_lock);
2751 xt_spinlock_init_with_autoname(self, &ind->mi_dirty_lock);
2752 ind->mi_index_no = idx;
2753 ind->mi_flags = (index->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL | HA_UNIQUE_CHECK));
2754@@ -2556,8 +2560,12 @@
2755 ave_row_size += 3 + ave_data_size;
2756
2757 /* This is the length of the record required for all indexes: */
2758- if (field_count + 1 == dic->dic_ind_cols_req)
2759- dic->dic_ind_rec_len = max_data_size;
2760+ /* This was calculated incorrectly. Not a serius bug because it
2761+ * is only used in the case of fixed length row, and in this
2762+ * case the dic_ind_rec_len is set correctly below.
2763+ */
2764+ if (field_count == dic->dic_ind_cols_req)
2765+ dic->dic_ind_rec_len = max_row_size;
2766 }
2767
2768 dic->dic_min_row_size = min_row_size;
2769@@ -2624,6 +2632,20 @@
2770 }
2771 }
2772
2773+ /* Ensure that handle data record size is big enough to
2774+ * include the extended record reference, in the case of
2775+ * variable length rows
2776+ */
2777+ if (!dic_rec_fixed) {
2778+ if (dic_rec_size < offsetof(XTTabRecExtDRec, re_data))
2779+ dic_rec_size = offsetof(XTTabRecExtDRec, re_data);
2780+ }
2781+#ifdef DEBUG
2782+ else {
2783+ ASSERT_NS(dic_rec_size > offsetof(XTTabRecFix, rf_data));
2784+ }
2785+#endif
2786+
2787 if (!dic->dic_rec_size) {
2788 dic->dic_rec_size = dic_rec_size;
2789 dic->dic_rec_fixed = dic_rec_fixed;
2790@@ -2861,6 +2883,7 @@
2791 for (key_part = key->key_part; key_part != key_part_end; key_part++) {
2792 if (!(cref = new XTDDColumnRef()))
2793 xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
2794+ cref->init(self);
2795 ind->co_cols.append(self, cref);
2796 cref->cr_col_name = xt_dup_string(self, (char *) key_part->field->field_name);
2797 }
2798
2799=== modified file 'storage/pbxt/src/pthread_xt.cc'
2800--- storage/pbxt/src/pthread_xt.cc 2009-11-24 10:55:06 +0000
2801+++ storage/pbxt/src/pthread_xt.cc 2010-05-07 08:52:27 +0000
2802@@ -39,25 +39,25 @@
2803
2804 #ifdef XT_WIN
2805
2806-void xt_p_init_threading(void)
2807+xtPublic void xt_p_init_threading(void)
2808 {
2809 }
2810
2811-int xt_p_set_normal_priority(pthread_t thr)
2812+xtPublic int xt_p_set_normal_priority(pthread_t thr)
2813 {
2814 if (!SetThreadPriority (thr, THREAD_PRIORITY_NORMAL))
2815 return GetLastError();
2816 return 0;
2817 }
2818
2819-int xt_p_set_low_priority(pthread_t thr)
2820+xtPublic int xt_p_set_low_priority(pthread_t thr)
2821 {
2822 if (!SetThreadPriority (thr, THREAD_PRIORITY_LOWEST))
2823 return GetLastError();
2824 return 0;
2825 }
2826
2827-int xt_p_set_high_priority(pthread_t thr)
2828+xtPublic int xt_p_set_high_priority(pthread_t thr)
2829 {
2830 if (!SetThreadPriority (thr, THREAD_PRIORITY_HIGHEST))
2831 return GetLastError();
2832@@ -67,9 +67,9 @@
2833 #define XT_RWLOCK_MAGIC 0x78AC390E
2834
2835 #ifdef XT_THREAD_LOCK_INFO
2836-int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr, const char *n)
2837+xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr, const char *n)
2838 #else
2839-int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr)
2840+xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr)
2841 #endif
2842 {
2843 InitializeCriticalSection(&mutex->mt_cs);
2844@@ -80,7 +80,7 @@
2845 return 0;
2846 }
2847
2848-int xt_p_mutex_destroy(xt_mutex_type *mutex)
2849+xtPublic int xt_p_mutex_destroy(xt_mutex_type *mutex)
2850 {
2851 DeleteCriticalSection(&mutex->mt_cs);
2852 #ifdef XT_THREAD_LOCK_INFO
2853@@ -89,7 +89,7 @@
2854 return 0;
2855 }
2856
2857-int xt_p_mutex_lock(xt_mutex_type *mx)
2858+xtPublic int xt_p_mutex_lock(xt_mutex_type *mx)
2859 {
2860 EnterCriticalSection(&mx->mt_cs);
2861 #ifdef XT_THREAD_LOCK_INFO
2862@@ -98,7 +98,7 @@
2863 return 0;
2864 }
2865
2866-int xt_p_mutex_unlock(xt_mutex_type *mx)
2867+xtPublic int xt_p_mutex_unlock(xt_mutex_type *mx)
2868 {
2869 LeaveCriticalSection(&mx->mt_cs);
2870 #ifdef XT_THREAD_LOCK_INFO
2871@@ -107,7 +107,7 @@
2872 return 0;
2873 }
2874
2875-int xt_p_mutex_trylock(xt_mutex_type *mutex)
2876+xtPublic int xt_p_mutex_trylock(xt_mutex_type *mutex)
2877 {
2878 #if(_WIN32_WINNT >= 0x0400)
2879 /* NOTE: MySQL bug! was using?!
2880@@ -130,9 +130,9 @@
2881 }
2882
2883 #ifdef XT_THREAD_LOCK_INFO
2884-int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr, const char *n)
2885+xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr, const char *n)
2886 #else
2887-int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr)
2888+xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr)
2889 #endif
2890 {
2891 int result;
2892@@ -173,7 +173,7 @@
2893 return result;
2894 }
2895
2896-int xt_p_rwlock_destroy(xt_rwlock_type *rwl)
2897+xtPublic int xt_p_rwlock_destroy(xt_rwlock_type *rwl)
2898 {
2899 int result = 0, result1 = 0, result2 = 0;
2900
2901@@ -225,7 +225,7 @@
2902 }
2903
2904
2905-int xt_p_rwlock_rdlock(xt_rwlock_type *rwl)
2906+xtPublic int xt_p_rwlock_rdlock(xt_rwlock_type *rwl)
2907 {
2908 int result;
2909
2910@@ -262,7 +262,7 @@
2911 return (xt_p_mutex_unlock (&(rwl->rw_ex_lock)));
2912 }
2913
2914-int xt_p_rwlock_wrlock(xt_rwlock_type *rwl)
2915+xtPublic int xt_p_rwlock_wrlock(xt_rwlock_type *rwl)
2916 {
2917 int result;
2918
2919@@ -309,7 +309,54 @@
2920 return result;
2921 }
2922
2923-int xt_p_rwlock_unlock(xt_rwlock_type *rwl)
2924+xtPublic xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwl)
2925+{
2926+ int result;
2927+
2928+ if (rwl == NULL)
2929+ return FALSE;
2930+
2931+ if (rwl->rw_magic != XT_RWLOCK_MAGIC)
2932+ return FALSE;
2933+
2934+ if ((result = xt_p_mutex_trylock(&rwl->rw_ex_lock)) != 0)
2935+ return FALSE;
2936+
2937+ if ((result = xt_p_mutex_lock(&rwl->rw_sh_lock)) != 0) {
2938+ (void) xt_p_mutex_unlock(&rwl->rw_ex_lock);
2939+ return FALSE;
2940+ }
2941+
2942+ if (rwl->rw_ex_count == 0) {
2943+ if (rwl->rw_sh_complete_count > 0) {
2944+ rwl->rw_sh_count -= rwl->rw_sh_complete_count;
2945+ rwl->rw_sh_complete_count = 0;
2946+ }
2947+
2948+ if (rwl->rw_sh_count > 0) {
2949+ rwl->rw_sh_complete_count = -rwl->rw_sh_count;
2950+
2951+ do {
2952+ result = pthread_cond_wait (&rwl->rw_sh_cond, &rwl->rw_sh_lock.mt_cs);
2953+ }
2954+ while (result == 0 && rwl->rw_sh_complete_count < 0);
2955+
2956+ if (result == 0)
2957+ rwl->rw_sh_count = 0;
2958+ }
2959+ }
2960+
2961+ if (result == 0)
2962+ rwl->rw_ex_count++;
2963+
2964+#ifdef XT_THREAD_LOCK_INFO
2965+ xt_thread_lock_info_add_owner(&rwl->rw_lock_info);
2966+#endif
2967+
2968+ return TRUE;
2969+}
2970+
2971+xtPublic int xt_p_rwlock_unlock(xt_rwlock_type *rwl)
2972 {
2973 int result, result1;
2974
2975@@ -342,12 +389,12 @@
2976 return ((result != 0) ? result : result1);
2977 }
2978
2979-int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex)
2980+xtPublic int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex)
2981 {
2982 return xt_p_cond_timedwait(cond, mutex, NULL);
2983 }
2984
2985-int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mt, struct timespec *abstime)
2986+xtPublic int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mt, struct timespec *abstime)
2987 {
2988 pthread_mutex_t *mutex = &mt->mt_cs;
2989 int result;
2990@@ -393,7 +440,7 @@
2991 return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
2992 }
2993
2994-int xt_p_join(pthread_t thread, void **value)
2995+xtPublic int xt_p_join(pthread_t thread, void **value)
2996 {
2997 DWORD exitcode;
2998
2999@@ -676,6 +723,23 @@
3000 return r;
3001 }
3002
3003+xtPublic xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwlock)
3004+{
3005+ XTThreadPtr self = xt_get_self();
3006+ int r;
3007+
3008+ ASSERT_NS(rwlock->rw_init == 67890);
3009+ r = pthread_rwlock_trywrlock(&rwlock->rw_plock);
3010+ if (r == 0) {
3011+ ASSERT_NS(!rwlock->rw_locker);
3012+ rwlock->rw_locker = self;
3013+#ifdef XT_THREAD_LOCK_INFO
3014+ xt_thread_lock_info_add_owner(&rwlock->rw_lock_info);
3015+#endif
3016+ }
3017+ return r == 0;
3018+}
3019+
3020 xtPublic int xt_p_rwlock_unlock(xt_rwlock_type *rwlock)
3021 {
3022 XTThreadPtr self = xt_get_self();
3023
3024=== modified file 'storage/pbxt/src/pthread_xt.h'
3025--- storage/pbxt/src/pthread_xt.h 2009-03-26 12:18:01 +0000
3026+++ storage/pbxt/src/pthread_xt.h 2010-05-07 08:52:27 +0000
3027@@ -101,13 +101,14 @@
3028 #else
3029 int xt_p_rwlock_init(xt_rwlock_type *rwlock, const pthread_condattr_t *attr);
3030 #endif
3031-int xt_p_rwlock_destroy(xt_rwlock_type *rwlock);
3032-int xt_p_rwlock_rdlock(xt_rwlock_type *mx);
3033-int xt_p_rwlock_wrlock(xt_rwlock_type *mx);
3034-int xt_p_rwlock_unlock(xt_rwlock_type *mx);
3035+int xt_p_rwlock_destroy(xt_rwlock_type *rwlock);
3036+int xt_p_rwlock_rdlock(xt_rwlock_type *mx);
3037+int xt_p_rwlock_wrlock(xt_rwlock_type *mx);
3038+xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwl);
3039+int xt_p_rwlock_unlock(xt_rwlock_type *mx);
3040
3041-int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex);
3042-int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mutex, struct timespec *abstime);
3043+int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex);
3044+int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mutex, struct timespec *abstime);
3045
3046 int xt_p_join(pthread_t thread, void **value);
3047
3048@@ -125,6 +126,7 @@
3049
3050 #define xt_slock_rwlock_ns xt_p_rwlock_rdlock
3051 #define xt_xlock_rwlock_ns xt_p_rwlock_wrlock
3052+#define xt_xlock_try_rwlock_ns xt_p_rwlock_try_wrlock
3053 #define xt_unlock_rwlock_ns xt_p_rwlock_unlock
3054
3055 #ifdef XT_THREAD_LOCK_INFO
3056@@ -225,9 +227,10 @@
3057 #endif
3058 } xt_rwlock_type;
3059
3060-int xt_p_rwlock_rdlock(xt_rwlock_type *mx);
3061-int xt_p_rwlock_wrlock(xt_rwlock_type *mx);
3062-int xt_p_rwlock_unlock(xt_rwlock_type *mx);
3063+int xt_p_rwlock_rdlock(xt_rwlock_type *mx);
3064+int xt_p_rwlock_wrlock(xt_rwlock_type *mx);
3065+xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *mx);
3066+int xt_p_rwlock_unlock(xt_rwlock_type *mx);
3067
3068 int xt_p_mutex_lock(xt_mutex_type *mx, u_int line, const char *file);
3069 int xt_p_mutex_unlock(xt_mutex_type *mx);
3070@@ -251,37 +254,39 @@
3071 }
3072 #endif
3073
3074-#define xt_slock_rwlock_ns xt_p_rwlock_rdlock
3075-#define xt_xlock_rwlock_ns xt_p_rwlock_wrlock
3076-#define xt_unlock_rwlock_ns xt_p_rwlock_unlock
3077+#define xt_slock_rwlock_ns xt_p_rwlock_rdlock
3078+#define xt_xlock_rwlock_ns xt_p_rwlock_wrlock
3079+#define xt_xlock_try_rwlock_ns xt_p_rwlock_try_wrlock
3080+#define xt_unlock_rwlock_ns xt_p_rwlock_unlock
3081
3082-#define xt_lock_mutex_ns(x) xt_p_mutex_lock(x, __LINE__, __FILE__)
3083-#define xt_unlock_mutex_ns xt_p_mutex_unlock
3084-#define xt_mutex_trylock xt_p_mutex_trylock
3085+#define xt_lock_mutex_ns(x) xt_p_mutex_lock(x, __LINE__, __FILE__)
3086+#define xt_unlock_mutex_ns xt_p_mutex_unlock
3087+#define xt_mutex_trylock xt_p_mutex_trylock
3088
3089 #else // DEBUG_LOCKING
3090
3091-#define xt_rwlock_struct _opaque_pthread_rwlock_t
3092-#define xt_mutex_struct _opaque_pthread_mutex_t
3093-
3094-#define xt_rwlock_type pthread_rwlock_t
3095-#define xt_mutex_type pthread_mutex_t
3096-
3097-#define xt_slock_rwlock_ns pthread_rwlock_rdlock
3098-#define xt_xlock_rwlock_ns pthread_rwlock_wrlock
3099-#define xt_unlock_rwlock_ns pthread_rwlock_unlock
3100-
3101-#define xt_lock_mutex_ns pthread_mutex_lock
3102-#define xt_unlock_mutex_ns pthread_mutex_unlock
3103-#define xt_mutex_trylock pthread_mutex_trylock
3104-
3105-#define xt_p_mutex_trylock pthread_mutex_trylock
3106-#define xt_p_mutex_destroy pthread_mutex_destroy
3107-#define xt_p_mutex_init pthread_mutex_init
3108-#define xt_p_rwlock_destroy pthread_rwlock_destroy
3109-#define xt_p_rwlock_init pthread_rwlock_init
3110-#define xt_p_cond_wait pthread_cond_wait
3111-#define xt_p_cond_timedwait pthread_cond_timedwait
3112+#define xt_rwlock_struct _opaque_pthread_rwlock_t
3113+#define xt_mutex_struct _opaque_pthread_mutex_t
3114+
3115+#define xt_rwlock_type pthread_rwlock_t
3116+#define xt_mutex_type pthread_mutex_t
3117+
3118+#define xt_slock_rwlock_ns pthread_rwlock_rdlock
3119+#define xt_xlock_rwlock_ns pthread_rwlock_wrlock
3120+#define xt_xlock_try_rwlock_ns(x) (pthread_rwlock_trywrlock(x) == 0)
3121+#define xt_unlock_rwlock_ns pthread_rwlock_unlock
3122+
3123+#define xt_lock_mutex_ns pthread_mutex_lock
3124+#define xt_unlock_mutex_ns pthread_mutex_unlock
3125+#define xt_mutex_trylock pthread_mutex_trylock
3126+
3127+#define xt_p_mutex_trylock pthread_mutex_trylock
3128+#define xt_p_mutex_destroy pthread_mutex_destroy
3129+#define xt_p_mutex_init pthread_mutex_init
3130+#define xt_p_rwlock_destroy pthread_rwlock_destroy
3131+#define xt_p_rwlock_init pthread_rwlock_init
3132+#define xt_p_cond_wait pthread_cond_wait
3133+#define xt_p_cond_timedwait pthread_cond_timedwait
3134
3135 #endif // DEBUG_LOCKING
3136
3137
3138=== modified file 'storage/pbxt/src/restart_xt.cc'
3139--- storage/pbxt/src/restart_xt.cc 2010-01-06 21:27:53 +0000
3140+++ storage/pbxt/src/restart_xt.cc 2010-05-07 08:52:27 +0000
3141@@ -1315,7 +1315,7 @@
3142 tab->tab_head_op_seq = op->or_op_seq;
3143 if (tab->tab_wr_wake_freeer) {
3144 if (!XTTableSeq::xt_op_is_before(tab->tab_head_op_seq, tab->tab_wake_freeer_op))
3145- xt_wr_wake_freeer(self);
3146+ xt_wr_wake_freeer(self, ws->ws_db);
3147 }
3148 i++;
3149 }
3150@@ -1498,7 +1498,7 @@
3151 tab->tab_head_op_seq = op_seq;
3152 if (tab->tab_wr_wake_freeer) {
3153 if (!XTTableSeq::xt_op_is_before(tab->tab_head_op_seq, tab->tab_wake_freeer_op))
3154- xt_wr_wake_freeer(self);
3155+ xt_wr_wake_freeer(self, ws->ws_db);
3156 }
3157
3158 /* Apply any operations in the list that now follow on...
3159@@ -1575,10 +1575,12 @@
3160 static void xres_init_checkpoint_state(XTThreadPtr self, XTCheckPointStatePtr cp)
3161 {
3162 xt_init_mutex_with_autoname(self, &cp->cp_state_lock);
3163+ cp->cp_inited = TRUE;
3164 }
3165
3166 static void xres_free_checkpoint_state(XTThreadPtr self, XTCheckPointStatePtr cp)
3167 {
3168+ cp->cp_inited = FALSE;
3169 xt_free_mutex(&cp->cp_state_lock);
3170 if (cp->cp_table_ids) {
3171 xt_free_sortedlist(self, cp->cp_table_ids);
3172@@ -1616,6 +1618,7 @@
3173
3174 xt_init_mutex_with_autoname(self, &db->db_cp_lock);
3175 xt_init_cond(self, &db->db_cp_cond);
3176+ xt_init_mutex_with_autoname(self, &db->db_fl_lock);
3177
3178 xres_init_checkpoint_state(self, &db->db_cp_state);
3179 db->db_restart.xres_init(self, db, &db->db_wr_log_id, &db->db_wr_log_offset, &max_log_id);
3180@@ -1633,6 +1636,7 @@
3181 xres_free_checkpoint_state(self, &db->db_cp_state);
3182 xt_free_mutex(&db->db_cp_lock);
3183 xt_free_cond(&db->db_cp_cond);
3184+ xt_free_mutex(&db->db_fl_lock);
3185 }
3186
3187 /* ----------------------------------------------------------------------
3188@@ -2182,7 +2186,7 @@
3189
3190 xtBool XTXactRestart::xres_is_checkpoint_pending(xtLogID curr_log_id, xtLogOffset curr_log_offset)
3191 {
3192- return xt_bytes_since_last_checkpoint(xres_db, curr_log_id, curr_log_offset) >= xt_db_checkpoint_frequency / 2;
3193+ return xt_bytes_since_last_checkpoint(xres_db, curr_log_id, curr_log_offset) >= xt_db_checkpoint_frequency;
3194 }
3195
3196 /*
3197@@ -2531,10 +2535,10 @@
3198 XTDatabaseHPtr db = self->st_database;
3199 u_int curr_writer_total;
3200 time_t now;
3201+ xtXactID sweep_count;
3202
3203 xt_set_low_priority(self);
3204
3205-
3206 while (!self->t_quit) {
3207 /* Wait 2 seconds: */
3208 curr_writer_total = db->db_xn_total_writer_count;
3209@@ -2549,9 +2553,13 @@
3210 if (self->t_quit)
3211 break;
3212
3213- if (curr_writer_total == db->db_xn_total_writer_count)
3214+ sweep_count = db->db_xn_curr_id + 1 - db->db_xn_to_clean_id;
3215+ if (curr_writer_total == db->db_xn_total_writer_count &&
3216+ !sweep_count &&
3217+ db->db_wr_idle == XT_THREAD_IDLE) {
3218 /* No activity in 2 seconds: */
3219 xres_cp_checkpoint(self, db, curr_writer_total, FALSE);
3220+ }
3221 else {
3222 /* There server is busy, check if we need to
3223 * write a checkpoint anyway...
3224@@ -2672,6 +2680,10 @@
3225 XTOperationPtr op;
3226 XTCheckPointTableRec cpt;
3227 XTSortedListPtr tables = NULL;
3228+
3229+ /* during startup we can get an error before the checkpointer is inited */
3230+ if (!cp->cp_inited)
3231+ return FAILED;
3232
3233 /* First check if a checkpoint is already running: */
3234 xt_lock_mutex_ns(&cp->cp_state_lock);
3235@@ -3314,7 +3326,7 @@
3236 * #7 0x000c0db2 in THD::~THD at sql_class.cc:934
3237 * #8 0x003b025b in myxt_destroy_thread at myxt_xt.cc:2999
3238 * #9 0x003b66b5 in xn_xres_run_recovery_thread at restart_xt.cc:3196
3239- * #10 0x003cbfbb in thr_main_pbxt at thread_xt.cc:1020
3240+ * #10 0x003cbfbb in xt_thread_main at thread_xt.cc:1020
3241 *
3242 myxt_destroy_thread(mysql_thread, TRUE);
3243 */
3244@@ -3350,3 +3362,123 @@
3245 xt_wait_for_thread(tid, TRUE);
3246 }
3247 }
3248+
3249+/* ----------------------------------------------------------------------
3250+ * L O G F L U S H P R O C E S S
3251+ */
3252+
3253+static void *xres_fl_run_thread(XTThreadPtr self)
3254+{
3255+ XTDatabaseHPtr db = (XTDatabaseHPtr) self->t_data;
3256+ int count;
3257+ void *mysql_thread;
3258+ xtWord8 to_flush;
3259+
3260+ if (!(mysql_thread = myxt_create_thread()))
3261+ xt_throw(self);
3262+
3263+ while (!self->t_quit) {
3264+ try_(a) {
3265+ /*
3266+ * The garbage collector requires that the database
3267+ * is in use because.
3268+ */
3269+ xt_use_database(self, db, XT_FOR_CHECKPOINTER);
3270+
3271+ /* This action is both safe and required (see details elsewhere) */
3272+ xt_heap_release(self, self->st_database);
3273+
3274+ xt_set_low_priority(self);
3275+
3276+ to_flush = xt_trace_clock() + XT_XLOG_FLUSH_FREQ * 1000;
3277+ for (;;) {
3278+ /* Wait 1 second: */
3279+ while (!self->t_quit && xt_trace_clock() < to_flush)
3280+ xt_sleep_milli_second(10);
3281+
3282+ if (self->t_quit)
3283+ break;
3284+
3285+ if (!db->db_xlog.xlog_flush(self))
3286+ xt_throw(self);
3287+
3288+ to_flush += XT_XLOG_FLUSH_FREQ * 1000;
3289+ }
3290+ }
3291+ catch_(a) {
3292+ /* This error is "normal"! */
3293+ if (self->t_exception.e_xt_err != XT_ERR_NO_DICTIONARY &&
3294+ !(self->t_exception.e_xt_err == XT_SIGNAL_CAUGHT &&
3295+ self->t_exception.e_sys_err == SIGTERM))
3296+ xt_log_and_clear_exception(self);
3297+ }
3298+ cont_(a);
3299+
3300+ /* Avoid releasing the database (done above) */
3301+ self->st_database = NULL;
3302+ xt_unuse_database(self, self);
3303+
3304+ /* After an exception, pause before trying again... */
3305+ /* Number of seconds */
3306+ count = 60;
3307+ while (!self->t_quit && count > 0) {
3308+ sleep(1);
3309+ count--;
3310+ }
3311+ }
3312+
3313+ /*
3314+ * {MYSQL-THREAD-KILL}
3315+ myxt_destroy_thread(mysql_thread, TRUE);
3316+ */
3317+ return NULL;
3318+}
3319+
3320+static void xres_fl_free_thread(XTThreadPtr self, void *data)
3321+{
3322+ XTDatabaseHPtr db = (XTDatabaseHPtr) data;
3323+
3324+ if (db->db_fl_thread) {
3325+ xt_lock_mutex(self, &db->db_fl_lock);
3326+ pushr_(xt_unlock_mutex, &db->db_fl_lock);
3327+ db->db_fl_thread = NULL;
3328+ freer_(); // xt_unlock_mutex(&db->db_fl_lock)
3329+ }
3330+}
3331+
3332+xtPublic void xt_start_flusher(XTThreadPtr self, XTDatabaseHPtr db)
3333+{
3334+ char name[PATH_MAX];
3335+
3336+ sprintf(name, "FL-%s", xt_last_directory_of_path(db->db_main_path));
3337+ xt_remove_dir_char(name);
3338+ db->db_fl_thread = xt_create_daemon(self, name);
3339+ xt_set_thread_data(db->db_fl_thread, db, xres_fl_free_thread);
3340+ xt_run_thread(self, db->db_fl_thread, xres_fl_run_thread);
3341+}
3342+
3343+xtPublic void xt_stop_flusher(XTThreadPtr self, XTDatabaseHPtr db)
3344+{
3345+ XTThreadPtr thr_fl;
3346+
3347+ if (db->db_fl_thread) {
3348+ xt_lock_mutex(self, &db->db_fl_lock);
3349+ pushr_(xt_unlock_mutex, &db->db_fl_lock);
3350+
3351+ /* This pointer is safe as long as you have the transaction lock. */
3352+ if ((thr_fl = db->db_fl_thread)) {
3353+ xtThreadID tid = thr_fl->t_id;
3354+
3355+ /* Make sure the thread quits when woken up. */
3356+ xt_terminate_thread(self, thr_fl);
3357+
3358+ freer_(); // xt_unlock_mutex(&db->db_cp_lock)
3359+
3360+ xt_wait_for_thread(tid, FALSE);
3361+ db->db_fl_thread = NULL;
3362+ }
3363+ else
3364+ freer_(); // xt_unlock_mutex(&db->db_cp_lock)
3365+ }
3366+}
3367+
3368
3369=== modified file 'storage/pbxt/src/restart_xt.h'
3370--- storage/pbxt/src/restart_xt.h 2009-11-24 10:55:06 +0000
3371+++ storage/pbxt/src/restart_xt.h 2010-05-07 08:52:27 +0000
3372@@ -92,6 +92,7 @@
3373 } XTXactRestartRec, *XTXactRestartPtr;
3374
3375 typedef struct XTCheckPointState {
3376+ xtBool cp_inited; /* TRUE if structure was inited */
3377 xt_mutex_type cp_state_lock; /* Lock and the entire checkpoint state. */
3378 xtBool cp_running; /* TRUE if a checkpoint is running. */
3379 xtLogID cp_log_id;
3380@@ -136,6 +137,9 @@
3381 void xt_xres_start_database_recovery(XTThreadPtr self);
3382 void xt_xres_terminate_recovery(XTThreadPtr self);
3383
3384+void xt_start_flusher(struct XTThread *self, struct XTDatabase *db);
3385+void xt_stop_flusher(struct XTThread *self, struct XTDatabase *db);
3386+
3387 #define XT_RECOVER_PENDING 0
3388 #define XT_RECOVER_DONE 1
3389 #define XT_RECOVER_SWEPT 2
3390
3391=== modified file 'storage/pbxt/src/strutil_xt.cc'
3392--- storage/pbxt/src/strutil_xt.cc 2009-12-21 13:13:15 +0000
3393+++ storage/pbxt/src/strutil_xt.cc 2010-05-07 08:52:27 +0000
3394@@ -380,7 +380,7 @@
3395 /* Version number must also be set in configure.in! */
3396 xtPublic c_char *xt_get_version(void)
3397 {
3398- return "1.0.09g RC";
3399+ return "1.0.11 Pre-GA";
3400 }
3401
3402 /* Copy and URL decode! */
3403
3404=== modified file 'storage/pbxt/src/tabcache_xt.cc'
3405--- storage/pbxt/src/tabcache_xt.cc 2009-11-27 15:37:02 +0000
3406+++ storage/pbxt/src/tabcache_xt.cc 2010-05-07 08:52:27 +0000
3407@@ -46,8 +46,10 @@
3408 xtPublic void xt_tc_set_cache_size(size_t cache_size)
3409 {
3410 xt_tab_cache.tcm_cache_size = cache_size;
3411- xt_tab_cache.tcm_low_level = cache_size / 4 * 3; // Current 75%
3412- xt_tab_cache.tcm_high_level = cache_size / 100 * 95; // Current 95%
3413+ /* Multiplying by this number can overflow a 4 byte value! */
3414+ xt_tab_cache.tcm_low_level = (size_t) ((xtWord8) cache_size * (xtWord8) 70 / (xtWord8) 100); // Current 70%
3415+ xt_tab_cache.tcm_high_level = (size_t) ((xtWord8) cache_size * 95 / (xtWord8) 100); // Current 95%
3416+ xt_tab_cache.tcm_mid_level = (size_t) ((xtWord8) cache_size * 85 / (xtWord8) 100); // Current 85%
3417 }
3418
3419 /*
3420@@ -84,25 +86,30 @@
3421
3422 xtPublic void xt_tc_exit(XTThreadPtr self)
3423 {
3424+ XTTabCacheSegPtr seg;
3425+
3426 for (u_int i=0; i<XT_TC_SEGMENT_COUNT; i++) {
3427- if (xt_tab_cache.tcm_segment[i].tcs_hash_table) {
3428- if (xt_tab_cache.tcm_segment[i].tcs_cache_in_use) {
3429- XTTabCachePagePtr page, tmp_page;
3430+ seg = &xt_tab_cache.tcm_segment[i];
3431+ if (seg->tcs_hash_table) {
3432+ XTTabCachePagePtr page, tmp_page;
3433
3434- for (size_t j=0; j<xt_tab_cache.tcm_hash_size; j++) {
3435- page = xt_tab_cache.tcm_segment[i].tcs_hash_table[j];
3436- while (page) {
3437- tmp_page = page;
3438- page = page->tcp_next;
3439- xt_free(self, tmp_page);
3440- }
3441+ for (size_t j=0; j<xt_tab_cache.tcm_hash_size; j++) {
3442+ page = seg->tcs_hash_table[j];
3443+ while (page) {
3444+ tmp_page = page;
3445+ page = page->tcp_next;
3446+ ASSERT_NS(seg->tcs_cache_in_use >= offsetof(XTTabCachePageRec, tcp_data) + tmp_page->tcp_data_size);
3447+ seg->tcs_cache_in_use -= (offsetof(XTTabCachePageRec, tcp_data) + tmp_page->tcp_data_size);
3448+ ASSERT_NS(seg->tcs_cache_in_use == 0 || seg->tcs_cache_in_use >= 25000);
3449+ xt_free(self, tmp_page);
3450 }
3451 }
3452
3453- xt_free(self, xt_tab_cache.tcm_segment[i].tcs_hash_table);
3454- xt_tab_cache.tcm_segment[i].tcs_hash_table = NULL;
3455- TAB_CAC_FREE_LOCK(self, &xt_tab_cache.tcm_segment[i].tcs_lock);
3456+ xt_free(self, seg->tcs_hash_table);
3457+ seg->tcs_hash_table = NULL;
3458+ TAB_CAC_FREE_LOCK(self, &seg->tcs_lock);
3459 }
3460+ ASSERT_NS(seg->tcs_cache_in_use == 0);
3461 }
3462
3463 xt_free_mutex(&xt_tab_cache.tcm_lock);
3464@@ -554,24 +561,24 @@
3465 }
3466 page = page->tcp_next;
3467 }
3468+
3469+ size_t page_size = offsetof(XTTabCachePageRec, tcp_data) + this->tci_page_size;
3470+
3471 TAB_CAC_UNLOCK(&seg->tcs_lock, thread->t_id);
3472
3473 /* Page not found, allocate a new page: */
3474- size_t page_size = offsetof(XTTabCachePageRec, tcp_data) + this->tci_page_size;
3475 if (!(new_page = (XTTabCachePagePtr) xt_malloc_ns(page_size)))
3476 return FAILED;
3477- /* Increment cache used. */
3478- seg->tcs_cache_in_use += page_size;
3479
3480 /* Check the level of the cache: */
3481 size_t cache_used = 0;
3482 for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)
3483 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
3484
3485- if (cache_used > dcg->tcm_cache_high)
3486+ if (cache_used + page_size > dcg->tcm_cache_high)
3487 dcg->tcm_cache_high = cache_used;
3488
3489- if (cache_used > dcg->tcm_cache_size) {
3490+ if (cache_used + page_size > dcg->tcm_cache_size) {
3491 XTThreadPtr self;
3492 time_t now;
3493
3494@@ -638,7 +645,7 @@
3495 for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)
3496 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
3497
3498- if (cache_used <= dcg->tcm_high_level)
3499+ if (cache_used + page_size <= dcg->tcm_high_level)
3500 break;
3501 /*
3502 * If there is too little cache we can get stuck here.
3503@@ -663,7 +670,7 @@
3504 while (time(NULL) < now + 5);
3505 xt_unlock_mutex_ns(&dcg->tcm_freeer_lock);
3506 }
3507- else if (cache_used > dcg->tcm_high_level) {
3508+ else if (cache_used + page_size > dcg->tcm_high_level) {
3509 /* Wake up the freeer because the cache level,
3510 * is higher than the high level.
3511 */
3512@@ -693,6 +700,9 @@
3513 }
3514
3515 #ifdef XT_MEMSET_UNUSED_SPACE
3516+ else
3517+ red_size = 0;
3518+
3519 /* Removing this is an optimization. It should not be required
3520 * to clear the unused space in the page.
3521 */
3522@@ -727,6 +737,15 @@
3523 page->tcp_next = seg->tcs_hash_table[hash_idx];
3524 seg->tcs_hash_table[hash_idx] = page;
3525
3526+ /* GOTCHA! This increment was done just after the malloc!
3527+ * So it was not protected by the segment lock!
3528+ * The result was that this count was no longer reliable,
3529+ * This resulted in the amount of cache being used becoming less, and\
3530+ * less, because increments were lost over time!
3531+ */
3532+ /* Increment cache used. */
3533+ seg->tcs_cache_in_use += page_size;
3534+
3535 done_ok:
3536 *ret_seg = seg;
3537 *ret_page = page;
3538@@ -761,7 +780,7 @@
3539 * some will be missing, so the writer will not
3540 * be able to contniue.
3541 */
3542- return xt_xlog_log_data(thread, sizeof(XTactNoOpEntryDRec), (XTXactLogBufferDPtr) &ent_rec, FALSE);
3543+ return xt_xlog_log_data(thread, sizeof(XTactNoOpEntryDRec), (XTXactLogBufferDPtr) &ent_rec, XT_XLOG_NO_WRITE_NO_FLUSH);
3544 }
3545
3546 #ifdef XT_NOT_INLINE
3547@@ -828,13 +847,23 @@
3548 /*
3549 * Used by the writer to wake the freeer.
3550 */
3551-xtPublic void xt_wr_wake_freeer(XTThreadPtr self)
3552+xtPublic void xt_wr_wake_freeer(XTThreadPtr self, XTDatabaseHPtr db)
3553 {
3554+ /* BUG FIX: Was using tcm_freeer_cond.
3555+ * This is incorrect. When the freeer waits for the
3556+ * writter, it uses the writer's condition!
3557+ */
3558+ xt_lock_mutex_ns(&db->db_wr_lock);
3559+ if (!xt_broadcast_cond_ns(&db->db_wr_cond))
3560+ xt_log_and_clear_exception_ns();
3561+ xt_unlock_mutex_ns(&db->db_wr_lock);
3562+/*
3563 xt_lock_mutex(self, &xt_tab_cache.tcm_freeer_lock);
3564 pushr_(xt_unlock_mutex, &xt_tab_cache.tcm_freeer_lock);
3565 if (!xt_broadcast_cond_ns(&xt_tab_cache.tcm_freeer_cond))
3566 xt_log_and_clear_exception_ns();
3567 freer_(); // xt_unlock_mutex(&xt_tab_cache.tcm_freeer_lock)
3568+*/
3569 }
3570
3571 /* Wait for a transaction to quit: */
3572@@ -1070,7 +1099,9 @@
3573
3574 /* Free the page: */
3575 size_t freed_space = offsetof(XTTabCachePageRec, tcp_data) + page->tcp_data_size;
3576+ ASSERT_NS(seg->tcs_cache_in_use >= freed_space);
3577 seg->tcs_cache_in_use -= freed_space;
3578+ ASSERT_NS(seg->tcs_cache_in_use == 0 || seg->tcs_cache_in_use >= 25000);
3579 xt_free_ns(page);
3580
3581 TAB_CAC_UNLOCK(&seg->tcs_lock, self->t_id);
3582@@ -1083,6 +1114,7 @@
3583 {
3584 register XTTabCacheMemPtr dcg = &xt_tab_cache;
3585 TCResourceRec tc = { 0 };
3586+ int i;
3587
3588 xt_set_low_priority(self);
3589 dcg->tcm_freeer_busy = TRUE;
3590@@ -1095,14 +1127,20 @@
3591 while (!self->t_quit) {
3592 /* Total up the cache memory used: */
3593 cache_used = 0;
3594- for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)
3595+ for (i=0; i<XT_TC_SEGMENT_COUNT; i++)
3596 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
3597- if (cache_used > dcg->tcm_cache_high) {
3598+
3599+ if (cache_used > dcg->tcm_cache_high)
3600 dcg->tcm_cache_high = cache_used;
3601- }
3602
3603 /* Check if the cache usage is over 95%: */
3604- if (self->t_quit || cache_used < dcg->tcm_high_level)
3605+ if (self->t_quit)
3606+ break;
3607+
3608+ /* If threads are waiting then we are more aggressive about freeing
3609+ * cache.
3610+ */
3611+ if (cache_used < (dcg->tcm_threads_waiting ? dcg->tcm_mid_level : dcg->tcm_high_level))
3612 break;
3613
3614 /* Reduce cache to the 75% level: */
3615@@ -1137,7 +1175,23 @@
3616 */
3617 xt_db_approximate_time = time(NULL);
3618 dcg->tcm_freeer_busy = FALSE;
3619- tabc_fr_wait_for_cache(self, 500);
3620+ /* No idea, why, but I am getting an uneccesarry pause here.
3621+ * I run DBT2 with low record cache.
3622+ *
3623+ * Every now and then there is a pause where the freeer is here,
3624+ * and all user threads are waiting for the freeer.
3625+ *
3626+ * So adding the tcm_threads_waiting condition.
3627+ */
3628+ if (dcg->tcm_threads_waiting) {
3629+ cache_used = 0;
3630+ for (i=0; i<XT_TC_SEGMENT_COUNT; i++)
3631+ cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
3632+ if (cache_used < dcg->tcm_mid_level)
3633+ tabc_fr_wait_for_cache(self, 500);
3634+ }
3635+ else
3636+ tabc_fr_wait_for_cache(self, 500);
3637 //tabc_fr_wait_for_cache(self, 30*1000);
3638 dcg->tcm_freeer_busy = TRUE;
3639 xt_db_approximate_time = time(NULL);
3640@@ -1174,7 +1228,7 @@
3641 count = 2*60;
3642 #endif
3643 while (!self->t_quit && count > 0) {
3644- xt_db_approximate_time = xt_trace_clock();
3645+ xt_db_approximate_time = time(NULL);
3646 sleep(1);
3647 count--;
3648 }
3649
3650=== modified file 'storage/pbxt/src/tabcache_xt.h'
3651--- storage/pbxt/src/tabcache_xt.h 2009-11-24 10:55:06 +0000
3652+++ storage/pbxt/src/tabcache_xt.h 2010-05-07 08:52:27 +0000
3653@@ -29,6 +29,7 @@
3654 struct XTTable;
3655 struct XTOpenTable;
3656 struct XTTabCache;
3657+struct XTDatabase;
3658
3659 #include "thread_xt.h"
3660 #include "filesys_xt.h"
3661@@ -226,6 +227,7 @@
3662 size_t tcm_cache_high; /* The high water level of cache allocation. */
3663 size_t tcm_low_level; /* This is the level to which the freeer will free, once it starts working. */
3664 size_t tcm_high_level; /* This is the level at which the freeer will start to work (to avoid waiting)! */
3665+ size_t tcm_mid_level; /* At this level the freeer will not sleep if there are threads waiting. */
3666
3667 /* The free'er thread: */
3668 struct XTThread *tcm_freeer_thread; /* The freeer thread . */
3669@@ -283,6 +285,6 @@
3670 void xt_quit_freeer(XTThreadPtr self);
3671 void xt_stop_freeer(XTThreadPtr self);
3672 void xt_start_freeer(XTThreadPtr self);
3673-void xt_wr_wake_freeer(XTThreadPtr self);
3674+void xt_wr_wake_freeer(XTThreadPtr self, struct XTDatabase *db);
3675
3676 #endif
3677
3678=== modified file 'storage/pbxt/src/table_xt.cc'
3679--- storage/pbxt/src/table_xt.cc 2009-12-22 10:33:20 +0000
3680+++ storage/pbxt/src/table_xt.cc 2010-05-07 08:52:27 +0000
3681@@ -61,6 +61,11 @@
3682
3683 #define CHECK_TABLE_STATS
3684
3685+/* The problem is that this can take a long time
3686+ * if the table is very large!
3687+ */
3688+//#define CHECK_TABLE_READ_DATA_LOG
3689+
3690 #ifdef TRACE_TABLE_IDS
3691 //#define PRINTF xt_ftracef
3692 #define PRINTF xt_trace
3693@@ -217,6 +222,7 @@
3694 xt_spinlock_free(self, &tab->tab_ainc_lock);
3695 xt_free_mutex(&tab->tab_rec_flush_lock);
3696 xt_free_mutex(&tab->tab_ind_flush_lock);
3697+ xt_free_mutex(&tab->tab_ind_stat_lock);
3698 xt_free_mutex(&tab->tab_dic_field_lock);
3699 xt_free_mutex(&tab->tab_row_lock);
3700 xt_free_mutex(&tab->tab_ind_lock);
3701@@ -487,6 +493,12 @@
3702 }
3703 freer_(); // xt_describe_tables_exit(&desc)
3704
3705+ /*
3706+ * When we open all tables, we ignore problems with foreign keys.
3707+ * This must be done or we will not be able to load tables that
3708+ * were created with foreign key checks off.
3709+ */
3710+ self->st_ignore_fkeys = 1;
3711 /*
3712 * The purpose of this code is to ensure that all tables are opened and cached,
3713 * which is actually only required if tables have foreign key references.
3714@@ -499,14 +511,30 @@
3715 *
3716 * Cannot open tables in the loop above because db->db_table_by_id which is built
3717 * above is used by xt_use_table_no_lock()
3718+ *
3719+ * {TABLE-STATS}
3720+ * NOTE: The code also lead to the statistics failing to work because
3721+ * the tables were already open when the handler was opened.
3722+ * Previously we only caclulated statistics when a handler was opened
3723+ * and the underlying table was also opened.
3724 */
3725 xt_enum_tables_init(&edx);
3726 while ((te_ptr = xt_enum_tables_next(self, db, &edx))) {
3727 xt_strcpy(PATH_MAX, pbuf, te_ptr->te_tab_path->tp_path);
3728 xt_add_dir_char(PATH_MAX, pbuf);
3729 xt_strcat(PATH_MAX, pbuf, te_ptr->te_tab_name);
3730- xt_heap_release(self, xt_use_table_no_lock(self, db, (XTPathStrPtr)pbuf, FALSE, FALSE, NULL, NULL));
3731+ try_(a) {
3732+ xt_heap_release(self, xt_use_table_no_lock(self, db, (XTPathStrPtr) pbuf, FALSE, FALSE, NULL));
3733+ }
3734+ catch_(a) {
3735+ /* ignore errors, because we are just loading all
3736+ * the tables that we can...
3737+ */
3738+ xt_log_and_clear_warning(self);
3739+ }
3740+ cont_(a);
3741 }
3742+ self->st_ignore_fkeys = 0;
3743
3744 popr_(); // Discard xt_tab_exit_db(db)
3745 exit_();
3746@@ -651,7 +679,7 @@
3747 xt_strcpy(PATH_MAX, path, te_ptr->te_tab_path->tp_path);
3748 xt_add_dir_char(PATH_MAX, path);
3749 xt_strcat(PATH_MAX, path, te_ptr->te_tab_name);
3750- tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);
3751+ tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE);
3752 tab_check_table(self, tab);
3753 xt_heap_release(self, tab);
3754 tab = NULL;
3755@@ -1009,6 +1037,7 @@
3756 /* a helper function to remove table from the open tables hash on exception
3757 * used in tab_new_handle() below
3758 */
3759+ #ifdef NO_LONGER_REQ
3760 static void xt_del_from_db_tables_ht(XTThreadPtr self, XTTableHPtr tab)
3761 {
3762 XTTableEntryPtr te_ptr;
3763@@ -1024,6 +1053,7 @@
3764 if ((te_ptr = (XTTableEntryPtr) xt_sl_find(self, db->db_table_by_id, &tab_id)))
3765 te_ptr->te_table = NULL;
3766 }
3767+#endif
3768
3769 /*
3770 * Create a new table handle (i.e. open a table).
3771@@ -1067,6 +1097,7 @@
3772 xt_spinlock_init_with_autoname(self, &tab->tab_ainc_lock);
3773 xt_init_mutex_with_autoname(self, &tab->tab_rec_flush_lock);
3774 xt_init_mutex_with_autoname(self, &tab->tab_ind_flush_lock);
3775+ xt_init_mutex_with_autoname(self, &tab->tab_ind_stat_lock);
3776 xt_init_mutex_with_autoname(self, &tab->tab_dic_field_lock);
3777 xt_init_mutex_with_autoname(self, &tab->tab_row_lock);
3778 xt_init_mutex_with_autoname(self, &tab->tab_ind_lock);
3779@@ -1148,9 +1179,16 @@
3780 * will work if we have cyclic foreign key references.
3781 */
3782 if (tab->tab_dic.dic_table) {
3783- pushr_(xt_del_from_db_tables_ht, tab);
3784- tab->tab_dic.dic_table->attachReferences(self, db);
3785- popr_();
3786+ try_(a) {
3787+ tab->tab_dic.dic_table->attachReferences(self, db);
3788+ }
3789+ catch_(a) {
3790+ /* Errors are thrown when: set foreign_key_checks = 1 */
3791+ /* Undo everything done above: */
3792+ xt_ht_del(self, db->db_tables, tab->tab_name);
3793+ xt_throw(self);
3794+ }
3795+ cont_(a);
3796 }
3797
3798 *r_tab = tab;
3799@@ -1162,7 +1200,7 @@
3800 * Get a reference to a table in the current database. The table reference is valid,
3801 * as long as the thread is using the database!!!
3802 */
3803-xtPublic XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, XTDatabaseHPtr db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic, xtBool *opened)
3804+xtPublic XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, XTDatabaseHPtr db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic)
3805 {
3806 XTTableHPtr tab;
3807
3808@@ -1181,9 +1219,6 @@
3809
3810 if (tab_new_handle(self, &tab, db, tab_id, name, FALSE, dic) == XT_TAB_NO_DICTIONARY)
3811 xt_throw_taberr(XT_CONTEXT, XT_ERR_NO_DICTIONARY, name);
3812-
3813- if (opened)
3814- *opened = TRUE;
3815 }
3816
3817 if (tab)
3818@@ -1297,7 +1332,7 @@
3819 XTSortedListInfoRec li_undo;
3820
3821 #ifdef TRACE_CREATE_TABLES
3822- fprintf(stderr, "CREATE %s\n", name->ps_path);
3823+ printf("CREATE %s\n", name->ps_path);
3824 #endif
3825 enter_();
3826 if (strlen(xt_last_name_of_path(name->ps_path)) > XT_TABLE_NAME_SIZE-1)
3827@@ -1528,7 +1563,7 @@
3828 * as well.
3829 */
3830 if (!old_tab_id) {
3831- tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL, NULL);
3832+ tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL);
3833 xt_heap_release(self, tab);
3834 }
3835 }
3836@@ -1556,7 +1591,7 @@
3837 /* Same purpose as above {LOAD-FOR-FKS} (although this should work,
3838 * beacuse this is a TRUNCATE TABLE.
3839 */
3840- tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL, NULL);
3841+ tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL);
3842 xt_heap_release(self, tab);
3843 }
3844 catch_(b) {
3845@@ -1599,7 +1634,7 @@
3846 /* this code is not needed anymore as we open tables referred by FKs as necessary during checks
3847 xt_ht_lock(self, db->db_tables);
3848 pushr_(xt_ht_unlock, db->db_tables);
3849- tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL, NULL);
3850+ tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL);
3851 freer_(); // xt_ht_unlock(db->db_tables)
3852 xt_heap_release(self, tab);
3853 * CHANGED see {LOAD-FOR-FKS} above.
3854@@ -1619,7 +1654,7 @@
3855 enter_();
3856
3857 #ifdef TRACE_CREATE_TABLES
3858- fprintf(stderr, "DROP %s\n", tab_name->ps_path);
3859+ printf("DROP %s\n", tab_name->ps_path);
3860 #endif
3861
3862 table_pool = tab_lock_table(self, tab_name, FALSE, TRUE, TRUE, &tab);
3863@@ -1775,9 +1810,10 @@
3864 size_t rec_size;
3865 size_t row_size;
3866 u_llong ext_data_len = 0;
3867+ u_llong ext_rec_count = 0;
3868
3869 #if defined(DUMP_CHECK_TABLE) || defined(CHECK_TABLE_STATS)
3870- fprintf(stderr, "\nCHECK TABLE: %s\n", tab->tab_name->ps_path);
3871+ printf("\nCHECK TABLE: %s\n", tab->tab_name->ps_path);
3872 #endif
3873
3874 xt_lock_mutex(self, &tab->tab_db->db_co_ext_lock);
3875@@ -1787,38 +1823,38 @@
3876 pushr_(xt_unlock_mutex, &tab->tab_rec_lock);
3877
3878 #ifdef CHECK_TABLE_STATS
3879- fprintf(stderr, "Record buffer size = %lu\n", (u_long) tab->tab_dic.dic_mysql_buf_size);
3880- fprintf(stderr, "Fixed length rec. len. = %lu\n", (u_long) tab->tab_dic.dic_mysql_rec_size);
3881- fprintf(stderr, "Handle data record size = %lu\n", (u_long) tab->tab_dic.dic_rec_size);
3882- fprintf(stderr, "Min/max header size = %d/%d\n", (int) offsetof(XTTabRecFix, rf_data), tab->tab_dic.dic_rec_fixed ? (int) offsetof(XTTabRecFix, rf_data) : (int) offsetof(XTTabRecExtDRec, re_data));
3883- fprintf(stderr, "Min/avg/max record size = %llu/%llu/%llu\n", (u_llong) tab->tab_dic.dic_min_row_size, (u_llong) tab->tab_dic.dic_ave_row_size, (u_llong) tab->tab_dic.dic_max_row_size);
3884+ printf("Record buffer size = %lu\n", (u_long) tab->tab_dic.dic_mysql_buf_size);
3885+ printf("Fixed length rec. len. = %lu\n", (u_long) tab->tab_dic.dic_mysql_rec_size);
3886+ printf("Handle data record size = %lu\n", (u_long) tab->tab_dic.dic_rec_size);
3887+ printf("Min/max header size = %d/%d\n", (int) offsetof(XTTabRecFix, rf_data), tab->tab_dic.dic_rec_fixed ? (int) offsetof(XTTabRecFix, rf_data) : (int) offsetof(XTTabRecExtDRec, re_data));
3888+ printf("Min/avg/max record size = %llu/%llu/%llu\n", (u_llong) tab->tab_dic.dic_min_row_size, (u_llong) tab->tab_dic.dic_ave_row_size, (u_llong) tab->tab_dic.dic_max_row_size);
3889 if (tab->tab_dic.dic_def_ave_row_size)
3890- fprintf(stderr, "Avg row len set for tab = %lu\n", (u_long) tab->tab_dic.dic_def_ave_row_size);
3891+ printf("Avg row len set for tab = %lu\n", (u_long) tab->tab_dic.dic_def_ave_row_size);
3892 else
3893- fprintf(stderr, "Avg row len set for tab = not specified\n");
3894- fprintf(stderr, "Rows fixed length = %s\n", tab->tab_dic.dic_rec_fixed ? "YES" : "NO");
3895+ printf("Avg row len set for tab = not specified\n");
3896+ printf("Rows fixed length = %s\n", tab->tab_dic.dic_rec_fixed ? "YES" : "NO");
3897 if (tab->tab_dic.dic_tab_flags & XT_TAB_FLAGS_TEMP_TAB)
3898- fprintf(stderr, "Table type = TEMP\n");
3899+ printf("Table type = TEMP\n");
3900 if (tab->tab_dic.dic_def_ave_row_size)
3901- fprintf(stderr, "Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH_SPEC);
3902+ printf("Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH_SPEC);
3903 else
3904- fprintf(stderr, "Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH);
3905- fprintf(stderr, "Minimum variable size = %lu\n", (u_long) XT_TAB_MIN_VAR_REC_LENGTH);
3906- fprintf(stderr, "Minimum auto-increment = %llu\n", (u_llong) tab->tab_dic.dic_min_auto_inc);
3907- fprintf(stderr, "Number of columns = %lu\n", (u_long) tab->tab_dic.dic_no_of_cols);
3908- fprintf(stderr, "Number of fixed columns = %lu\n", (u_long) tab->tab_dic.dic_fix_col_count);
3909- fprintf(stderr, "Columns req. for index = %lu\n", (u_long) tab->tab_dic.dic_ind_cols_req);
3910+ printf("Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH);
3911+ printf("Minimum variable size = %lu\n", (u_long) XT_TAB_MIN_VAR_REC_LENGTH);
3912+ printf("Minimum auto-increment = %llu\n", (u_llong) tab->tab_dic.dic_min_auto_inc);
3913+ printf("Number of columns = %lu\n", (u_long) tab->tab_dic.dic_no_of_cols);
3914+ printf("Number of fixed columns = %lu\n", (u_long) tab->tab_dic.dic_fix_col_count);
3915+ printf("Columns req. for index = %lu\n", (u_long) tab->tab_dic.dic_ind_cols_req);
3916 if (tab->tab_dic.dic_ind_rec_len)
3917- fprintf(stderr, "Rec len req. for index = %llu\n", (u_llong) tab->tab_dic.dic_ind_rec_len);
3918- fprintf(stderr, "Columns req. for blobs = %lu\n", (u_long) tab->tab_dic.dic_blob_cols_req);
3919- fprintf(stderr, "Number of blob columns = %lu\n", (u_long) tab->tab_dic.dic_blob_count);
3920- fprintf(stderr, "Number of indices = %lu\n", (u_long) tab->tab_dic.dic_key_count);
3921+ printf("Rec len req. for index = %llu\n", (u_llong) tab->tab_dic.dic_ind_rec_len);
3922+ printf("Columns req. for blobs = %lu\n", (u_long) tab->tab_dic.dic_blob_cols_req);
3923+ printf("Number of blob columns = %lu\n", (u_long) tab->tab_dic.dic_blob_count);
3924+ printf("Number of indices = %lu\n", (u_long) tab->tab_dic.dic_key_count);
3925 #endif
3926
3927 #ifdef DUMP_CHECK_TABLE
3928- fprintf(stderr, "Records:-\n");
3929- fprintf(stderr, "Free list: %llu (%llu)\n", (u_llong) tab->tab_rec_free_id, (u_llong) tab->tab_rec_fnum);
3930- fprintf(stderr, "EOF: %llu\n", (u_llong) tab->tab_rec_eof_id);
3931+ printf("Records:-\n");
3932+ printf("Free list: %llu (%llu)\n", (u_llong) tab->tab_rec_free_id, (u_llong) tab->tab_rec_fnum);
3933+ printf("EOF: %llu\n", (u_llong) tab->tab_rec_eof_id);
3934 #endif
3935
3936 rec_size = XT_REC_EXT_HEADER_SIZE;
3937@@ -1830,24 +1866,24 @@
3938 xt_throw(self);
3939
3940 #ifdef DUMP_CHECK_TABLE
3941- fprintf(stderr, "%-4llu ", (u_llong) rec_id);
3942+ printf("%-4llu ", (u_llong) rec_id);
3943 #endif
3944 switch (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_MASK) {
3945 case XT_TAB_STATUS_FREED:
3946 #ifdef DUMP_CHECK_TABLE
3947- fprintf(stderr, "======== ");
3948+ printf("======== ");
3949 #endif
3950 free_rec_count++;
3951 break;
3952 case XT_TAB_STATUS_DELETE:
3953 #ifdef DUMP_CHECK_TABLE
3954- fprintf(stderr, "delete ");
3955+ printf("delete ");
3956 #endif
3957 delete_rec_count++;
3958 break;
3959 case XT_TAB_STATUS_FIXED:
3960 #ifdef DUMP_CHECK_TABLE
3961- fprintf(stderr, "record-F ");
3962+ printf("record-F ");
3963 #endif
3964 alloc_rec_count++;
3965 row_size = myxt_store_row_length(ot, (char *) ot->ot_row_rbuffer + XT_REC_FIX_HEADER_SIZE);
3966@@ -1859,7 +1895,7 @@
3967 break;
3968 case XT_TAB_STATUS_VARIABLE:
3969 #ifdef DUMP_CHECK_TABLE
3970- fprintf(stderr, "record-V ");
3971+ printf("record-V ");
3972 #endif
3973 alloc_rec_count++;
3974 row_size = myxt_load_row_length(ot, tab->tab_dic.dic_rec_size, ot->ot_row_rbuffer + XT_REC_FIX_HEADER_SIZE, NULL);
3975@@ -1871,9 +1907,10 @@
3976 break;
3977 case XT_TAB_STATUS_EXT_DLOG:
3978 #ifdef DUMP_CHECK_TABLE
3979- fprintf(stderr, "record-X ");
3980+ printf("record-X ");
3981 #endif
3982 alloc_rec_count++;
3983+ ext_rec_count++;
3984 ext_data_len += XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
3985 row_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4) + ot->ot_rec_size - XT_REC_EXT_HEADER_SIZE;
3986 alloc_rec_bytes += row_size;
3987@@ -1885,9 +1922,9 @@
3988 }
3989 #ifdef DUMP_CHECK_TABLE
3990 if (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_CLEANED_BIT)
3991- fprintf(stderr, "C");
3992+ printf("C");
3993 else
3994- fprintf(stderr, " ");
3995+ printf(" ");
3996 #endif
3997 prev_rec_id = XT_GET_DISK_4(rec_buf->tr_prev_rec_id_4);
3998 xn_id = XT_GET_DISK_4(rec_buf->tr_xact_id_4);
3999@@ -1895,14 +1932,15 @@
4000 switch (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_MASK) {
4001 case XT_TAB_STATUS_FREED:
4002 #ifdef DUMP_CHECK_TABLE
4003- fprintf(stderr, " prev=%-3llu (xact=%-3llu row=%lu)\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);
4004+ printf(" prev=%-3llu (xact=%-3llu row=%lu)\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);
4005 #endif
4006 break;
4007 case XT_TAB_STATUS_EXT_DLOG:
4008 #ifdef DUMP_CHECK_TABLE
4009- fprintf(stderr, " prev=%-3llu xact=%-3llu row=%lu Xlog=%lu Xoff=%llu Xsiz=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id, (u_long) XT_GET_DISK_2(rec_buf->re_log_id_2), (u_llong) XT_GET_DISK_6(rec_buf->re_log_offs_6), (u_long) XT_GET_DISK_4(rec_buf->re_log_dat_siz_4));
4010+ printf(" prev=%-3llu xact=%-3llu row=%lu Xlog=%lu Xoff=%llu Xsiz=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id, (u_long) XT_GET_DISK_2(rec_buf->re_log_id_2), (u_llong) XT_GET_DISK_6(rec_buf->re_log_offs_6), (u_long) XT_GET_DISK_4(rec_buf->re_log_dat_siz_4));
4011 #endif
4012
4013+#ifdef CHECK_TABLE_READ_DATA_LOG
4014 log_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
4015 XT_GET_LOG_REF(log_id, log_offset, rec_buf);
4016 if (!self->st_dlog_buf.dlb_read_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data), (xtWord1 *) &ext_rec, self))
4017@@ -1919,10 +1957,11 @@
4018 xt_logf(XT_INFO, "Table %s: record %llu, extended record %lu:%llu not valid\n", tab->tab_name, (u_llong) rec_id, (u_long) log_id, (u_llong) log_offset);
4019 }
4020 }
4021+#endif
4022 break;
4023 default:
4024 #ifdef DUMP_CHECK_TABLE
4025- fprintf(stderr, " prev=%-3llu xact=%-3llu row=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);
4026+ printf(" prev=%-3llu xact=%-3llu row=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);
4027 #endif
4028 break;
4029 }
4030@@ -1930,17 +1969,19 @@
4031 }
4032
4033 #ifdef CHECK_TABLE_STATS
4034- if (!tab->tab_dic.dic_rec_fixed)
4035- fprintf(stderr, "Extendend data length = %llu\n", ext_data_len);
4036+ if (!tab->tab_dic.dic_rec_fixed) {
4037+ printf("Extended data length = %llu\n", ext_data_len);
4038+ printf("Extended record count = %llu\n", ext_rec_count);
4039+ }
4040
4041 if (alloc_rec_count) {
4042- fprintf(stderr, "Minumum comp. rec. len. = %llu\n", (u_llong) min_comp_rec_len);
4043- fprintf(stderr, "Average comp. rec. len. = %llu\n", (u_llong) ((double) alloc_rec_bytes / (double) alloc_rec_count + (double) 0.5));
4044- fprintf(stderr, "Maximum comp. rec. len. = %llu\n", (u_llong) max_comp_rec_len);
4045+ printf("Minumum comp. rec. len. = %llu\n", (u_llong) min_comp_rec_len);
4046+ printf("Average comp. rec. len. = %llu\n", (u_llong) ((double) alloc_rec_bytes / (double) alloc_rec_count + (double) 0.5));
4047+ printf("Maximum comp. rec. len. = %llu\n", (u_llong) max_comp_rec_len);
4048 }
4049- fprintf(stderr, "Free record count = %llu\n", (u_llong) free_rec_count);
4050- fprintf(stderr, "Deleted record count = %llu\n", (u_llong) delete_rec_count);
4051- fprintf(stderr, "Allocated record count = %llu\n", (u_llong) alloc_rec_count);
4052+ printf("Free record count = %llu\n", (u_llong) free_rec_count);
4053+ printf("Deleted record count = %llu\n", (u_llong) delete_rec_count);
4054+ printf("Allocated record count = %llu\n", (u_llong) alloc_rec_count);
4055 #endif
4056 if (tab->tab_rec_fnum != free_rec_count)
4057 xt_logf(XT_INFO, "Table %s: incorrect number of free blocks, %llu, should be: %llu\n", tab->tab_name, (u_llong) free_rec_count, (u_llong) tab->tab_rec_fnum);
4058@@ -1978,9 +2019,9 @@
4059 pushr_(xt_unlock_mutex, &tab->tab_row_lock);
4060
4061 #ifdef DUMP_CHECK_TABLE
4062- fprintf(stderr, "Rows:-\n");
4063- fprintf(stderr, "Free list: %llu (%llu)\n", (u_llong) tab->tab_row_free_id, (u_llong) tab->tab_row_fnum);
4064- fprintf(stderr, "EOF: %llu\n", (u_llong) tab->tab_row_eof_id);
4065+ printf("Rows:-\n");
4066+ printf("Free list: %llu (%llu)\n", (u_llong) tab->tab_row_free_id, (u_llong) tab->tab_row_fnum);
4067+ printf("EOF: %llu\n", (u_llong) tab->tab_row_eof_id);
4068 #endif
4069
4070 rec_id = 1;
4071@@ -1988,13 +2029,13 @@
4072 if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, rec_id, &ref_id, self))
4073 xt_throw(self);
4074 #ifdef DUMP_CHECK_TABLE
4075- fprintf(stderr, "%-3llu ", (u_llong) rec_id);
4076+ printf("%-3llu ", (u_llong) rec_id);
4077 #endif
4078 #ifdef DUMP_CHECK_TABLE
4079 if (ref_id == 0)
4080- fprintf(stderr, "====== 0\n");
4081+ printf("====== 0\n");
4082 else
4083- fprintf(stderr, "in use %llu\n", (u_llong) ref_id);
4084+ printf("in use %llu\n", (u_llong) ref_id);
4085 #endif
4086 rec_id++;
4087 }
4088@@ -2026,7 +2067,7 @@
4089 memset(&dic, 0, sizeof(dic));
4090
4091 #ifdef TRACE_CREATE_TABLES
4092- fprintf(stderr, "RENAME %s --> %s\n", old_name->ps_path, new_name->ps_path);
4093+ printf("RENAME %s --> %s\n", old_name->ps_path, new_name->ps_path);
4094 #endif
4095 if (strlen(xt_last_name_of_path(new_name->ps_path)) > XT_TABLE_NAME_SIZE-1)
4096 xt_throw_taberr(XT_CONTEXT, XT_ERR_NAME_TOO_LONG, new_name);
4097@@ -2100,7 +2141,7 @@
4098 popr_(); // Discard tab_free_table_path(te_new_path);
4099 popr_(); // Discard xt_free(te_new_name);
4100
4101- tab = xt_use_table_no_lock(self, db, new_name, FALSE, FALSE, &dic, NULL);
4102+ tab = xt_use_table_no_lock(self, db, new_name, FALSE, FALSE, &dic);
4103 /* All renamed tables are considered repaired! */
4104 xt_tab_table_repaired(tab);
4105 xt_heap_release(self, tab);
4106@@ -2110,14 +2151,14 @@
4107 freer_(); // xt_db_unlock_table_pool(table_pool)
4108 }
4109
4110-xtPublic XTTableHPtr xt_use_table(XTThreadPtr self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, xtBool *opened)
4111+xtPublic XTTableHPtr xt_use_table(XTThreadPtr self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok)
4112 {
4113 XTTableHPtr tab;
4114 XTDatabaseHPtr db = self->st_database;
4115
4116 xt_ht_lock(self, db->db_tables);
4117 pushr_(xt_ht_unlock, db->db_tables);
4118- tab = xt_use_table_no_lock(self, db, name, no_load, missing_ok, NULL, opened);
4119+ tab = xt_use_table_no_lock(self, db, name, no_load, missing_ok, NULL);
4120 freer_();
4121 return tab;
4122 }
4123@@ -2221,7 +2262,7 @@
4124 xt_tab_store_header(ot, &rec_head);
4125
4126 #ifdef TRACE_FLUSH
4127- fprintf(stderr, "FLUSH rec/row %d %s\n", (int) tab->tab_bytes_to_flush, tab->tab_name->ps_path);
4128+ printf("FLUSH rec/row %d %s\n", (int) tab->tab_bytes_to_flush, tab->tab_name->ps_path);
4129 fflush(stdout);
4130 #endif
4131 /* Write the table header: */
4132@@ -2276,7 +2317,7 @@
4133 xt_unlock_mutex_ns(&cp->cp_state_lock);
4134
4135 #ifdef TRACE_FLUSH
4136- fprintf(stderr, "FLUSH --end-- %s\n", tab->tab_name->ps_path);
4137+ printf("FLUSH --end-- %s\n", tab->tab_name->ps_path);
4138 fflush(stdout);
4139 #endif
4140 xt_unlock_mutex_ns(&tab->tab_rec_flush_lock);
4141@@ -2858,7 +2899,7 @@
4142 /* This is a record written by this transaction. */
4143 if (thread->st_is_update) {
4144 /* Check that it was not written by the current update statement: */
4145- if (XT_STAT_ID_MASK(thread->st_update_id) == rec_head->tr_stat_id_1) {
4146+ if (XT_STAT_ID_MASK(ot->ot_update_id) == rec_head->tr_stat_id_1) {
4147 #ifdef TRACE_VARIATIONS
4148 if (len <= 450)
4149 len += sprintf(t_buf+len, "MY UPDATE IN THIS STATEMENT T%d\n", (int) xn_id);
4150@@ -3139,7 +3180,7 @@
4151 }
4152 if (lw.lw_curr_lock != XT_NO_LOCK) {
4153 #ifdef TRACE_VARIATIONS
4154- xt_ttracef(thread, "T%d WAIT FOR LOCK(%D) T%d\n", (int) thread->st_xact_data->xd_start_xn_id, (int) lock_type, (int) xn_id);
4155+ xt_ttracef(thread, "T%d WAIT FOR LOCK(%s) T%d\n", (int) thread->st_xact_data->xd_start_xn_id, (int) lw.lw_curr_lock == XT_TEMP_LOCK ? "temp" : "perm", (int) xn_id);
4156 #endif
4157 if (!xt_xn_wait_for_xact(thread, NULL, &lw)) {
4158 #ifdef DEBUG_LOCK_QUEUE
4159@@ -3950,6 +3991,21 @@
4160 tab_restore_exception(&e);
4161 }
4162
4163+static xtBool tab_write_ext_record(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, xtTableID tab_id, xtRecordID rec_id, xtLogID log_id, xtLogOffset log_offset, XTThreadPtr thread)
4164+{
4165+ xtWord1 tmp_buffer[offsetof(XTactExtRecEntryDRec, er_data)];
4166+ xtBool ok;
4167+
4168+ memcpy(tmp_buffer, rec_info->ri_log_buf, sizeof(tmp_buffer));
4169+ rec_info->ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;
4170+ XT_SET_DISK_4(rec_info->ri_log_buf->er_data_size_4, rec_info->ri_log_data_size);
4171+ XT_SET_DISK_4(rec_info->ri_log_buf->er_tab_id_4, tab_id);
4172+ XT_SET_DISK_4(rec_info->ri_log_buf->er_rec_id_4, rec_id);
4173+ ok = thread->st_dlog_buf.dlb_append_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data) + rec_info->ri_log_data_size, (xtWord1 *) rec_info->ri_log_buf, thread);
4174+ memcpy(rec_info->ri_log_buf, tmp_buffer, sizeof(tmp_buffer));
4175+ return ok;
4176+}
4177+
4178 static xtBool tab_add_record(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, u_int status)
4179 {
4180 register XTTableHPtr tab = ot->ot_table;
4181@@ -4007,26 +4063,19 @@
4182 */
4183 read = ((rec_id - 1) % tab->tab_recs.tci_rows_per_page) != 0;
4184
4185- if (!tab->tab_recs.xt_tc_write(ot->ot_rec_file, rec_id, 0, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf, &op_seq, read, ot->ot_thread)) {
4186+ if (!tab->tab_recs.xt_tc_write(ot->ot_rec_file, rec_id, 0, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf, &op_seq, read, thread)) {
4187 xt_unlock_mutex_ns(&tab->tab_rec_lock);
4188 return FAILED;
4189 }
4190 }
4191 xt_unlock_mutex_ns(&tab->tab_rec_lock);
4192
4193- if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, next_rec_id, rec_id, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf, ot->ot_thread))
4194+ if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, next_rec_id, rec_id, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf, thread))
4195 return FAILED;
4196
4197 if (rec_info->ri_ext_rec) {
4198- /* Write the log buffer overflow: */
4199- rec_info->ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;
4200- XT_SET_DISK_4(rec_info->ri_log_buf->er_data_size_4, rec_info->ri_log_data_size);
4201- XT_SET_DISK_4(rec_info->ri_log_buf->er_tab_id_4, tab->tab_id);
4202- XT_SET_DISK_4(rec_info->ri_log_buf->er_rec_id_4, rec_id);
4203- if (!thread->st_dlog_buf.dlb_append_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data) + rec_info->ri_log_data_size, (xtWord1 *) rec_info->ri_log_buf, ot->ot_thread)) {
4204- /* Failed to write the overflow, free the record allocated above: */
4205+ if (!tab_write_ext_record(ot, rec_info, tab->tab_id, rec_id, log_id, log_offset, thread))
4206 return FAILED;
4207- }
4208 }
4209
4210 XT_DISABLED_TRACE(("new rec tx=%d val=%d\n", (int) thread->st_xact_data->xd_start_xn_id, (int) rec_id));
4211@@ -4062,8 +4111,11 @@
4212 }
4213 }
4214
4215+ /* This is not required because the extended record will be free
4216+ * later when the record is freed!
4217 if (row_ptr->tr_rec_type_1 == XT_TAB_STATUS_EXT_DLOG || row_ptr->tr_rec_type_1 == XT_TAB_STATUS_EXT_CLEAN)
4218 tab_free_ext_record_on_fail(ot, rec_id, (XTTabRecExtDPtr) row_ptr, log_err);
4219+ */
4220
4221 rec_info.ri_fix_rec_buf = (XTTabRecFixDPtr) ot->ot_row_wbuffer;
4222 rec_info.ri_rec_buf_size = offsetof(XTTabRecFixDRec, rf_data);
4223@@ -4369,7 +4421,7 @@
4224 if (!(row_id = tab_new_row(ot, tab)))
4225 goto failed_0;
4226
4227- rec_info.ri_fix_rec_buf->tr_stat_id_1 = self->st_update_id;
4228+ rec_info.ri_fix_rec_buf->tr_stat_id_1 = ot->ot_update_id;
4229 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);
4230 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, 0);
4231 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);
4232@@ -4458,7 +4510,7 @@
4233 * order to do this we'd need to read the before-image of the
4234 * record before modifying it.
4235 */
4236- if (!ot->ot_thread->t_exception.e_xt_err)
4237+ if (!thread->t_exception.e_xt_err)
4238 xt_register_xterr(XT_REG_CONTEXT, XT_ERR_NO_BEFORE_IMAGE);
4239 return FAILED;
4240 }
4241@@ -4471,7 +4523,7 @@
4242
4243 if (rec_info->ri_ext_rec) {
4244 /* Determine where the overflow will go... */
4245- if (!thread->st_dlog_buf.dlb_get_log_offset(&log_id, &log_offset, rec_info->ri_log_data_size + offsetof(XTactExtRecEntryDRec, er_data), ot->ot_thread))
4246+ if (!thread->st_dlog_buf.dlb_get_log_offset(&log_id, &log_offset, rec_info->ri_log_data_size + offsetof(XTactExtRecEntryDRec, er_data), thread))
4247 return FAILED;
4248 XT_SET_LOG_REF(rec_info->ri_ext_rec, log_id, log_offset);
4249 }
4250@@ -4481,11 +4533,7 @@
4251
4252 if (rec_info->ri_ext_rec) {
4253 /* Write the log buffer overflow: */
4254- rec_info->ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;
4255- XT_SET_DISK_4(rec_info->ri_log_buf->er_data_size_4, rec_info->ri_log_data_size);
4256- XT_SET_DISK_4(rec_info->ri_log_buf->er_tab_id_4, tab->tab_id);
4257- XT_SET_DISK_4(rec_info->ri_log_buf->er_rec_id_4, rec_id);
4258- if (!thread->st_dlog_buf.dlb_append_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data) + rec_info->ri_log_data_size, (xtWord1 *) rec_info->ri_log_buf, ot->ot_thread))
4259+ if (!tab_write_ext_record(ot, rec_info, tab->tab_id, rec_id, log_id, log_offset, thread))
4260 return FAILED;
4261 }
4262
4263@@ -4529,12 +4577,12 @@
4264
4265 if (rec_info.ri_ext_rec) {
4266 /* Determine where the overflow will go... */
4267- if (!self->st_dlog_buf.dlb_get_log_offset(&log_id, &log_offset, offsetof(XTactExtRecEntryDRec, er_data) + rec_info.ri_log_data_size, ot->ot_thread))
4268+ if (!self->st_dlog_buf.dlb_get_log_offset(&log_id, &log_offset, offsetof(XTactExtRecEntryDRec, er_data) + rec_info.ri_log_data_size, self))
4269 goto failed_0;
4270 XT_SET_LOG_REF(rec_info.ri_ext_rec, log_id, log_offset);
4271 }
4272
4273- rec_info.ri_fix_rec_buf->tr_stat_id_1 = self->st_update_id;
4274+ rec_info.ri_fix_rec_buf->tr_stat_id_1 = ot->ot_update_id;
4275 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);
4276 XT_COPY_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, prev_rec_head.tr_prev_rec_id_4);
4277 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);
4278@@ -4555,11 +4603,7 @@
4279
4280 if (rec_info.ri_ext_rec) {
4281 /* Write the log buffer overflow: */
4282- rec_info.ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;
4283- XT_SET_DISK_4(rec_info.ri_log_buf->er_data_size_4, rec_info.ri_log_data_size);
4284- XT_SET_DISK_4(rec_info.ri_log_buf->er_tab_id_4, tab->tab_id);
4285- XT_SET_DISK_4(rec_info.ri_log_buf->er_rec_id_4, rec_id);
4286- if (!self->st_dlog_buf.dlb_append_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data) + rec_info.ri_log_data_size, (xtWord1 *) rec_info.ri_log_buf, ot->ot_thread))
4287+ if (!tab_write_ext_record(ot, &rec_info, tab->tab_id, rec_id, log_id, log_offset, self))
4288 goto failed_1;
4289 }
4290
4291@@ -4678,7 +4722,7 @@
4292 if (!myxt_store_row(ot, &rec_info, (char *) after_buf))
4293 goto failed_0;
4294
4295- rec_info.ri_fix_rec_buf->tr_stat_id_1 = self->st_update_id;
4296+ rec_info.ri_fix_rec_buf->tr_stat_id_1 = ot->ot_update_id;
4297 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);
4298 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, ot->ot_curr_rec_id);
4299 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);
4300@@ -4688,7 +4732,7 @@
4301 goto failed_0;
4302
4303 /* Link the new variation into the list: */
4304- XT_TAB_ROW_WRITE_LOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);
4305+ XT_TAB_ROW_WRITE_LOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], self);
4306
4307 if (!xt_tab_get_row(ot, row_id, &curr_var_rec_id))
4308 goto failed_1;
4309@@ -4714,7 +4758,7 @@
4310 goto failed_1;
4311 XT_DISABLED_TRACE(("set upd tx=%d row=%d rec=%d\n", (int) self->st_xact_data->xd_start_xn_id, (int) row_id, (int) rec_info.ri_rec_id));
4312
4313- XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);
4314+ XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], self);
4315
4316 /* Add the index references: */
4317 for (idx_cnt=0, ind=tab->tab_dic.dic_keys; idx_cnt<tab->tab_dic.dic_key_count; idx_cnt++, ind++) {
4318@@ -4729,7 +4773,7 @@
4319 goto failed_2;
4320 }
4321
4322- ot->ot_thread->st_statistics.st_row_update++;
4323+ self->st_statistics.st_row_update++;
4324 return OK;
4325
4326 failed_2:
4327@@ -4737,7 +4781,7 @@
4328 goto failed_0;
4329
4330 failed_1:
4331- XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);
4332+ XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], self);
4333
4334 failed_0:
4335 return FAILED;
4336
4337=== modified file 'storage/pbxt/src/table_xt.h'
4338--- storage/pbxt/src/table_xt.h 2009-11-24 10:55:06 +0000
4339+++ storage/pbxt/src/table_xt.h 2010-05-07 08:52:27 +0000
4340@@ -364,6 +364,9 @@
4341 xtWord4 tab_rec_fnum; /* The count of the number of free rows on the free list. */
4342 xt_mutex_type tab_rec_lock; /* Lock for the free list. */
4343
4344+ xt_mutex_type tab_ind_stat_lock; /* Aquired when calculating index statistics. */
4345+ time_t tab_ind_stat_calc_time; /* Zero means the index stats have not be calculated, otherwize this is a time. */
4346+
4347 xt_mutex_type tab_ind_flush_lock; /* Required while the index file is being flushed. */
4348 xtLogID tab_ind_rec_log_id; /* The point before which index entries have been written. */
4349 xtLogOffset tab_ind_rec_log_offset; /* The log offset of the write point. */
4350@@ -372,7 +375,7 @@
4351 xtIndexNodeID tab_ind_free; /* The start of the free page list of the index. */
4352 XTIndFreeListPtr tab_ind_free_list; /* A cache of the free list (if exists, don't go to disk!) */
4353 xt_mutex_type tab_ind_lock; /* Lock for reading and writing the index free list. */
4354- xtWord2 tab_ind_flush_seq;
4355+ xtWord4 tab_ind_flush_seq;
4356 } XTTableHRec, *XTTableHPtr; /* Heap pointer */
4357
4358 /* Used for an in-memory list of the tables, ordered by ID. */
4359@@ -403,6 +406,8 @@
4360 size_t ot_rec_size; /* Cached from table for quick access. */
4361
4362 char ot_error_key[XT_IDENTIFIER_NAME_SIZE];
4363+ struct XTOpenTable *ot_prev_update; /* The UPDATE statement stack! {UPDATE-STACK} */
4364+ u_int ot_update_id; /* The update statement ID. */
4365 xtBool ot_for_update; /* True if reading FOR UPDATE. */
4366 xtBool ot_is_modify; /* True if UPDATE or DELETE. */
4367 xtRowID ot_temp_row_lock; /* The temporary row lock set on this table. */
4368@@ -507,11 +512,11 @@
4369 char *xt_tab_file_to_name(size_t size, char *tab_name, char *file_name);
4370
4371 void xt_create_table(struct XTThread *self, XTPathStrPtr name, XTDictionaryPtr dic);
4372-XTTableHPtr xt_use_table(struct XTThread *self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, xtBool *opened);
4373+XTTableHPtr xt_use_table(struct XTThread *self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok);
4374 void xt_sync_flush_table(struct XTThread *self, XTOpenTablePtr ot);
4375 xtBool xt_flush_record_row(XTOpenTablePtr ot, off_t *bytes_flushed, xtBool have_table_loc);
4376 void xt_flush_table(struct XTThread *self, XTOpenTablePtr ot);
4377-XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, struct XTDatabase *db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic, xtBool *opened);
4378+XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, struct XTDatabase *db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic);
4379 int xt_use_table_by_id(struct XTThread *self, XTTableHPtr *tab, struct XTDatabase *db, xtTableID tab_id);
4380 XTOpenTablePtr xt_open_table(XTTableHPtr tab);
4381 void xt_close_table(XTOpenTablePtr ot, xtBool flush, xtBool have_table_lock);
4382
4383=== modified file 'storage/pbxt/src/thread_xt.cc'
4384--- storage/pbxt/src/thread_xt.cc 2010-01-06 21:27:53 +0000
4385+++ storage/pbxt/src/thread_xt.cc 2010-05-07 08:52:27 +0000
4386@@ -96,7 +96,7 @@
4387 {
4388 int err;
4389
4390- log_file = stderr;
4391+ log_file = stdout;
4392 log_level = XT_LOG_TRACE;
4393 err = xt_p_mutex_init_with_autoname(&log_mutex, NULL);
4394 if (err) {
4395@@ -413,7 +413,8 @@
4396 vsnprintf(e->e_err_msg, XT_ERR_MSG_SIZE, fmt, ap);
4397
4398 /* Make the first character of the message upper case: */
4399- if (isalpha(e->e_err_msg[0]) && islower(e->e_err_msg[0]))
4400+ /* This did not work for foreign languages! */
4401+ if (e->e_err_msg[0] >= 'a' && e->e_err_msg[0] <= 'z')
4402 e->e_err_msg[0] = (char) toupper(e->e_err_msg[0]);
4403
4404 if (func && *func && *func != '-')
4405@@ -793,11 +794,9 @@
4406
4407 xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);
4408 xt_strcat(sizeof(buffer), buffer, ".");
4409- xt_strcpy(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
4410- xt_strcat(sizeof(buffer), buffer, ".");
4411- xt_strcat(sizeof(buffer), buffer, item2);
4412+ xt_strcat(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
4413
4414- xt_register_ixterr(func, file, line, xt_err, buffer);
4415+ xt_register_i2xterr(func, file, line, xt_err, buffer, item2);
4416 }
4417
4418 xtPublic void xt_register_taberr(c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item)
4419@@ -806,7 +805,7 @@
4420
4421 xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);
4422 xt_strcat(sizeof(buffer), buffer, ".");
4423- xt_strcpy(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
4424+ xt_strcat(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
4425
4426 xt_register_ixterr(func, file, line, xt_err, buffer);
4427 }
4428@@ -1013,7 +1012,7 @@
4429
4430 typedef void *(*ThreadMainFunc)(XTThreadPtr self);
4431
4432-extern "C" void *thr_main_pbxt(void *data)
4433+extern "C" void *xt_thread_main(void *data)
4434 {
4435 ThreadDataPtr td = (ThreadDataPtr) data;
4436 XTThreadPtr self = td->td_thr;
4437@@ -1168,6 +1167,14 @@
4438 /* Align the number of threads: */
4439 xt_thr_maximum_threads = xt_align_size(max_threads, XT_XS_LOCK_ALIGN);
4440
4441+#ifdef XT_TRACK_CONNECTIONS
4442+ if (xt_thr_maximum_threads > XT_TRACK_MAX_CONNS) {
4443+ xt_log_error(XT_NS_CONTEXT, XT_LOG_FATAL, XT_ERR_TOO_MANY_THREADS, 0,
4444+ "XT_TRACK_CONNECTIONS is enabled and xt_thr_maximum_threads > XT_TRACK_MAX_CONNS");
4445+ goto failed;
4446+ }
4447+#endif
4448+
4449 #ifdef HANDLE_SIGNALS
4450 if (!thr_setup_signals())
4451 return NULL;
4452@@ -1503,10 +1510,10 @@
4453 pthread_attr_t attr = { 0, 0, 0 };
4454
4455 attr.priority = THREAD_PRIORITY_NORMAL;
4456- err = pthread_create(&child_thread, &attr, thr_main_pbxt, &data);
4457+ err = pthread_create(&child_thread, &attr, xt_thread_main, &data);
4458 }
4459 #else
4460- err = pthread_create(&child_thread, NULL, thr_main_pbxt, &data);
4461+ err = pthread_create(&child_thread, NULL, xt_thread_main, &data);
4462 #endif
4463 if (err) {
4464 xt_free_thread(child);
4465
4466=== modified file 'storage/pbxt/src/thread_xt.h'
4467--- storage/pbxt/src/thread_xt.h 2010-01-06 21:27:53 +0000
4468+++ storage/pbxt/src/thread_xt.h 2010-05-07 08:52:27 +0000
4469@@ -132,6 +132,7 @@
4470 struct XTXactLog;
4471 struct XTXactData;
4472 struct XTDatabase;
4473+struct XTOpenTable;
4474
4475 typedef void (*XTThreadFreeFunc)(struct XTThread *self, void *data);
4476
4477@@ -307,8 +308,7 @@
4478 xtThreadID *st_thread_list;
4479
4480 /* Used to prevent a record from being updated twice in one statement. */
4481- xtBool st_is_update; /* TRUE if this is an UPDATE statement. */
4482- u_int st_update_id; /* The update statement ID. */
4483+ struct XTOpenTable *st_is_update; /* TRUE if this is an UPDATE statement. {UPDATE-STACK} */
4484
4485 XTRowLockListRec st_lock_list; /* The thread row lock list (drop locks on transaction end). */
4486 XTStatisticsRec st_statistics; /* Accumulated statistics for this thread. */
4487@@ -536,7 +536,10 @@
4488 * Function prototypes
4489 */
4490
4491-extern "C" void *thr_main_pbxt(void *data);
4492+/* OpenSolaris has thr_main in /usr/include/thread.h (name conflict)
4493+ * Thanks for the tip Monty!
4494+ */
4495+extern "C" void *xt_thread_main(void *data);
4496
4497 void xt_get_now(char *buffer, size_t len);
4498 xtBool xt_init_logging(void);
4499
4500=== modified file 'storage/pbxt/src/trace_xt.cc'
4501--- storage/pbxt/src/trace_xt.cc 2009-12-22 10:33:20 +0000
4502+++ storage/pbxt/src/trace_xt.cc 2010-05-07 08:52:27 +0000
4503@@ -36,6 +36,7 @@
4504 #ifdef DEBUG
4505 //#define PRINT_TRACE
4506 //#define RESET_AFTER_DUMP
4507+//#define DUMP_TO_STDOUT
4508 #endif
4509
4510 static xtBool trace_initialized = FALSE;
4511@@ -109,10 +110,10 @@
4512 xt_lock_mutex_ns(&trace_mutex);
4513 if (trace_log_end > trace_log_offset+1) {
4514 trace_log_buffer[trace_log_end] = 0;
4515- fprintf(stderr, "%s", trace_log_buffer + trace_log_offset + 1);
4516+ printf("%s", trace_log_buffer + trace_log_offset + 1);
4517 }
4518 trace_log_buffer[trace_log_offset] = 0;
4519- fprintf(stderr, "%s", trace_log_buffer);
4520+ printf("%s", trace_log_buffer);
4521 trace_log_offset = 0;
4522 trace_log_end = 0;
4523 xt_unlock_mutex_ns(&trace_mutex);
4524@@ -121,9 +122,18 @@
4525
4526 xtPublic void xt_dump_trace(void)
4527 {
4528- FILE *fp;
4529+ if (trace_log_offset) {
4530+#ifdef DUMP_TO_STDOUT
4531+ if (trace_log_end > trace_log_offset+1) {
4532+ trace_log_buffer[trace_log_end] = 0;
4533+ printf("%s", trace_log_buffer + trace_log_offset + 1);
4534+ }
4535+ trace_log_buffer[trace_log_offset] = 0;
4536+ printf("%s", trace_log_buffer);
4537+ printf("\n");
4538+#else
4539+ FILE *fp;
4540
4541- if (trace_log_offset) {
4542 fp = fopen("pbxt.log", "w");
4543
4544 xt_lock_mutex_ns(&trace_mutex);
4545@@ -136,6 +146,7 @@
4546 fprintf(fp, "%s", trace_log_buffer);
4547 fclose(fp);
4548 }
4549+#endif
4550
4551 #ifdef RESET_AFTER_DUMP
4552 trace_log_offset = 0;
4553@@ -379,9 +390,9 @@
4554 ptr = conn_info;
4555 for (int i=0; i<XT_TRACK_MAX_CONNS; i++) {
4556 if (ptr->ci_curr_xact_id || ptr->ci_prev_xact_id) {
4557- fprintf(stderr, "%3d curr=%d prev=%d prev-time=%ld\n", (int) ptr->cu_t_id, (int) ptr->ci_curr_xact_id, (int) ptr->ci_prev_xact_id, (long) ptr->ci_prev_xact_time);
4558+ printf("%3d curr=%d prev=%d prev-time=%ld\n", (int) ptr->cu_t_id, (int) ptr->ci_curr_xact_id, (int) ptr->ci_prev_xact_id, (long) ptr->ci_prev_xact_time);
4559 if (i+1<XT_TRACK_MAX_CONNS) {
4560- fprintf(stderr, " diff=%d\n", (int) (ptr+1)->ci_curr_xact_id - (int) ptr->ci_curr_xact_id);
4561+ printf(" diff=%d\n", (int) (ptr+1)->ci_curr_xact_id - (int) ptr->ci_curr_xact_id);
4562 }
4563 }
4564 ptr++;
4565
4566=== modified file 'storage/pbxt/src/trace_xt.h'
4567--- storage/pbxt/src/trace_xt.h 2009-08-17 11:12:36 +0000
4568+++ storage/pbxt/src/trace_xt.h 2010-05-07 08:52:27 +0000
4569@@ -51,7 +51,9 @@
4570 * CONNECTION TRACKING
4571 */
4572
4573+#ifdef DEBUG
4574 #define XT_TRACK_CONNECTIONS
4575+#endif
4576
4577 #ifdef XT_TRACK_CONNECTIONS
4578 #define XT_TRACK_MAX_CONNS 500
4579
4580=== modified file 'storage/pbxt/src/xaction_xt.cc'
4581--- storage/pbxt/src/xaction_xt.cc 2009-11-24 10:55:06 +0000
4582+++ storage/pbxt/src/xaction_xt.cc 2010-05-07 08:52:27 +0000
4583@@ -1326,7 +1326,7 @@
4584 }
4585
4586 /* Write and flush the transaction log: */
4587- if (!xt_xlog_log_data(thread, sizeof(XTXactEndEntryDRec), (XTXactLogBufferDPtr) &entry, TRUE)) {
4588+ if (!xt_xlog_log_data(thread, sizeof(XTXactEndEntryDRec), (XTXactLogBufferDPtr) &entry, xt_db_flush_log_at_trx_commit)) {
4589 ok = FALSE;
4590 status = XT_LOG_ENT_ABORT;
4591 /* Make sure this is done, if we failed to log
4592@@ -1440,16 +1440,23 @@
4593 /* Don't get too far ahead of the sweeper! */
4594 if (writer) {
4595 #ifdef XT_WAIT_FOR_CLEANUP
4596- xtXactID wait_xn_id;
4597-
4598- /* This is the transaction that was committed 3 transactions ago: */
4599- wait_xn_id = thread->st_prev_xact[thread->st_last_xact];
4600- thread->st_prev_xact[thread->st_last_xact] = xn_id;
4601- /* This works because XT_MAX_XACT_BEHIND == 2! */
4602- ASSERT_NS((thread->st_last_xact + 1) % XT_MAX_XACT_BEHIND == (thread->st_last_xact ^ 1));
4603- thread->st_last_xact ^= 1;
4604- while (xt_xn_is_before(db->db_xn_to_clean_id, wait_xn_id) && (db->db_sw_faster & XT_SW_TOO_FAR_BEHIND)) {
4605- xt_critical_wait();
4606+ if (db->db_sw_faster & XT_SW_TOO_FAR_BEHIND) {
4607+ /* Set a maximum wait time (1/100s) */
4608+ xtWord8 then = xt_trace_clock() + (xtWord8) 100000;
4609+ xtXactID wait_xn_id;
4610+
4611+ /* This is the transaction that was committed 3 transactions ago: */
4612+ wait_xn_id = thread->st_prev_xact[thread->st_last_xact];
4613+ thread->st_prev_xact[thread->st_last_xact] = xn_id;
4614+ /* This works because XT_MAX_XACT_BEHIND == 2! */
4615+ ASSERT_NS((thread->st_last_xact + 1) % XT_MAX_XACT_BEHIND == (thread->st_last_xact ^ 1));
4616+ thread->st_last_xact ^= 1;
4617+
4618+ while (xt_xn_is_before(db->db_xn_to_clean_id, wait_xn_id) && (db->db_sw_faster & XT_SW_TOO_FAR_BEHIND)) {
4619+ if (xt_trace_clock() >= then)
4620+ break;
4621+ xt_critical_wait();
4622+ }
4623 }
4624 #else
4625 if ((db->db_sw_faster & XT_SW_TOO_FAR_BEHIND) != 0) {
4626@@ -1486,7 +1493,7 @@
4627 entry.xt_status_1 = XT_LOG_ENT_NEW_TAB;
4628 entry.xt_checksum_1 = XT_CHECKSUM_1(tab_id);
4629 XT_SET_DISK_4(entry.xt_tab_id_4, tab_id);
4630- return xt_xlog_log_data(self, sizeof(XTXactNewTabEntryDRec), (XTXactLogBufferDPtr) &entry, TRUE);
4631+ return xt_xlog_log_data(self, sizeof(XTXactNewTabEntryDRec), (XTXactLogBufferDPtr) &entry, XT_XLOG_WRITE_AND_FLUSH);
4632 }
4633
4634 xtPublic int xt_xn_status(XTOpenTablePtr ot, xtXactID xn_id, xtRecordID XT_UNUSED(rec_id))
4635@@ -2266,6 +2273,7 @@
4636 xt_log_and_clear_exception(self);
4637 break;
4638 }
4639+
4640 prev_rec_id = next_rec_id;
4641 next_rec_id = XT_GET_DISK_4(prev_rec_head.tr_prev_rec_id_4);
4642 }
4643@@ -2461,7 +2469,7 @@
4644 cu.xc_checksum_1 = XT_CHECKSUM_1(XT_CHECKSUM4_XACT(xact->xd_start_xn_id));
4645 XT_SET_DISK_4(cu.xc_xact_id_4, xact->xd_start_xn_id);
4646
4647- if (!xt_xlog_log_data(self, sizeof(XTXactCleanupEntryDRec), (XTXactLogBufferDPtr) &cu, FALSE))
4648+ if (!xt_xlog_log_data(self, sizeof(XTXactCleanupEntryDRec), (XTXactLogBufferDPtr) &cu, XT_XLOG_NO_WRITE_NO_FLUSH))
4649 return FAILED;
4650
4651 ss->ss_flush_pending = TRUE;
4652@@ -2656,7 +2664,9 @@
4653 * we flush the log.
4654 */
4655 if (now >= idle_start + 2) {
4656- if (!xt_xlog_flush_log(db, self))
4657+ /* Don't do this if flusher is active! */
4658+ if (!db->db_fl_thread &&
4659+ !xt_xlog_flush_log(db, self))
4660 xt_throw(self);
4661 ss->ss_flush_pending = FALSE;
4662 }
4663
4664=== modified file 'storage/pbxt/src/xaction_xt.h'
4665--- storage/pbxt/src/xaction_xt.h 2009-11-24 10:55:06 +0000
4666+++ storage/pbxt/src/xaction_xt.h 2010-05-07 08:52:27 +0000
4667@@ -153,14 +153,14 @@
4668 #define XT_XACT_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
4669 #define XT_XACT_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
4670 #define XT_XACT_READ_LOCK(i, s) xt_spinxslock_slock(i)
4671-#define XT_XACT_WRITE_LOCK(i, s) xt_spinxslock_xlock(i, (s)->t_id)
4672+#define XT_XACT_WRITE_LOCK(i, s) xt_spinxslock_xlock(i, FALSE, (s)->t_id)
4673 #define XT_XACT_UNLOCK(i, s, b) xt_spinxslock_unlock(i, b)
4674 #else
4675 #define XT_XACT_LOCK_TYPE XTSkewRWLockRec
4676 #define XT_XACT_INIT_LOCK(s, i) xt_skewrwlock_init_with_autoname(s, i)
4677 #define XT_XACT_FREE_LOCK(s, i) xt_skewrwlock_free(s, i)
4678 #define XT_XACT_READ_LOCK(i, s) xt_skewrwlock_slock(i)
4679-#define XT_XACT_WRITE_LOCK(i, s) xt_skewrwlock_xlock(i, (s)->t_id)
4680+#define XT_XACT_WRITE_LOCK(i, s) xt_skewrwlock_xlock(i, FALSE, (s)->t_id)
4681 #define XT_XACT_UNLOCK(i, s, b) xt_skewrwlock_unlock(i, b)
4682 #endif
4683
4684
4685=== modified file 'storage/pbxt/src/xactlog_xt.cc'
4686--- storage/pbxt/src/xactlog_xt.cc 2009-11-24 10:55:06 +0000
4687+++ storage/pbxt/src/xactlog_xt.cc 2010-05-07 08:52:27 +0000
4688@@ -719,14 +719,14 @@
4689 }
4690 }
4691
4692-#define WR_NO_SPACE 1
4693-#define WR_FLUSH 2
4694+#define WR_NO_SPACE 1 /* Write because there is no space, or some other reason */
4695+#define WR_FLUSH 2 /* Normal commit, write and flush */
4696
4697 xtBool XTDatabaseLog::xlog_flush(XTThreadPtr thread)
4698 {
4699 if (!xlog_flush_pending())
4700 return OK;
4701- return xlog_append(thread, 0, NULL, 0, NULL, TRUE, NULL, NULL);
4702+ return xlog_append(thread, 0, NULL, 0, NULL, XT_XLOG_WRITE_AND_FLUSH, NULL, NULL);
4703 }
4704
4705 xtBool XTDatabaseLog::xlog_flush_pending()
4706@@ -754,7 +754,7 @@
4707 * This function returns the log ID and offset of
4708 * the data write position.
4709 */
4710-xtBool XTDatabaseLog::xlog_append(XTThreadPtr thread, size_t size1, xtWord1 *data1, size_t size2, xtWord1 *data2, xtBool commit, xtLogID *log_id, xtLogOffset *log_offset)
4711+xtBool XTDatabaseLog::xlog_append(XTThreadPtr thread, size_t size1, xtWord1 *data1, size_t size2, xtWord1 *data2, int flush_log_at_trx_commit, xtLogID *log_id, xtLogOffset *log_offset)
4712 {
4713 int write_reason = 0;
4714 xtLogID req_flush_log_id;
4715@@ -763,19 +763,20 @@
4716 xtWord8 flush_time;
4717 xtWord2 sum;
4718
4719+ /* The first size value must be set, of the second is set! */
4720+ ASSERT_NS(size1 || !size2);
4721+
4722 if (!size1) {
4723 /* Just flush the buffer... */
4724 xt_lck_slock(&xl_buffer_lock);
4725- write_reason = WR_FLUSH;
4726+ write_reason = flush_log_at_trx_commit == XT_XLOG_WRITE_AND_FLUSH ? WR_FLUSH : WR_NO_SPACE;
4727 req_flush_log_id = xl_append_log_id;
4728 req_flush_log_offset = xl_append_log_offset + xl_append_buf_pos;
4729 xt_spinlock_unlock(&xl_buffer_lock);
4730 goto write_log_to_file;
4731 }
4732- else {
4733- req_flush_log_id = 0;
4734- req_flush_log_offset = 0;
4735- }
4736+ req_flush_log_id = 0;
4737+ req_flush_log_offset = 0;
4738
4739 /*
4740 * This is a dirty read, which will send us to the
4741@@ -866,11 +867,17 @@
4742 return OK;
4743 }
4744 }
4745- else {
4746+ else if (size1) {
4747 /* It may be that there is now space in the append buffer: */
4748 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers)
4749 goto copy_to_log_buffer;
4750 }
4751+ else {
4752+ /* We are just writing the buffer! */
4753+ ASSERT_NS(write_reason == WR_NO_SPACE);
4754+ if (xt_comp_log_pos(req_flush_log_id, req_flush_log_offset, xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : xl_write_buf_pos_start)) <= 0)
4755+ return OK;
4756+ }
4757
4758 if (xt_trace_clock() >= then) {
4759 xt_lock_mutex_ns(&xl_write_lock);
4760@@ -922,12 +929,18 @@
4761 ASSERT_NS(xt_comp_log_pos(xl_write_log_id, xl_write_log_offset, xl_append_log_id, xl_append_log_offset) <= 0);
4762 return OK;
4763 }
4764- goto write_log_to_file;
4765- }
4766-
4767- /* It may be that there is now space in the append buffer: */
4768- if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers)
4769- goto copy_to_log_buffer;
4770+ }
4771+ else if (size1) {
4772+ /* It may be that there is now space in the append buffer: */
4773+ if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers)
4774+ goto copy_to_log_buffer;
4775+ }
4776+ else {
4777+ /* We are just writing the buffer! */
4778+ ASSERT_NS(write_reason == WR_NO_SPACE);
4779+ if (xt_comp_log_pos(req_flush_log_id, req_flush_log_offset, xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : xl_write_buf_pos_start)) <= 0)
4780+ return OK;
4781+ }
4782
4783 goto write_log_to_file;
4784 }
4785@@ -952,7 +965,7 @@
4786 return OK;
4787 }
4788 /* Not flushed, but what about written? */
4789- if (xt_comp_log_pos(req_flush_log_id, req_flush_log_offset, xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : 0)) <= 0) {
4790+ if (xt_comp_log_pos(req_flush_log_id, req_flush_log_offset, xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : xl_write_buf_pos_start)) <= 0) {
4791 /* The write position is after or equal to the required flush
4792 * position. This means that all we have to do is flush
4793 * to satisfy the writers condition.
4794@@ -960,7 +973,7 @@
4795 xtBool ok = TRUE;
4796
4797 if (xl_log_id != xl_write_log_id)
4798- ok = xlog_open_log(xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : 0), thread);
4799+ ok = xlog_open_log(xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : xl_write_buf_pos_start), thread);
4800
4801 if (ok) {
4802 if (xl_db->db_co_busy) {
4803@@ -979,7 +992,7 @@
4804
4805 xt_lock_mutex_ns(&xl_db->db_wr_lock);
4806 xl_flush_log_id = xl_write_log_id;
4807- xl_flush_log_offset = xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : 0);
4808+ xl_flush_log_offset = xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : xl_write_buf_pos_start);
4809 /*
4810 * We have written data to the log, wake the writer to commit
4811 * the data to the database.
4812@@ -1000,8 +1013,11 @@
4813 return ok;
4814 }
4815 }
4816- else {
4817- /* If there is space in the buffer, then we can go on
4818+ else if (size1) {
4819+ /* If the amounf of data to be written is 0, then we are just required
4820+ * to write the transaction buffer.
4821+ *
4822+ * If there is space in the buffer, then we can go on
4823 * to copy our data into the buffer:
4824 */
4825 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers) {
4826@@ -1016,6 +1032,21 @@
4827 goto copy_to_log_buffer;
4828 }
4829 }
4830+ else {
4831+ /* We are just writing the buffer! */
4832+ ASSERT_NS(write_reason == WR_NO_SPACE);
4833+ if (xt_comp_log_pos(req_flush_log_id, req_flush_log_offset, xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : xl_write_buf_pos_start)) <= 0) {
4834+#ifdef XT_XLOG_WAIT_SPINS
4835+ xt_writing = 0;
4836+ if (xt_waiting)
4837+ xt_cond_wakeall(&xl_write_cond);
4838+#else
4839+ xt_writing = FALSE;
4840+ xt_cond_wakeall(&xl_write_cond);
4841+#endif
4842+ return OK;
4843+ }
4844+ }
4845
4846 rewrite:
4847 /* If the current write buffer has been written, then
4848@@ -1109,7 +1140,8 @@
4849 part_size = 512 - part_size;
4850 xl_write_buffer[xl_write_buf_pos] = XT_LOG_ENT_END_OF_LOG;
4851 #ifdef HAVE_valgrind
4852- memset(xl_write_buffer + xl_write_buf_pos + 1, 0x66, part_size);
4853+ if (part_size > 1)
4854+ memset(xl_write_buffer + xl_write_buf_pos + 1, 0x66, part_size - 1);
4855 #endif
4856 if (!xt_pwrite_file(xl_log_file, xl_write_log_offset, xl_write_buf_pos+part_size, xl_write_buffer, &thread->st_statistics.st_xlog, thread))
4857 goto write_failed;
4858@@ -1197,9 +1229,13 @@
4859 xt_writing = FALSE;
4860 xt_cond_wakeall(&xl_write_cond);
4861 #endif
4862+
4863+ if (size1 == 0)
4864+ return OK;
4865 }
4866
4867 copy_to_log_buffer:
4868+ ASSERT_NS(size1);
4869 xt_spinlock_lock(&xl_buffer_lock);
4870 /* Now we have to check again. The check above was a dirty read!
4871 */
4872@@ -1291,11 +1327,14 @@
4873 if (log_offset)
4874 *log_offset = xl_append_log_offset + xl_append_buf_pos;
4875 xl_append_buf_pos += size1 + size2;
4876- if (commit) {
4877- write_reason = WR_FLUSH;
4878+ if (flush_log_at_trx_commit != XT_XLOG_NO_WRITE_NO_FLUSH) {
4879+ write_reason = flush_log_at_trx_commit == XT_XLOG_WRITE_AND_FLUSH ? WR_FLUSH : WR_NO_SPACE;
4880 req_flush_log_id = xl_append_log_id;
4881 req_flush_log_offset = xl_append_log_offset + xl_append_buf_pos;
4882 xt_spinlock_unlock(&xl_buffer_lock);
4883+ /* We have written the data already! */
4884+ size1 = 0;
4885+ size2 = 0;
4886 goto write_log_to_file;
4887 }
4888
4889@@ -1485,9 +1524,9 @@
4890 return db->db_xlog.xlog_flush(thread);
4891 }
4892
4893-xtPublic xtBool xt_xlog_log_data(XTThreadPtr thread, size_t size, XTXactLogBufferDPtr log_entry, xtBool commit)
4894+xtPublic xtBool xt_xlog_log_data(XTThreadPtr thread, size_t size, XTXactLogBufferDPtr log_entry, int flush_log_at_trx_commit)
4895 {
4896- return thread->st_database->db_xlog.xlog_append(thread, size, (xtWord1 *) log_entry, 0, NULL, commit, NULL, NULL);
4897+ return thread->st_database->db_xlog.xlog_append(thread, size, (xtWord1 *) log_entry, 0, NULL, flush_log_at_trx_commit, NULL, NULL);
4898 }
4899
4900 /* Allocate a record from the free list. */
4901@@ -1498,7 +1537,7 @@
4902 xtWord4 sum = 0;
4903 int check_size = 1;
4904 XTXactDataPtr xact = NULL;
4905- xtBool commit = FALSE;
4906+ int flush_log_at_trx_commit = XT_XLOG_NO_WRITE_NO_FLUSH;
4907
4908 switch (status) {
4909 case XT_LOG_ENT_REC_MODIFIED:
4910@@ -1613,7 +1652,7 @@
4911 XT_SET_DISK_4(log_entry.xp.xp_xact_id_4, op_seq);
4912 log_entry.xp.xp_xa_len_1 = (xtWord1) size;
4913 len = offsetof(XTXactPrepareEntryDRec, xp_xa_data);
4914- commit = TRUE;
4915+ flush_log_at_trx_commit = xt_db_flush_log_at_trx_commit;
4916 break;
4917 default:
4918 ASSERT_NS(FALSE);
4919@@ -1652,9 +1691,9 @@
4920 xt_print_log_record(0, 0, &log_entry);
4921 #endif
4922 if (xact)
4923- return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, commit, &xact->xd_begin_log, &xact->xd_begin_offset);
4924+ return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, flush_log_at_trx_commit, &xact->xd_begin_log, &xact->xd_begin_offset);
4925
4926- return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, commit, NULL, NULL);
4927+ return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, flush_log_at_trx_commit, NULL, NULL);
4928 }
4929
4930 /*
4931
4932=== modified file 'storage/pbxt/src/xactlog_xt.h'
4933--- storage/pbxt/src/xactlog_xt.h 2009-11-24 10:55:06 +0000
4934+++ storage/pbxt/src/xactlog_xt.h 2010-05-07 08:52:27 +0000
4935@@ -75,6 +75,10 @@
4936 #define XT_DELETE_LOGS 1
4937 #define XT_KEEP_LOGS 2
4938
4939+#define XT_XLOG_NO_WRITE_NO_FLUSH 0
4940+#define XT_XLOG_WRITE_AND_FLUSH 1
4941+#define XT_XLOG_WRITE_AND_NO_FLUSH 2
4942+
4943 /* LOG CACHE ---------------------------------------------------- */
4944
4945 typedef struct XTXLogBlock {
4946@@ -443,7 +447,7 @@
4947 void xlog_name(size_t size, char *path, xtLogID log_id);
4948 int xlog_delete_log(xtLogID del_log_id, struct XTThread *thread);
4949
4950- xtBool xlog_append(struct XTThread *thread, size_t size1, xtWord1 *data1, size_t size2, xtWord1 *data2, xtBool commit, xtLogID *log_id, xtLogOffset *log_offset);
4951+ xtBool xlog_append(struct XTThread *thread, size_t size1, xtWord1 *data1, size_t size2, xtWord1 *data2, int flush_log_at_trx_commit, xtLogID *log_id, xtLogOffset *log_offset);
4952 xtBool xlog_flush(struct XTThread *thread);
4953 xtBool xlog_flush_pending();
4954
4955@@ -464,7 +468,7 @@
4956 } XTDatabaseLogRec, *XTDatabaseLogPtr;
4957
4958 xtBool xt_xlog_flush_log(struct XTDatabase *db, struct XTThread *thread);
4959-xtBool xt_xlog_log_data(struct XTThread *thread, size_t len, XTXactLogBufferDPtr log_entry, xtBool commit);
4960+xtBool xt_xlog_log_data(struct XTThread *thread, size_t len, XTXactLogBufferDPtr log_entry, int flush_log_at_trx_commit);
4961 xtBool xt_xlog_modify_table(xtTableID tab_id, u_int status, xtOpSeqNo op_seq, xtRecordID free_list, xtRecordID address, size_t size, xtWord1 *data, struct XTThread *thread);
4962
4963 void xt_xlog_init(struct XTThread *self, size_t cache_size);
4964
4965=== modified file 'storage/pbxt/src/xt_defs.h'
4966--- storage/pbxt/src/xt_defs.h 2009-11-24 10:55:06 +0000
4967+++ storage/pbxt/src/xt_defs.h 2010-05-07 08:52:27 +0000
4968@@ -221,7 +221,7 @@
4969 */
4970
4971 #ifdef DEBUG
4972-//#define XT_USE_GLOBAL_DEBUG_SIZES
4973+#define XT_USE_GLOBAL_DEBUG_SIZES
4974 #endif
4975
4976 /*
4977@@ -392,6 +392,11 @@
4978 //#define XT_NO_ATOMICS
4979 #endif
4980
4981+/* When pbxt_flush_log_at_trx_commit != 1, the transaction log is flushed
4982+ * at regular intervals. Set the interval here.
4983+ */
4984+#define XT_XLOG_FLUSH_FREQ 1000
4985+
4986 /* ----------------------------------------------------------------------
4987 * GLOBAL CONSTANTS
4988 */
4989@@ -457,21 +462,24 @@
4990 #ifdef XT_USE_GLOBAL_DEBUG_SIZES
4991
4992 //#undef XT_ROW_RWLOCKS
4993-//#define XT_ROW_RWLOCKS 2
4994+//#define XT_ROW_RWLOCKS 2
4995
4996 //#undef XT_TAB_MIN_VAR_REC_LENGTH
4997-//#define XT_TAB_MIN_VAR_REC_LENGTH 20
4998+//#define XT_TAB_MIN_VAR_REC_LENGTH 20
4999
5000 //#undef XT_ROW_LOCK_COUNT
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches