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
=== modified file 'mysql-test/suite/pbxt/r/func_str.result'
--- mysql-test/suite/pbxt/r/func_str.result 2009-08-17 15:57:58 +0000
+++ mysql-test/suite/pbxt/r/func_str.result 2010-05-07 08:52:27 +0000
@@ -1362,7 +1362,7 @@
1362WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00');1362WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00');
1363id select_type table type possible_keys key key_len ref rows filtered Extra1363id select_type table type possible_keys key key_len ref rows filtered Extra
13641 SIMPLE t2 const PRIMARY PRIMARY 12 const 1 100.00 Using index13641 SIMPLE t2 const PRIMARY PRIMARY 12 const 1 100.00 Using index
13651 SIMPLE t1 ref code code 13 const 1 100.00 Using where; Using index13651 SIMPLE t1 ref code code 13 const 3 100.00 Using where; Using index
1366Warnings:1366Warnings:
1367Note 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))1367Note 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))
1368DROP TABLE t1,t2;1368DROP TABLE t1,t2;
13691369
=== modified file 'mysql-test/suite/pbxt/r/group_min_max.result'
--- mysql-test/suite/pbxt/r/group_min_max.result 2009-11-24 10:19:08 +0000
+++ mysql-test/suite/pbxt/r/group_min_max.result 2010-05-07 08:52:27 +0000
@@ -287,52 +287,52 @@
287b m422 p422287b m422 p422
288explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;288explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
289id select_type table type possible_keys key key_len ref rows Extra289id select_type table type possible_keys key key_len ref rows Extra
2901 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where2901 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
291explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;291explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
292id select_type table type possible_keys key key_len ref rows Extra292id select_type table type possible_keys key key_len ref rows Extra
2931 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where2931 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
294explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;294explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
295id select_type table type possible_keys key key_len ref rows Extra295id select_type table type possible_keys key key_len ref rows Extra
2961 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 2 Using where; Using index for group-by2961 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
297explain select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;297explain select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
298id select_type table type possible_keys key key_len ref rows Extra298id select_type table type possible_keys key key_len ref rows Extra
2991 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 2 Using where; Using index for group-by2991 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
300explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;300explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
301id select_type table type possible_keys key key_len ref rows Extra301id select_type table type possible_keys key key_len ref rows Extra
3021 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 129 Using where; Using index for group-by3021 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
303explain select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;303explain select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
304id select_type table type possible_keys key key_len ref rows Extra304id select_type table type possible_keys key key_len ref rows Extra
3051 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 3 Using where; Using index3051 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 96 Using where; Using index
306explain select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;306explain select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
307id select_type table type possible_keys key key_len ref rows Extra307id select_type table type possible_keys key key_len ref rows Extra
3081 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 3 Using where; Using index3081 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 96 Using where; Using index
309explain 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;309explain 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;
310id select_type table type possible_keys key key_len ref rows Extra310id select_type table type possible_keys key key_len ref rows Extra
3111 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 Using where; Using index3111 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 Using where; Using index
312explain 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;312explain 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;
313id select_type table type possible_keys key key_len ref rows Extra313id select_type table type possible_keys key key_len ref rows Extra
3141 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 Using where; Using index3141 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 Using where; Using index
315explain select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;315explain select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
316id select_type table type possible_keys key key_len ref rows Extra316id select_type table type possible_keys key key_len ref rows Extra
3171 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where3171 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
318explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;318explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
319id select_type table type possible_keys key key_len ref rows Extra319id select_type table type possible_keys key key_len ref rows Extra
3201 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 3 Using where; Using index3201 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 96 Using where; Using index
321explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;321explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
322id select_type table type possible_keys key key_len ref rows Extra322id select_type table type possible_keys key key_len ref rows Extra
3231 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where3231 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
324explain select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b;324explain select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b;
325id select_type table type possible_keys key key_len ref rows Extra325id select_type table type possible_keys key key_len ref rows Extra
3261 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where3261 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
327explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;327explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
328id select_type table type possible_keys key key_len ref rows Extra328id select_type table type possible_keys key key_len ref rows Extra
3291 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where3291 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
330explain select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;330explain select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
331id select_type table type possible_keys key key_len ref rows Extra331id select_type table type possible_keys key key_len ref rows Extra
3321 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by3321 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
333explain select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;333explain select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
334id select_type table type possible_keys key key_len ref rows Extra334id select_type table type possible_keys key key_len ref rows Extra
3351 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by3351 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
336explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;336explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
337id select_type table type possible_keys key key_len ref rows Extra337id select_type table type possible_keys key key_len ref rows Extra
3381 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by3381 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
@@ -350,7 +350,7 @@
3501 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL # Using where; Using index3501 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL # Using where; Using index
351explain select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;351explain select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
352id select_type table type possible_keys key key_len ref rows Extra352id select_type table type possible_keys key key_len ref rows Extra
3531 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where3531 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
354explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;354explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
355id select_type table type possible_keys key key_len ref rows Extra355id select_type table type possible_keys key key_len ref rows Extra
3561 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index3561 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
@@ -1377,13 +1377,13 @@
13771 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by13771 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by
1378explain 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;1378explain 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;
1379id select_type table type possible_keys key key_len ref rows Extra1379id select_type table type possible_keys key key_len ref rows Extra
13801 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 2 Using where; Using index for group-by13801 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
1381explain 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;1381explain 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;
1382id select_type table type possible_keys key key_len ref rows Extra1382id select_type table type possible_keys key key_len ref rows Extra
13831 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 2 Using where; Using index for group-by13831 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 64 Using where; Using index
1384explain select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;1384explain select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
1385id select_type table type possible_keys key key_len ref rows Extra1385id select_type table type possible_keys key key_len ref rows Extra
13861 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where13861 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
1387explain 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;1387explain 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;
1388id select_type table type possible_keys key key_len ref rows Extra1388id select_type table type possible_keys key key_len ref rows Extra
13891 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using where; Using index for group-by13891 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using where; Using index for group-by
@@ -1398,13 +1398,13 @@
13981 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by13981 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
1399explain 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;1399explain 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;
1400id select_type table type possible_keys key key_len ref rows Extra1400id select_type table type possible_keys key key_len ref rows Extra
14011 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by14011 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
1402explain 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;1402explain 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;
1403id select_type table type possible_keys key key_len ref rows Extra1403id select_type table type possible_keys key key_len ref rows Extra
14041 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by14041 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
1405explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;1405explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
1406id select_type table type possible_keys key key_len ref rows Extra1406id select_type table type possible_keys key key_len ref rows Extra
14071 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where14071 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 65 NULL # Using where; Using index
1408select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;1408select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
1409a1 a2 b min(c) max(c)1409a1 a2 b min(c) max(c)
1410a a b e112 h1121410a a b e112 h112
@@ -1500,7 +1500,7 @@
15001 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by15001 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by
1501explain select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;1501explain select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
1502id select_type table type possible_keys key key_len ref rows Extra1502id select_type table type possible_keys key key_len ref rows Extra
15031 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1 Using where15031 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 Using where; Using index
1504explain select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;1504explain select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
1505id select_type table type possible_keys key key_len ref rows Extra1505id select_type table type possible_keys key key_len ref rows Extra
15061 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where; Using index for group-by15061 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where; Using index for group-by
@@ -1512,7 +1512,7 @@
15121 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by15121 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
1513explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;1513explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
1514id select_type table type possible_keys key key_len ref rows Extra1514id select_type table type possible_keys key key_len ref rows Extra
15151 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where15151 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where; Using index
1516select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;1516select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
1517a1 a2 b1517a1 a2 b
1518a a b1518a a b
@@ -1565,7 +1565,7 @@
1565Note 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'))1565Note 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'))
1566explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');1566explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
1567id select_type table type possible_keys key key_len ref rows Extra1567id select_type table type possible_keys key key_len ref rows Extra
15681 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1 Using where15681 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 Using where; Using index
1569explain select distinct b from t1 where (a2 >= 'b') and (b = 'a');1569explain select distinct b from t1 where (a2 >= 'b') and (b = 'a');
1570id select_type table type possible_keys key key_len ref rows Extra1570id select_type table type possible_keys key key_len ref rows Extra
15711 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index15711 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
@@ -1582,7 +1582,7 @@
1582Note 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'))1582Note 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'))
1583explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');1583explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
1584id select_type table type possible_keys key key_len ref rows Extra1584id select_type table type possible_keys key key_len ref rows Extra
15851 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where15851 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where; Using index
1586explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');1586explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');
1587id select_type table type possible_keys key key_len ref rows Extra1587id select_type table type possible_keys key key_len ref rows Extra
15881 SIMPLE t2 index NULL idx_t2_2 146 NULL 164 Using where; Using index15881 SIMPLE t2 index NULL idx_t2_2 146 NULL 164 Using where; Using index
@@ -1711,7 +1711,7 @@
17111 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by17111 SIMPLE t1 range NULL idx_t1_1 163 NULL 129 Using where; Using index for group-by
1712explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;1712explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
1713id select_type table type possible_keys key key_len ref rows Extra1713id select_type table type possible_keys key key_len ref rows Extra
17141 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1 Using where17141 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 Using where; Using index
1715explain select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;1715explain select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
1716id select_type table type possible_keys key key_len ref rows Extra1716id select_type table type possible_keys key key_len ref rows Extra
17171 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using where; Using index for group-by; Using temporary; Using filesort17171 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using where; Using index for group-by; Using temporary; Using filesort
@@ -1726,7 +1726,7 @@
17261 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by17261 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
1727explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;1727explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
1728id select_type table type possible_keys key key_len ref rows Extra1728id select_type table type possible_keys key key_len ref rows Extra
17291 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where17291 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 65 NULL # Using where; Using index
1730explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;1730explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
1731id select_type table type possible_keys key key_len ref rows Extra1731id select_type table type possible_keys key key_len ref rows Extra
17321 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort17321 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort
@@ -1806,7 +1806,7 @@
18061 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index18061 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
1807explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');1807explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
1808id select_type table type possible_keys key key_len ref rows filtered Extra1808id select_type table type possible_keys key key_len ref rows filtered Extra
18091 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_0 65 NULL 1 100.00 Using where18091 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
1810Warnings:1810Warnings:
1811Note 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'))1811Note 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'))
1812explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');1812explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
@@ -1814,7 +1814,7 @@
18141 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index18141 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
1815explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');1815explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
1816id select_type table type possible_keys key key_len ref rows filtered Extra1816id select_type table type possible_keys key key_len ref rows filtered Extra
18171 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_0 65 NULL 1 100.00 Using where18171 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
1818Warnings:1818Warnings:
1819Note 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'))1819Note 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'))
1820select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');1820select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
@@ -1834,16 +1834,16 @@
18341041834104
1835explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;1835explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
1836id select_type table type possible_keys key key_len ref rows Extra1836id select_type table type possible_keys key key_len ref rows Extra
18371 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where18371 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
1838explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;1838explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
1839id select_type table type possible_keys key key_len ref rows Extra1839id select_type table type possible_keys key key_len ref rows Extra
18401 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where18401 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
1841explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;1841explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
1842id select_type table type possible_keys key key_len ref rows Extra1842id select_type table type possible_keys key key_len ref rows Extra
18431 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where18431 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
1844explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;1844explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
1845id select_type table type possible_keys key key_len ref rows Extra1845id select_type table type possible_keys key key_len ref rows Extra
18461 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 Using where18461 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 32 Using where; Using index
1847explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;1847explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
1848id select_type table type possible_keys key key_len ref rows Extra1848id select_type table type possible_keys key key_len ref rows Extra
18491 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using index for group-by18491 SIMPLE t1 range NULL idx_t1_1 147 NULL 129 Using index for group-by
@@ -1922,19 +1922,19 @@
1922explain extended select a1,a2,min(b),max(b) from t11922explain extended select a1,a2,min(b),max(b) from t1
1923where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;1923where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;
1924id select_type table type possible_keys key key_len ref rows filtered Extra1924id select_type table type possible_keys key key_len ref rows filtered Extra
19251 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 100.00 Using where; Using index19251 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 100.00 Using where; Using index
1926Warnings:1926Warnings:
1927Note 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`1927Note 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`
1928explain extended select a1,a2,b,min(c),max(c) from t11928explain extended select a1,a2,b,min(c),max(c) from t1
1929where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;1929where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;
1930id select_type table type possible_keys key key_len ref rows filtered Extra1930id select_type table type possible_keys key key_len ref rows filtered Extra
19311 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 130 NULL 4 100.00 Using where19311 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 50.00 Using where; Using temporary; Using filesort
1932Warnings:1932Warnings:
1933Note 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`1933Note 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`
1934explain extended select a1,a2,b,c from t11934explain extended select a1,a2,b,c from t1
1935where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;1935where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;
1936id select_type table type possible_keys key key_len ref rows filtered Extra1936id select_type table type possible_keys key key_len ref rows filtered Extra
19371 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 100.00 Using where19371 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 50.00 Using where; Using temporary; Using filesort
1938Warnings:1938Warnings:
1939Note 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`1939Note 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`
1940explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;1940explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;
@@ -1942,7 +1942,7 @@
19421 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index19421 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
1943explain 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;1943explain 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;
1944id select_type table type possible_keys key key_len ref rows filtered Extra1944id select_type table type possible_keys key key_len ref rows filtered Extra
19451 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 4 100.00 Using where; Using index19451 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 64 100.00 Using where; Using index
1946Warnings:1946Warnings:
1947Note 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`1947Note 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`
1948explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;1948explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
@@ -1966,12 +1966,12 @@
19661 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using index19661 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using index
1967explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;1967explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
1968id select_type table type possible_keys key key_len ref rows filtered Extra1968id select_type table type possible_keys key key_len ref rows filtered Extra
19691 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 100.00 Using where19691 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
1970Warnings:1970Warnings:
1971Note 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`1971Note 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`
1972explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;1972explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
1973id select_type table type possible_keys key key_len ref rows filtered Extra1973id select_type table type possible_keys key key_len ref rows filtered Extra
19741 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1 100.00 Using where19741 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 32 100.00 Using where; Using index
1975Warnings:1975Warnings:
1976Note 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`1976Note 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`
1977explain select distinct(a1) from t1 where ord(a2) = 98;1977explain select distinct(a1) from t1 where ord(a2) = 98;
@@ -2047,10 +2047,10 @@
2047BB2047BB
2048EXPLAIN SELECT a FROM t1 WHERE a='AA' GROUP BY a;2048EXPLAIN SELECT a FROM t1 WHERE a='AA' GROUP BY a;
2049id select_type table type possible_keys key key_len ref rows Extra2049id select_type table type possible_keys key key_len ref rows Extra
20501 SIMPLE t1 ref PRIMARY PRIMARY 7 const 1 Using where; Using index20501 SIMPLE t1 ref PRIMARY PRIMARY 7 const 3 Using where; Using index
2051EXPLAIN SELECT a FROM t1 WHERE a='BB' GROUP BY a;2051EXPLAIN SELECT a FROM t1 WHERE a='BB' GROUP BY a;
2052id select_type table type possible_keys key key_len ref rows Extra2052id select_type table type possible_keys key key_len ref rows Extra
20531 SIMPLE t1 ref PRIMARY PRIMARY 7 const 1 Using where; Using index20531 SIMPLE t1 ref PRIMARY PRIMARY 7 const 3 Using where; Using index
2054SELECT DISTINCT a FROM t1 WHERE a='BB';2054SELECT DISTINCT a FROM t1 WHERE a='BB';
2055a2055a
2056BB2056BB
20572057
=== modified file 'mysql-test/suite/pbxt/r/join_nested.result'
--- mysql-test/suite/pbxt/r/join_nested.result 2009-12-27 16:48:27 +0000
+++ mysql-test/suite/pbxt/r/join_nested.result 2010-05-07 08:52:27 +0000
@@ -1055,7 +1055,7 @@
1055(t8.b=t9.b OR t8.c IS NULL) AND1055(t8.b=t9.b OR t8.c IS NULL) AND
1056(t9.a=1);1056(t9.a=1);
1057id select_type table type possible_keys key key_len ref rows Extra1057id select_type table type possible_keys key key_len ref rows Extra
10581 SIMPLE t0 ref idx_a idx_a 5 const 1 10581 SIMPLE t0 ref idx_a idx_a 5 const 2
10591 SIMPLE t1 ref idx_b idx_b 5 test.t0.b 1 10591 SIMPLE t1 ref idx_b idx_b 5 test.t0.b 1
10601 SIMPLE t2 ALL NULL NULL NULL NULL 3 10601 SIMPLE t2 ALL NULL NULL NULL NULL 3
10611 SIMPLE t3 ALL NULL NULL NULL NULL 2 10611 SIMPLE t3 ALL NULL NULL NULL NULL 2
10621062
=== modified file 'mysql-test/suite/pbxt/r/negation_elimination.result'
--- mysql-test/suite/pbxt/r/negation_elimination.result 2009-11-24 10:19:08 +0000
+++ mysql-test/suite/pbxt/r/negation_elimination.result 2010-05-07 08:52:27 +0000
@@ -388,7 +388,7 @@
388test.t1 analyze status OK388test.t1 analyze status OK
389explain 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));389explain 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));
390id select_type table type possible_keys key key_len ref rows filtered Extra390id select_type table type possible_keys key key_len ref rows filtered Extra
3911 SIMPLE t1 index NULL a 5 NULL 5 100.00 Using where; Using index3911 SIMPLE t1 index NULL a 5 NULL 21 100.00 Using where; Using index
392Warnings:392Warnings:
393Note 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`393Note 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`
394drop table t1;394drop table t1;
395395
=== modified file 'mysql-test/suite/pbxt/r/null.result'
--- mysql-test/suite/pbxt/r/null.result 2009-08-17 15:57:58 +0000
+++ mysql-test/suite/pbxt/r/null.result 2010-05-07 08:52:27 +0000
@@ -179,7 +179,7 @@
179Warning 1265 Data truncated for column 'i' at row 513179Warning 1265 Data truncated for column 'i' at row 513
180explain select * from t1 where i=2 or i is null;180explain select * from t1 where i=2 or i is null;
181id select_type table type possible_keys key key_len ref rows Extra181id select_type table type possible_keys key key_len ref rows Extra
1821 SIMPLE t1 ref i i 4 const 1 Using index1821 SIMPLE t1 ref i i 4 const 25 Using index
183select count(*) from t1 where i=2 or i is null;183select count(*) from t1 where i=2 or i is null;
184count(*)184count(*)
18591859
186186
=== modified file 'mysql-test/suite/pbxt/r/order_by.result'
--- mysql-test/suite/pbxt/r/order_by.result 2009-04-02 10:03:14 +0000
+++ mysql-test/suite/pbxt/r/order_by.result 2010-05-07 08:52:27 +0000
@@ -401,14 +401,14 @@
4011 0 4011 0
402explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;402explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
403id select_type table type possible_keys key key_len ref rows Extra403id select_type table type possible_keys key key_len ref rows Extra
4041 SIMPLE t1 index a a 20 NULL 11 Using where; Using index4041 SIMPLE t1 range a a 20 NULL 7 Using where; Using index
405select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;405select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
406a b c406a b c
4071 1 b4071 1 b
4081 1 b4081 1 b
409explain select * from t1 where a < 2 and b <= 1 order by a desc, b desc;409explain select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
410id select_type table type possible_keys key key_len ref rows Extra410id select_type table type possible_keys key key_len ref rows Extra
4111 SIMPLE t1 range a a 4 NULL 1 Using where; Using index4111 SIMPLE t1 range a a 4 NULL 6 Using where; Using index
412select * from t1 where a < 2 and b <= 1 order by a desc, b desc;412select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
413a b c413a b c
4141 1 b4141 1 b
@@ -432,7 +432,7 @@
4321 1 4321 1
433explain select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;433explain select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
434id select_type table type possible_keys key key_len ref rows Extra434id select_type table type possible_keys key key_len ref rows Extra
4351 SIMPLE t1 range a a 8 NULL 1 Using where; Using index4351 SIMPLE t1 range a a 8 NULL 6 Using where; Using index
436select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;436select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
437a b c437a b c
4382 1 b4382 1 b
@@ -444,7 +444,7 @@
4441 0 4441 0
445explain select * from t1 where a between 0 and 1 order by a desc, b desc;445explain select * from t1 where a between 0 and 1 order by a desc, b desc;
446id select_type table type possible_keys key key_len ref rows Extra446id select_type table type possible_keys key key_len ref rows Extra
4471 SIMPLE t1 range a a 4 NULL 1 Using where; Using index4471 SIMPLE t1 range a a 4 NULL 6 Using where; Using index
448select * from t1 where a between 0 and 1 order by a desc, b desc;448select * from t1 where a between 0 and 1 order by a desc, b desc;
449a b c449a b c
4501 3 b4501 3 b
451451
=== modified file 'mysql-test/suite/pbxt/r/pbxt_ref_int.result'
--- mysql-test/suite/pbxt/r/pbxt_ref_int.result 2009-08-17 15:57:58 +0000
+++ mysql-test/suite/pbxt/r/pbxt_ref_int.result 2010-05-07 08:52:27 +0000
@@ -14,7 +14,7 @@
14drop table t1;14drop table t1;
15set foreign_key_checks = 1;15set foreign_key_checks = 1;
16INSERT INTO t2 VALUES(2);16INSERT INTO t2 VALUES(2);
17ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `t1` not found)17ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `test.t1` not found)
18drop table if exists parent, child, child_child;18drop table if exists parent, child, child_child;
19CREATE TABLE parent (19CREATE TABLE parent (
20id INT NOT NULL,20id INT NOT NULL,
@@ -370,7 +370,7 @@
370CREATE TABLE t2 (s1 INT DEFAULT NULL, FOREIGN KEY (s1) REFERENCES t1 (s1));370CREATE TABLE t2 (s1 INT DEFAULT NULL, FOREIGN KEY (s1) REFERENCES t1 (s1));
371set foreign_key_checks = 1;371set foreign_key_checks = 1;
372insert into t2 values (1);372insert into t2 values (1);
373ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `t1` not found)373ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (Referenced table `test.t1` not found)
374set foreign_key_checks = 0;374set foreign_key_checks = 0;
375insert into t2 values (1);375insert into t2 values (1);
376CREATE TABLE t1 (s1 INT PRIMARY KEY);376CREATE TABLE t1 (s1 INT PRIMARY KEY);
377377
=== modified file 'mysql-test/suite/pbxt/r/range.result'
--- mysql-test/suite/pbxt/r/range.result 2009-08-17 15:57:58 +0000
+++ mysql-test/suite/pbxt/r/range.result 2010-05-07 08:52:27 +0000
@@ -964,5 +964,5 @@
964In following EXPLAIN the access method should be ref, #rows~=500 (and not 2)964In following EXPLAIN the access method should be ref, #rows~=500 (and not 2)
965explain select * from t2 where a=1000 and b<11;965explain select * from t2 where a=1000 and b<11;
966id select_type table type possible_keys key key_len ref rows Extra966id select_type table type possible_keys key key_len ref rows Extra
9671 SIMPLE t2 range a a 10 NULL 1 Using where9671 SIMPLE t2 range a a 10 NULL 2 Using where
968drop table t1, t2;968drop table t1, t2;
969969
=== modified file 'mysql-test/suite/pbxt/r/select.result'
--- mysql-test/suite/pbxt/r/select.result 2009-10-07 16:56:11 +0000
+++ mysql-test/suite/pbxt/r/select.result 2010-05-07 08:52:27 +0000
@@ -1384,52 +1384,52 @@
1384test.t2 analyze status OK1384test.t2 analyze status OK
1385explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;1385explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
1386id select_type table type possible_keys key key_len ref rows Extra1386id select_type table type possible_keys key key_len ref rows Extra
13871 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where13871 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
13881 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 13881 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
1389explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;1389explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;
1390id select_type table type possible_keys key key_len ref rows Extra1390id select_type table type possible_keys key key_len ref rows Extra
13911 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where13911 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
13921 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 13921 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
1393explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;1393explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
1394id select_type table type possible_keys key key_len ref rows Extra1394id select_type table type possible_keys key key_len ref rows Extra
13951 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where13951 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
13961 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 13961 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
1397explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;1397explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
1398id select_type table type possible_keys key key_len ref rows Extra1398id select_type table type possible_keys key key_len ref rows Extra
13991 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where13991 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
14001 SIMPLE t2 ALL NULL NULL NULL NULL 1199 14001 SIMPLE t2 ALL NULL NULL NULL NULL 1200
1401explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;1401explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
1402id select_type table type possible_keys key key_len ref rows Extra1402id select_type table type possible_keys key key_len ref rows Extra
14031 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where14031 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
14041 SIMPLE t2 ALL NULL NULL NULL NULL 1199 14041 SIMPLE t2 ALL NULL NULL NULL NULL 1200
1405explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;1405explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
1406id select_type table type possible_keys key key_len ref rows Extra1406id select_type table type possible_keys key key_len ref rows Extra
14071 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where14071 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
14081 SIMPLE t2 ALL NULL NULL NULL NULL 1199 14081 SIMPLE t2 ALL NULL NULL NULL NULL 1200
1409explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;1409explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
1410id select_type table type possible_keys key key_len ref rows Extra1410id select_type table type possible_keys key key_len ref rows Extra
14111 SIMPLE t4 ALL NULL NULL NULL NULL 12 14111 SIMPLE t4 ALL NULL NULL NULL NULL 12
14121 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where14121 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
1413explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;1413explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;
1414id select_type table type possible_keys key key_len ref rows Extra1414id select_type table type possible_keys key key_len ref rows Extra
14151 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 14151 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12
14161 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where14161 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
1417explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;1417explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;
1418id select_type table type possible_keys key key_len ref rows Extra1418id select_type table type possible_keys key key_len ref rows Extra
14191 SIMPLE t4 ALL NULL NULL NULL NULL 12 14191 SIMPLE t4 ALL NULL NULL NULL NULL 12
14201 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where14201 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where
1421explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;1421explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
1422id select_type table type possible_keys key key_len ref rows Extra1422id select_type table type possible_keys key key_len ref rows Extra
14231 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where14231 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
14241 SIMPLE t2 ALL NULL NULL NULL NULL 1199 14241 SIMPLE t2 ALL NULL NULL NULL NULL 1200
1425explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;1425explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
1426id select_type table type possible_keys key key_len ref rows Extra1426id select_type table type possible_keys key key_len ref rows Extra
14271 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where14271 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
14281 SIMPLE t2 ALL NULL NULL NULL NULL 1199 14281 SIMPLE t2 ALL NULL NULL NULL NULL 1200
1429explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;1429explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
1430id select_type table type possible_keys key key_len ref rows Extra1430id select_type table type possible_keys key key_len ref rows Extra
14311 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where14311 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
14321 SIMPLE t2 ALL NULL NULL NULL NULL 1199 14321 SIMPLE t2 ALL NULL NULL NULL NULL 1200
1433select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;1433select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
1434companynr companynr1434companynr companynr
143537 36143537 36
@@ -1437,7 +1437,7 @@
1437explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;1437explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
1438id select_type table type possible_keys key key_len ref rows Extra1438id select_type table type possible_keys key key_len ref rows Extra
14391 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary14391 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary
14401 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer14401 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Using join buffer
1441select 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;1441select 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;
1442fld1 companynr fld3 period1442fld1 companynr fld3 period
1443038008 37 reporters 10081443038008 37 reporters 1008
@@ -1511,7 +1511,7 @@
151170 absentee vest 17788966 254128.0857 3272.5940 10709871.3069151170 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
1512explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";1512explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
1513id select_type table type possible_keys key key_len ref rows filtered Extra1513id select_type table type possible_keys key key_len ref rows filtered Extra
15141 SIMPLE t2 ALL NULL NULL NULL NULL 1199 100.00 Using where15141 SIMPLE t2 ALL NULL NULL NULL NULL 1200 100.00 Using where
1515Warnings:1515Warnings:
1516Note 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` <> ''))1516Note 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` <> ''))
1517select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;1517select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
@@ -1955,7 +1955,7 @@
19551 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE19551 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
1956explain select fld3 from t2 where fld1=fld1;1956explain select fld3 from t2 where fld1=fld1;
1957id select_type table type possible_keys key key_len ref rows Extra1957id select_type table type possible_keys key key_len ref rows Extra
19581 SIMPLE t2 ALL NULL NULL NULL NULL 1199 19581 SIMPLE t2 ALL NULL NULL NULL NULL 1200
1959select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;1959select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
1960companynr fld11960companynr fld1
196134 250501196134 250501
@@ -2007,7 +2007,7 @@
2007418120074181
2008explain select min(fld1),max(fld1),count(*) from t2;2008explain select min(fld1),max(fld1),count(*) from t2;
2009id select_type table type possible_keys key key_len ref rows Extra2009id select_type table type possible_keys key key_len ref rows Extra
20101 SIMPLE t2 index NULL fld1 4 NULL 1199 Using index20101 SIMPLE t2 index NULL fld1 4 NULL 1200 Using index
2011select min(fld1),max(fld1),count(*) from t2;2011select min(fld1),max(fld1),count(*) from t2;
2012min(fld1) max(fld1) count(*)2012min(fld1) max(fld1) count(*)
20130 1232609 119920130 1232609 1199
@@ -2093,9 +2093,9 @@
2093Field Type Collation Null Key Default Extra Privileges Comment2093Field Type Collation Null Key Default Extra Privileges Comment
2094show keys from t2;2094show keys from t2;
2095Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment2095Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
2096t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE 2096t2 0 PRIMARY 1 auto A 1200 NULL NULL BTREE
2097t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE 2097t2 0 fld1 1 fld1 A 1200 NULL NULL BTREE
2098t2 1 fld3 1 fld3 A 1199 NULL NULL BTREE 2098t2 1 fld3 1 fld3 A 1200 NULL NULL BTREE
2099drop table t4, t3, t2, t1;2099drop table t4, t3, t2, t1;
2100DO 1;2100DO 1;
2101DO benchmark(100,1+1),1,1;2101DO benchmark(100,1+1),1,1;
21022102
=== modified file 'storage/pbxt/ChangeLog'
--- storage/pbxt/ChangeLog 2009-12-21 13:13:15 +0000
+++ storage/pbxt/ChangeLog 2010-05-07 08:52:27 +0000
@@ -1,6 +1,111 @@
1PBXT Release Notes1PBXT Release Notes
2==================2==================
33
4+------- 1.0.11 Pre-GA - 2010-05-11
5
6RN322: 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.
7
8RN321: Added "Extended record count" to the CHECK TABLE output. This indicates the number of records that have a data log component.
9
10RN320: All tests now run with MySQL 5.1.46.
11
12------- 1.0.10n RC4 - 2010-04-28
13
14RN319: 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.
15
16RN318: 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.
17
18------- 1.0.10m RC4 - 2010-03-29
19
20RN317: 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.
21
22------- 1.0.10k RC4 - 2010-03-29
23
24RN316: 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.
25
26RN315: 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.
27
28RN314: 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.
29
30------- 1.0.10j RC4 - 2010-03-24
31
32RN313: 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:
33
34CREATE TABLE objs (
35 id int(10) unsigned NOT NULL,
36 objdata mediumblob NOT NULL,
37 PRIMARY KEY (id)
38) ENGINE=PBXT AVG_ROW_LENGTH=10
39
40This 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.
41
42This 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).
43
44Tip: 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.
45
46The 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:
47
48byte size <= 240, add 1
49byte size < 2^16 (65536), add 3
50byte size < 2^24 (16777216), add 4
51byte size > 2^24, add 5
52
53------- 1.0.10i RC4 - 2010-03-17
54
55RN312: Fixed bug #534361: Valgrind error: write of uninitialised bytes in xt_flush_indices()
56
57RN311: Fixed ilog corruption when running out of disk space during an index flush operation, which lead to corruption of the index.
58
59------- 1.0.10h RC4 - 2010-02-25
60
61RN310: 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.
62
63RN309: 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.
64
65RN308: Fixed bug #509803: can't run tpcc (cannot compare FKs that rely on indexes of different length).
66
67------- 1.0.10g RC4 - 2010-02-11
68
69RN307: 2010-02-15: Set the internal version number 1.0.10g.
70
71RN306: All tests now run with MySQL 5.1.42.
72
73RN305: 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).
74
75RN304: Fixed bug #513012: On a table with a trigger the same record is updated more than once in one statement
76
77------- 1.0.10f RC4 - 2010-01-29
78
79RN303: 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.
80
81RN302: Fix RN1/11 back-ported from 1.1: Corrected a problem that sometimes caused a pause in activity when the record cache was full.
82
83------- 1.0.10e RC4 - 2010-01-25
84
85RN301: Fixed index statistics calculation. This bug lead to the wrong indices being selected by the optimizer because all indices returned the same cost.
86
87RN300: Fixed bug #509968: START TRANSACTION WITH CONSISTENT SNAPSHOT breaks transactional flow.
88
89RN299: Fixed bug #509218: Server asserts with Assertion `mutex->__data.__owner == 0' failed on high concurrency OLTP test.
90
91------- 1.0.10d RC4 - 2010-01-11
92
93RN298: Fixed a bug that caused huge amounts of transaction log to be written when pbxt_flush_log_at_trx_commit = 2.
94
95------- 1.0.10c RC4 - 2009-12-29
96
97RN297: Updated "LOCK TABLES ... READ LOCAL" behavior to be more restrictive and compatible with InnoDB
98
99RN296: Fixed bug #499026: START TRANSACTION WITH CONSISTENT SNAPSHOT does not work for PBXT
100
101------- 1.0.10 RC4 - 2009-12-18
102
103RN295: PBXT tests now all run with MySQL 5.1.41.
104
105RN294: Fixed bug #483714: a broken table can prevent other tables from opening
106
107RN293: 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.
108
4------- 1.0.09g RC3 - 2009-12-16109------- 1.0.09g RC3 - 2009-12-16
5110
6RN292: 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. 111RN292: 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.
7112
=== modified file 'storage/pbxt/src/backup_xt.cc'
--- storage/pbxt/src/backup_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/backup_xt.cc 2010-05-07 08:52:27 +0000
@@ -287,7 +287,7 @@
287 bd_table_no++;287 bd_table_no++;
288 try_(a) {288 try_(a) {
289 xt_ha_open_database_of_table(self, (XTPathStrPtr) path);289 xt_ha_open_database_of_table(self, (XTPathStrPtr) path);
290 tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);290 tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE);
291 pushr_(xt_heap_release, tab);291 pushr_(xt_heap_release, tab);
292 if (!(bd_ot = xt_db_open_table_using_tab(tab, bd_thread)))292 if (!(bd_ot = xt_db_open_table_using_tab(tab, bd_thread)))
293 xt_throw(self);293 xt_throw(self);
@@ -403,7 +403,7 @@
403 bd_thread->st_abort_trans = FALSE;403 bd_thread->st_abort_trans = FALSE;
404 bd_thread->st_stat_ended = FALSE;404 bd_thread->st_stat_ended = FALSE;
405 bd_thread->st_stat_trans = FALSE;405 bd_thread->st_stat_trans = FALSE;
406 bd_thread->st_is_update = FALSE;406 bd_thread->st_is_update = NULL;
407 if (!xt_xn_begin(bd_thread))407 if (!xt_xn_begin(bd_thread))
408 return backup::ERROR;408 return backup::ERROR;
409 bd_state = BUP_STATE_AFTER_LOCK;409 bd_state = BUP_STATE_AFTER_LOCK;
@@ -562,7 +562,7 @@
562 m_tables[rd_table_no-1].internal_name(path, sizeof(path));562 m_tables[rd_table_no-1].internal_name(path, sizeof(path));
563 try_(a) {563 try_(a) {
564 xt_ha_open_database_of_table(self, (XTPathStrPtr) path);564 xt_ha_open_database_of_table(self, (XTPathStrPtr) path);
565 tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);565 tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE);
566 pushr_(xt_heap_release, tab);566 pushr_(xt_heap_release, tab);
567 if (!(rd_ot = xt_db_open_table_using_tab(tab, rd_thread)))567 if (!(rd_ot = xt_db_open_table_using_tab(tab, rd_thread)))
568 xt_throw(self);568 xt_throw(self);
569569
=== modified file 'storage/pbxt/src/cache_xt.cc'
--- storage/pbxt/src/cache_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/cache_xt.cc 2010-05-07 08:52:27 +0000
@@ -90,7 +90,7 @@
90#define IDX_CAC_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, &(i)->cs_lock)90#define IDX_CAC_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, &(i)->cs_lock)
91#define IDX_CAC_FREE_LOCK(s, i) xt_spinxslock_free(s, &(i)->cs_lock) 91#define IDX_CAC_FREE_LOCK(s, i) xt_spinxslock_free(s, &(i)->cs_lock)
92#define IDX_CAC_READ_LOCK(i, s) xt_spinxslock_slock(&(i)->cs_lock, (s)->t_id)92#define IDX_CAC_READ_LOCK(i, s) xt_spinxslock_slock(&(i)->cs_lock, (s)->t_id)
93#define IDX_CAC_WRITE_LOCK(i, s) xt_spinxslock_xlock(&(i)->cs_lock, (s)->t_id)93#define IDX_CAC_WRITE_LOCK(i, s) xt_spinxslock_xlock(&(i)->cs_lock, FALSE, (s)->t_id)
94#define IDX_CAC_UNLOCK(i, s) xt_spinxslock_unlock(&(i)->cs_lock, (s)->t_id)94#define IDX_CAC_UNLOCK(i, s) xt_spinxslock_unlock(&(i)->cs_lock, (s)->t_id)
95#endif95#endif
9696
@@ -178,6 +178,7 @@
178KEY_CACHE my_cache;178KEY_CACHE my_cache;
179#undef pthread_rwlock_rdlock179#undef pthread_rwlock_rdlock
180#undef pthread_rwlock_wrlock180#undef pthread_rwlock_wrlock
181#undef pthread_rwlock_try_wrlock
181#undef pthread_rwlock_unlock182#undef pthread_rwlock_unlock
182#undef pthread_mutex_lock183#undef pthread_mutex_lock
183#undef pthread_mutex_unlock184#undef pthread_mutex_unlock
@@ -410,7 +411,7 @@
410 /* Because of the lock order, I have to release the411 /* Because of the lock order, I have to release the
411 * handle before I get a lock on the cache block.412 * handle before I get a lock on the cache block.
412 *413 *
413 * But, by doing this, thie cache block may be gone!414 * But, by doing this, this cache block may be gone!
414 */415 */
415 if (block) {416 if (block) {
416 IDX_CAC_READ_LOCK(seg, thread);417 IDX_CAC_READ_LOCK(seg, thread);
@@ -420,6 +421,11 @@
420 /* Found the block... 421 /* Found the block...
421 * {HANDLE-COUNT-SLOCK}422 * {HANDLE-COUNT-SLOCK}
422 * 04.05.2009, changed to slock.423 * 04.05.2009, changed to slock.
424 * The xlock causes too much contention
425 * on the cache block for read only loads.
426 *
427 * Is it safe?
428 * See below...
423 */429 */
424 XT_IPAGE_READ_LOCK(&block->cb_lock);430 XT_IPAGE_READ_LOCK(&block->cb_lock);
425 goto block_found;431 goto block_found;
@@ -691,6 +697,9 @@
691 }697 }
692 }698 }
693699
700 /* Must be done before freeing the blocks! */
701 ind_handle_exit(self);
702
694 if (ind_cac_globals.cg_blocks) {703 if (ind_cac_globals.cg_blocks) {
695 xt_free(self, ind_cac_globals.cg_blocks);704 xt_free(self, ind_cac_globals.cg_blocks);
696 ind_cac_globals.cg_blocks = NULL;705 ind_cac_globals.cg_blocks = NULL;
@@ -702,7 +711,6 @@
702 ind_cac_globals.cg_buffer = NULL;711 ind_cac_globals.cg_buffer = NULL;
703 }712 }
704#endif713#endif
705 ind_handle_exit(self);
706714
707 memset(&ind_cac_globals, 0, sizeof(ind_cac_globals));715 memset(&ind_cac_globals, 0, sizeof(ind_cac_globals));
708}716}
@@ -882,7 +890,58 @@
882 while (xblock) {890 while (xblock) {
883 if (block == xblock) {891 if (block == xblock) {
884 /* Found the block... */892 /* Found the block... */
885 XT_IPAGE_WRITE_LOCK(&block->cb_lock, ot->ot_thread->t_id);893 /* It is possible that a thread enters this code holding a
894 * lock on a page. This can cause a deadlock:
895 *
896 * #0 0x91faa2ce in semaphore_wait_signal_trap
897 * #1 0x91fb1da5 in pthread_mutex_lock
898 * #2 0x00e2ec13 in xt_p_mutex_lock at pthread_xt.cc:544
899 * #3 0x00e6c30a in xt_xsmutex_xlock at lock_xt.cc:1547
900 * #4 0x00dee402 in ind_free_block at cache_xt.cc:879
901 * #5 0x00dee76a in ind_cac_free_lru_blocks at cache_xt.cc:1033
902 * #6 0x00def8d1 in xt_ind_reserve at cache_xt.cc:1513
903 * #7 0x00e22118 in xt_idx_insert at index_xt.cc:2047
904 * #8 0x00e4d7ee in xt_tab_new_record at table_xt.cc:4702
905 * #9 0x00e0ff0b in ha_pbxt::write_row at ha_pbxt.cc:2340
906 * #10 0x0023a00f in handler::ha_write_row at handler.cc:4570
907 * #11 0x001a32c8 in write_record at sql_insert.cc:1568
908 * #12 0x001ab635 in mysql_insert at sql_insert.cc:812
909 * #13 0x0010e068 in mysql_execute_command at sql_parse.cc:3066
910 * #14 0x0011480d in mysql_parse at sql_parse.cc:5787
911 * #15 0x00115afb in dispatch_command at sql_parse.cc:1200
912 * #16 0x00116de2 in do_command at sql_parse.cc:857
913 * #17 0x00101ee4 in handle_one_connection at sql_connect.cc:1115
914 * #18 0x91fdb155 in _pthread_start
915 * #19 0x91fdb012 in thread_start
916 *
917 * #0 0x91fb146e in __semwait_signal
918 * #1 0x91fb12ef in nanosleep$UNIX2003
919 * #2 0x91fb1236 in usleep$UNIX2003
920 * #3 0x00e52112 in xt_yield at thread_xt.cc:1274
921 * #4 0x00e6c0eb in xt_spinxslock_xlock at lock_xt.cc:1456
922 * #5 0x00dee444 in ind_free_block at cache_xt.cc:886
923 * #6 0x00dee76a in ind_cac_free_lru_blocks at cache_xt.cc:1033
924 * #7 0x00deeaf0 in ind_cac_fetch at cache_xt.cc:1130
925 * #8 0x00def604 in xt_ind_fetch at cache_xt.cc:1386
926 * #9 0x00e2159a in xt_idx_update_row_id at index_xt.cc:2489
927 * #10 0x00e603c8 in xn_sw_clean_indices at xaction_xt.cc:1932
928 * #11 0x00e606d4 in xn_sw_cleanup_variation at xaction_xt.cc:2056
929 * #12 0x00e60e29 in xn_sw_cleanup_xact at xaction_xt.cc:2276
930 * #13 0x00e615ed in xn_sw_main at xaction_xt.cc:2433
931 * #14 0x00e61919 in xn_sw_run_thread at xaction_xt.cc:2564
932 * #15 0x00e53f80 in thr_main at thread_xt.cc:1017
933 * #16 0x91fdb155 in _pthread_start
934 * #17 0x91fdb012 in thread_start
935 *
936 * So we back off if a lock is held!
937 */
938 if (!XT_IPAGE_WRITE_TRY_LOCK(&block->cb_lock, ot->ot_thread->t_id)) {
939 IDX_CAC_UNLOCK(seg, ot->ot_thread);
940#ifdef DEBUG_CHECK_IND_CACHE
941 xt_ind_check_cache(NULL);
942#endif
943 return FALSE;
944 }
886 if (block->cb_state != IDX_CAC_BLOCK_CLEAN) {945 if (block->cb_state != IDX_CAC_BLOCK_CLEAN) {
887 /* This block cannot be freeed: */946 /* This block cannot be freeed: */
888 XT_IPAGE_UNLOCK(&block->cb_lock, TRUE);947 XT_IPAGE_UNLOCK(&block->cb_lock, TRUE);
@@ -1376,6 +1435,7 @@
1376 register XTIndBlockPtr block;1435 register XTIndBlockPtr block;
1377 DcSegmentPtr seg;1436 DcSegmentPtr seg;
1378 xtWord2 branch_size;1437 xtWord2 branch_size;
1438 u_int rec_size;
1379 xtBool xlock = FALSE;1439 xtBool xlock = FALSE;
13801440
1381#ifdef DEBUG1441#ifdef DEBUG
@@ -1386,10 +1446,24 @@
1386 return FAILED;1446 return FAILED;
13871447
1388 branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2);1448 branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2);
1389 if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) {1449 rec_size = XT_GET_INDEX_BLOCK_LEN(branch_size);
1390 IDX_CAC_UNLOCK(seg, ot->ot_thread);1450 if (rec_size < 2 || rec_size > XT_INDEX_PAGE_SIZE)
1391 xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);1451 goto failed_corrupt;
1392 return FAILED;1452 if (ind->mi_fix_key) {
1453 rec_size -= 2;
1454 if (XT_IS_NODE(branch_size)) {
1455 if (rec_size != 0) {
1456 if (rec_size < XT_NODE_REF_SIZE)
1457 goto failed_corrupt;
1458 rec_size -= XT_NODE_REF_SIZE;
1459 if ((rec_size % (ind->mi_key_size + XT_RECORD_REF_SIZE + XT_NODE_REF_SIZE)) != 0)
1460 goto failed_corrupt;
1461 }
1462 }
1463 else {
1464 if ((rec_size % (ind->mi_key_size + XT_RECORD_REF_SIZE)) != 0)
1465 goto failed_corrupt;
1466 }
1393 }1467 }
13941468
1395 switch (ltype) {1469 switch (ltype) {
@@ -1450,6 +1524,11 @@
1450 iref->ir_block = block;1524 iref->ir_block = block;
1451 iref->ir_branch = (XTIdxBranchDPtr) block->cb_data;1525 iref->ir_branch = (XTIdxBranchDPtr) block->cb_data;
1452 return OK;1526 return OK;
1527
1528 failed_corrupt:
1529 IDX_CAC_UNLOCK(seg, ot->ot_thread);
1530 xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
1531 return FAILED;
1453}1532}
14541533
1455xtPublic xtBool xt_ind_release(XTOpenTablePtr ot, XTIndexPtr ind, XTPageUnlockType XT_NDEBUG_UNUSED(utype), XTIndReferencePtr iref)1534xtPublic xtBool xt_ind_release(XTOpenTablePtr ot, XTIndexPtr ind, XTPageUnlockType XT_NDEBUG_UNUSED(utype), XTIndReferencePtr iref)
14561535
=== modified file 'storage/pbxt/src/cache_xt.h'
--- storage/pbxt/src/cache_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/cache_xt.h 2010-05-07 08:52:27 +0000
@@ -58,7 +58,8 @@
58#define XT_IPAGE_INIT_LOCK(s, i) xt_atomicrwlock_init_with_autoname(s, i)58#define XT_IPAGE_INIT_LOCK(s, i) xt_atomicrwlock_init_with_autoname(s, i)
59#define XT_IPAGE_FREE_LOCK(s, i) xt_atomicrwlock_free(s, i) 59#define XT_IPAGE_FREE_LOCK(s, i) xt_atomicrwlock_free(s, i)
60#define XT_IPAGE_READ_LOCK(i) xt_atomicrwlock_slock(i)60#define XT_IPAGE_READ_LOCK(i) xt_atomicrwlock_slock(i)
61#define XT_IPAGE_WRITE_LOCK(i, o) xt_atomicrwlock_xlock(i, o)61#define XT_IPAGE_WRITE_LOCK(i, o) xt_atomicrwlock_xlock(i, FALSE, o)
62#define XT_IPAGE_WRITE_TRY_LOCK(i, o) xt_atomicrwlock_xlock(i, TRUE, o)
62#define XT_IPAGE_UNLOCK(i, x) xt_atomicrwlock_unlock(i, x)63#define XT_IPAGE_UNLOCK(i, x) xt_atomicrwlock_unlock(i, x)
63#elif defined(XT_IPAGE_USE_PTHREAD_RW)64#elif defined(XT_IPAGE_USE_PTHREAD_RW)
64#define XT_IPAGE_LOCK_TYPE xt_rwlock_type65#define XT_IPAGE_LOCK_TYPE xt_rwlock_type
@@ -66,20 +67,23 @@
66#define XT_IPAGE_FREE_LOCK(s, i) xt_free_rwlock(i) 67#define XT_IPAGE_FREE_LOCK(s, i) xt_free_rwlock(i)
67#define XT_IPAGE_READ_LOCK(i) xt_slock_rwlock_ns(i)68#define XT_IPAGE_READ_LOCK(i) xt_slock_rwlock_ns(i)
68#define XT_IPAGE_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i)69#define XT_IPAGE_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i)
70#define XT_IPAGE_WRITE_TRY_LOCK(i, s) xt_xlock_try_rwlock_ns(i)
69#define XT_IPAGE_UNLOCK(i, x) xt_unlock_rwlock_ns(i)71#define XT_IPAGE_UNLOCK(i, x) xt_unlock_rwlock_ns(i)
70#elif defined(XT_IPAGE_USE_SPINXSLOCK)72#elif defined(XT_IPAGE_USE_SPINXSLOCK)
71#define XT_IPAGE_LOCK_TYPE XTSpinXSLockRec73#define XT_IPAGE_LOCK_TYPE XTSpinXSLockRec
72#define XT_IPAGE_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)74#define XT_IPAGE_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
73#define XT_IPAGE_FREE_LOCK(s, i) xt_spinxslock_free(s, i) 75#define XT_IPAGE_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
74#define XT_IPAGE_READ_LOCK(i) xt_spinxslock_slock(i)76#define XT_IPAGE_READ_LOCK(i) xt_spinxslock_slock(i)
75#define XT_IPAGE_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, o)77#define XT_IPAGE_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, FALSE, o)
78#define XT_IPAGE_WRITE_TRY_LOCK(i, o) xt_spinxslock_xlock(i, TRUE, o)
76#define XT_IPAGE_UNLOCK(i, x) xt_spinxslock_unlock(i, x)79#define XT_IPAGE_UNLOCK(i, x) xt_spinxslock_unlock(i, x)
77#else // XT_IPAGE_USE_SKEW_RW80#else // XT_IPAGE_USE_SKEW_RW
78#define XT_IPAGE_LOCK_TYPE XTSkewRWLockRec81#define XT_IPAGE_LOCK_TYPE XTSkewRWLockRec
79#define XT_IPAGE_INIT_LOCK(s, i) xt_skewrwlock_init_with_autoname(s, i)82#define XT_IPAGE_INIT_LOCK(s, i) xt_skewrwlock_init_with_autoname(s, i)
80#define XT_IPAGE_FREE_LOCK(s, i) xt_skewrwlock_free(s, i) 83#define XT_IPAGE_FREE_LOCK(s, i) xt_skewrwlock_free(s, i)
81#define XT_IPAGE_READ_LOCK(i) xt_skewrwlock_slock(i)84#define XT_IPAGE_READ_LOCK(i) xt_skewrwlock_slock(i)
82#define XT_IPAGE_WRITE_LOCK(i, o) xt_skewrwlock_xlock(i, o)85#define XT_IPAGE_WRITE_LOCK(i, o) xt_skewrwlock_xlock(i, FALSE, o)
86#define XT_IPAGE_WRITE_TRY_LOCK(i, o) xt_skewrwlock_xlock(i, TRUE, o)
83#define XT_IPAGE_UNLOCK(i, x) xt_skewrwlock_unlock(i, x)87#define XT_IPAGE_UNLOCK(i, x) xt_skewrwlock_unlock(i, x)
84#endif88#endif
8589
@@ -103,10 +107,10 @@
103 struct XTIndBlock *cb_lr_used; /* Less recently used blocks. */107 struct XTIndBlock *cb_lr_used; /* Less recently used blocks. */
104 /* Protected by cb_lock: */108 /* Protected by cb_lock: */
105 XT_IPAGE_LOCK_TYPE cb_lock;109 XT_IPAGE_LOCK_TYPE cb_lock;
106 xtWord1 cb_state; /* Block status. */110 xtWord4 cp_flush_seq;
107 xtWord2 cb_handle_count; /* TRUE if this page is referenced by a handle. */111 xtWord2 cb_handle_count; /* TRUE if this page is referenced by a handle. */
108 xtWord2 cp_flush_seq;
109 xtWord2 cp_del_count; /* Number of deleted entries. */112 xtWord2 cp_del_count; /* Number of deleted entries. */
113 xtWord1 cb_state; /* Block status. */
110#ifdef XT_USE_DIRECT_IO_ON_INDEX114#ifdef XT_USE_DIRECT_IO_ON_INDEX
111 xtWord1 *cb_data;115 xtWord1 *cb_data;
112#else116#else
113117
=== modified file 'storage/pbxt/src/database_xt.cc'
--- storage/pbxt/src/database_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/database_xt.cc 2010-05-07 08:52:27 +0000
@@ -68,6 +68,7 @@
68xtPublic int xt_db_auto_increment_mode; /* 0 = MySQL compatible, 1 = PrimeBase Compatible. */68xtPublic int xt_db_auto_increment_mode; /* 0 = MySQL compatible, 1 = PrimeBase Compatible. */
69xtPublic int xt_db_offline_log_function; /* 0 = recycle logs, 1 = delete logs, 2 = keep logs */69xtPublic int xt_db_offline_log_function; /* 0 = recycle logs, 1 = delete logs, 2 = keep logs */
70xtPublic int xt_db_sweeper_priority; /* 0 = low (default), 1 = normal, 2 = high */70xtPublic int xt_db_sweeper_priority; /* 0 = low (default), 1 = normal, 2 = high */
71xtPublic int xt_db_flush_log_at_trx_commit; /* 0 = no-write/no-flush, 1 = yes, 2 = write/no-flush */
7172
72xtPublic XTSortedListPtr xt_db_open_db_by_id = NULL;73xtPublic XTSortedListPtr xt_db_open_db_by_id = NULL;
73xtPublic XTHashTabPtr xt_db_open_databases = NULL;74xtPublic XTHashTabPtr xt_db_open_databases = NULL;
@@ -288,6 +289,7 @@
288 /* Wait for the checkpointer: */289 /* Wait for the checkpointer: */
289 xt_wait_for_checkpointer(self, db);290 xt_wait_for_checkpointer(self, db);
290 }291 }
292 xt_stop_flusher(self, db);
291 xt_stop_checkpointer(self, db);293 xt_stop_checkpointer(self, db);
292 xt_stop_writer(self, db);294 xt_stop_writer(self, db);
293 xt_stop_sweeper(self, db);295 xt_stop_sweeper(self, db);
@@ -317,6 +319,7 @@
317{319{
318 XTDatabaseHPtr db = (XTDatabaseHPtr) x;320 XTDatabaseHPtr db = (XTDatabaseHPtr) x;
319321
322 xt_stop_flusher(self, db);
320 xt_stop_checkpointer(self, db);323 xt_stop_checkpointer(self, db);
321 xt_stop_compactor(self, db);324 xt_stop_compactor(self, db);
322 xt_stop_sweeper(self, db);325 xt_stop_sweeper(self, db);
@@ -475,6 +478,8 @@
475 xt_start_compactor(self, db);478 xt_start_compactor(self, db);
476 xt_start_writer(self, db);479 xt_start_writer(self, db);
477 xt_start_checkpointer(self, db);480 xt_start_checkpointer(self, db);
481 if (xt_db_flush_log_at_trx_commit == 0 || xt_db_flush_log_at_trx_commit == 2)
482 xt_start_flusher(self, db);
478483
479 popr_();484 popr_();
480 xt_ht_put(self, xt_db_open_databases, db);485 xt_ht_put(self, xt_db_open_databases, db);
@@ -574,6 +579,7 @@
574 pushr_(xt_ht_unlock, xt_db_open_databases);579 pushr_(xt_ht_unlock, xt_db_open_databases);
575580
576 /* Shutdown the database daemons: */581 /* Shutdown the database daemons: */
582 xt_stop_flusher(self, db);
577 xt_stop_checkpointer(self, db);583 xt_stop_checkpointer(self, db);
578 xt_stop_sweeper(self, db);584 xt_stop_sweeper(self, db);
579 xt_stop_compactor(self, db);585 xt_stop_compactor(self, db);
@@ -902,7 +908,7 @@
902 XTTableHPtr tab;908 XTTableHPtr tab;
903 xtTableID tab_id;909 xtTableID tab_id;
904910
905 pushsr_(tab, xt_heap_release, xt_use_table(self, tab_name, no_load, missing_ok, NULL));911 pushsr_(tab, xt_heap_release, xt_use_table(self, tab_name, no_load, missing_ok));
906 if (!tab) {912 if (!tab) {
907 freer_(); // xt_heap_release(tab)913 freer_(); // xt_heap_release(tab)
908 return NULL;914 return NULL;
909915
=== modified file 'storage/pbxt/src/database_xt.h'
--- storage/pbxt/src/database_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/database_xt.h 2010-05-07 08:52:27 +0000
@@ -60,6 +60,7 @@
60extern int xt_db_auto_increment_mode;60extern int xt_db_auto_increment_mode;
61extern int xt_db_offline_log_function;61extern int xt_db_offline_log_function;
62extern int xt_db_sweeper_priority;62extern int xt_db_sweeper_priority;
63extern int xt_db_flush_log_at_trx_commit;
6364
64extern XTSortedListPtr xt_db_open_db_by_id;65extern XTSortedListPtr xt_db_open_db_by_id;
65extern XTHashTabPtr xt_db_open_databases;66extern XTHashTabPtr xt_db_open_databases;
@@ -187,6 +188,10 @@
187 xt_mutex_type db_cp_lock;188 xt_mutex_type db_cp_lock;
188 xt_cond_type db_cp_cond; /* Writer condition when idle (must bw woken by log flush! */189 xt_cond_type db_cp_cond; /* Writer condition when idle (must bw woken by log flush! */
189 XTCheckPointStateRec db_cp_state; /* The checkpoint state. */190 XTCheckPointStateRec db_cp_state; /* The checkpoint state. */
191
192 /* The "flusher" thread (used when pbxt_flush_log_at_trx_commit = 0 or 2) */
193 struct XTThread *db_fl_thread; /* The flusher thread (flushes the transation log). */
194 xt_mutex_type db_fl_lock;
190} XTDatabaseRec, *XTDatabaseHPtr; /* Heap pointer */195} XTDatabaseRec, *XTDatabaseHPtr; /* Heap pointer */
191196
192#define XT_FOR_USER 0197#define XT_FOR_USER 0
193198
=== modified file 'storage/pbxt/src/datadic_xt.cc'
--- storage/pbxt/src/datadic_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/datadic_xt.cc 2010-05-07 08:52:27 +0000
@@ -1142,8 +1142,8 @@
11421142
1143void XTParseTable::parseReferenceDefinition(XTThreadPtr self, u_int req_cols)1143void XTParseTable::parseReferenceDefinition(XTThreadPtr self, u_int req_cols)
1144{1144{
1145 int on_delete = XT_KEY_ACTION_DEFAULT;1145 int on_delete = XT_KEY_ACTION_RESTRICT;
1146 int on_update = XT_KEY_ACTION_DEFAULT;1146 int on_update = XT_KEY_ACTION_RESTRICT;
1147 char name[XT_IDENTIFIER_NAME_SIZE];1147 char name[XT_IDENTIFIER_NAME_SIZE];
1148 char parent_name[XT_IDENTIFIER_NAME_SIZE];1148 char parent_name[XT_IDENTIFIER_NAME_SIZE];
1149 u_int cols = 0;1149 u_int cols = 0;
@@ -1437,7 +1437,7 @@
1437 XTTableHPtr tab;1437 XTTableHPtr tab;
14381438
1439 /* Find the table... */1439 /* Find the table... */
1440 pushsr_(tab, xt_heap_release, xt_use_table(self, (XTPathStrPtr) path, FALSE, TRUE, NULL));1440 pushsr_(tab, xt_heap_release, xt_use_table(self, (XTPathStrPtr) path, FALSE, TRUE));
14411441
1442 /* Clone the foreign key definitions: */1442 /* Clone the foreign key definitions: */
1443 if (tab && tab->tab_dic.dic_table) {1443 if (tab && tab->tab_dic.dic_table) {
@@ -2027,24 +2027,52 @@
2027void XTDDTableRef::deleteAllRows(XTThreadPtr self)2027void XTDDTableRef::deleteAllRows(XTThreadPtr self)
2028{2028{
2029 XTOpenTablePtr ot;2029 XTOpenTablePtr ot;
2030 xtInt8 row_count;2030 xtBool eof;
2031 xtWord1 *buffer;
20312032
2032 if (!tr_fkey->getReferenceIndexPtr())2033 if (!tr_fkey->getReferenceIndexPtr())
2033 throw_();2034 xt_throw(self);
20342035
2035 if (!tr_fkey->getIndexPtr())2036 if (!tr_fkey->getIndexPtr())
2036 throw_();2037 xt_throw(self);
20372038
2038 if (!(ot = xt_db_open_table_using_tab(tr_fkey->co_table->dt_table, self)))2039 if (!(ot = xt_db_open_table_using_tab(tr_fkey->co_table->dt_table, self)))
2039 throw_();2040 xt_throw(self);
20402041
2042 /* {FREE-ROWS-BAD} */
2043 /*
2041 row_count = ((xtInt8) ot->ot_table->tab_row_eof_id) - 1;2044 row_count = ((xtInt8) ot->ot_table->tab_row_eof_id) - 1;
2042 row_count -= (xtInt8) ot->ot_table->tab_row_fnum;2045 row_count -= (xtInt8) ot->ot_table->tab_row_fnum;
2046 */
2047 /* Check if there are any rows in the referencing table: */
2048 if (!xt_tab_seq_init(ot))
2049 goto failed;
2050
2051 if (!(buffer = (xtWord1 *) xt_malloc(self, ot->ot_table->tab_dic.dic_mysql_buf_size)))
2052 goto failed_1;
2053
2054 if (!xt_tab_seq_next(ot, buffer, &eof))
2055 goto failed_2;
2056
2057 xt_free(self, buffer);
2058
2059 xt_tab_seq_exit(ot);
20432060
2044 xt_db_return_table_to_pool_ns(ot);2061 xt_db_return_table_to_pool_ns(ot);
20452062
2046 if (row_count > 0)2063 if (!eof)
2047 xt_throw_ixterr(XT_CONTEXT, XT_ERR_ROW_IS_REFERENCED, tr_fkey->co_name);2064 xt_throw_ixterr(XT_CONTEXT, XT_ERR_ROW_IS_REFERENCED, tr_fkey->co_name);
2065 return;
2066
2067 failed_2:
2068 xt_free(self, buffer);
2069
2070 failed_1:
2071 xt_tab_seq_exit(ot);
2072
2073 failed:
2074 xt_db_return_table_to_pool_ns(ot);
2075 xt_throw(self);
2048}2076}
20492077
2050void XTDDIndex::init(XTThreadPtr self, XTObject *obj)2078void XTDDIndex::init(XTThreadPtr self, XTObject *obj)
@@ -2117,7 +2145,7 @@
2117 }2145 }
2118 xt_sb_concat(self, sb, "`)");2146 xt_sb_concat(self, sb, "`)");
2119 2147
2120 if (fk_on_delete != XT_KEY_ACTION_DEFAULT && fk_on_delete != XT_KEY_ACTION_RESTRICT) {2148 if (fk_on_delete != XT_KEY_ACTION_RESTRICT) {
2121 xt_sb_concat(self, sb, " ON DELETE ");2149 xt_sb_concat(self, sb, " ON DELETE ");
2122 switch (fk_on_delete) {2150 switch (fk_on_delete) {
2123 case XT_KEY_ACTION_CASCADE: xt_sb_concat(self, sb, "CASCADE"); break;2151 case XT_KEY_ACTION_CASCADE: xt_sb_concat(self, sb, "CASCADE"); break;
@@ -2126,10 +2154,9 @@
2126 case XT_KEY_ACTION_NO_ACTION: xt_sb_concat(self, sb, "NO ACTION"); break;2154 case XT_KEY_ACTION_NO_ACTION: xt_sb_concat(self, sb, "NO ACTION"); break;
2127 }2155 }
2128 }2156 }
2129 if (fk_on_update != XT_KEY_ACTION_DEFAULT && fk_on_update != XT_KEY_ACTION_RESTRICT) {2157 if (fk_on_update != XT_KEY_ACTION_RESTRICT) {
2130 xt_sb_concat(self, sb, " ON UPDATE ");2158 xt_sb_concat(self, sb, " ON UPDATE ");
2131 switch (fk_on_update) {2159 switch (fk_on_update) {
2132 case XT_KEY_ACTION_DEFAULT: xt_sb_concat(self, sb, "RESTRICT"); break;
2133 case XT_KEY_ACTION_RESTRICT: xt_sb_concat(self, sb, "RESTRICT"); break;2160 case XT_KEY_ACTION_RESTRICT: xt_sb_concat(self, sb, "RESTRICT"); break;
2134 case XT_KEY_ACTION_CASCADE: xt_sb_concat(self, sb, "CASCADE"); break;2161 case XT_KEY_ACTION_CASCADE: xt_sb_concat(self, sb, "CASCADE"); break;
2135 case XT_KEY_ACTION_SET_NULL: xt_sb_concat(self, sb, "SET NULL"); break;2162 case XT_KEY_ACTION_SET_NULL: xt_sb_concat(self, sb, "SET NULL"); break;
@@ -2259,8 +2286,8 @@
2259{2286{
2260 XTDDTable *ref_tab;2287 XTDDTable *ref_tab;
22612288
2262 xt_xlock_rwlock(self, &co_table->dt_ref_lock);2289 xt_recurrwlock_xlock(self, &co_table->dt_ref_lock);
2263 pushr_(xt_unlock_rwlock, &co_table->dt_ref_lock);2290 pushr_(xt_recurrwlock_unxlock, &co_table->dt_ref_lock);
22642291
2265 if ((ref_tab = fk_ref_table)) { 2292 if ((ref_tab = fk_ref_table)) {
2266 fk_ref_table = NULL;2293 fk_ref_table = NULL;
@@ -2270,7 +2297,7 @@
22702297
2271 fk_ref_index = UINT_MAX;2298 fk_ref_index = UINT_MAX;
22722299
2273 freer_(); // xt_unlock_rwlock(&co_table->dt_ref_lock);2300 freer_(); // xt_recurrwlock_unxlock(&co_table->dt_ref_lock);
2274}2301}
22752302
2276/*2303/*
@@ -2289,7 +2316,7 @@
2289 /* This lock ensures that the foreign key references are not2316 /* This lock ensures that the foreign key references are not
2290 * changed.2317 * changed.
2291 */2318 */
2292 xt_slock_rwlock_ns(&co_table->dt_ref_lock);2319 xt_recurrwlock_slock_ns(&co_table->dt_ref_lock);
22932320
2294 if (!(loc_ind = getIndexPtr()))2321 if (!(loc_ind = getIndexPtr()))
2295 goto failed;2322 goto failed;
@@ -2374,11 +2401,11 @@
2374 xt_db_return_table_to_pool_ns(ot);2401 xt_db_return_table_to_pool_ns(ot);
23752402
2376 failed:2403 failed:
2377 xt_unlock_rwlock_ns(&co_table->dt_ref_lock);2404 xt_recurrwlock_unslock_ns(&co_table->dt_ref_lock);
2378 return false;2405 return false;
23792406
2380 success:2407 success:
2381 xt_unlock_rwlock_ns(&co_table->dt_ref_lock);2408 xt_recurrwlock_unslock_ns(&co_table->dt_ref_lock);
2382 return true;2409 return true;
2383}2410}
23842411
@@ -2389,7 +2416,6 @@
2389{2416{
2390 switch (action)2417 switch (action)
2391 {2418 {
2392 case XT_KEY_ACTION_DEFAULT:
2393 case XT_KEY_ACTION_RESTRICT:2419 case XT_KEY_ACTION_RESTRICT:
2394 return "RESTRICT";2420 return "RESTRICT";
2395 case XT_KEY_ACTION_CASCADE:2421 case XT_KEY_ACTION_CASCADE:
@@ -2407,7 +2433,7 @@
24072433
2408void XTDDTable::init(XTThreadPtr self)2434void XTDDTable::init(XTThreadPtr self)
2409{2435{
2410 xt_init_rwlock_with_autoname(self, &dt_ref_lock);2436 xt_recurrwlock_init_with_autoname(self, &dt_ref_lock);
2411 dt_trefs = NULL;2437 dt_trefs = NULL;
2412}2438}
24132439
@@ -2444,7 +2470,7 @@
2444 ptr->release(self);2470 ptr->release(self);
2445 }2471 }
24462472
2447 xt_free_rwlock(&dt_ref_lock);2473 xt_recurrwlock_free(&dt_ref_lock);
2448}2474}
24492475
2450XTDDColumn *XTDDTable::findColumn(char *name)2476XTDDColumn *XTDDTable::findColumn(char *name)
@@ -2520,8 +2546,8 @@
2520 throw_();2546 throw_();
2521 }2547 }
25222548
2523 xt_xlock_rwlock(self, &dt_ref_lock);2549 xt_recurrwlock_xlock(self, &dt_ref_lock);
2524 pushr_(xt_unlock_rwlock, &dt_ref_lock);2550 pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
25252551
2526 if (!(tr = new XTDDTableRef()))2552 if (!(tr = new XTDDTableRef()))
2527 xt_throw_errno(XT_CONTEXT, XT_ENOMEM);2553 xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
@@ -2536,7 +2562,7 @@
2536 */2562 */
2537 xt_heap_reference(self, fk->co_table->dt_table);2563 xt_heap_reference(self, fk->co_table->dt_table);
25382564
2539 freer_(); // xt_unlock_rwlock(&dt_ref_lock);2565 freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
2540}2566}
25412567
2542/*2568/*
@@ -2546,8 +2572,8 @@
2546{2572{
2547 XTDDTableRef *tr, *prev_tr = NULL;2573 XTDDTableRef *tr, *prev_tr = NULL;
25482574
2549 xt_xlock_rwlock(self, &dt_ref_lock);2575 xt_recurrwlock_xlock(self, &dt_ref_lock);
2550 pushr_(xt_unlock_rwlock, &dt_ref_lock);2576 pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
25512577
2552 tr = dt_trefs;2578 tr = dt_trefs;
2553 while (tr) {2579 while (tr) {
@@ -2561,7 +2587,7 @@
2561 prev_tr = tr;2587 prev_tr = tr;
2562 tr = tr->tr_next;2588 tr = tr->tr_next;
2563 }2589 }
2564 freer_(); // xt_unlock_rwlock(&dt_ref_lock);2590 freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
2565 if (tr)2591 if (tr)
2566 tr->release(self);2592 tr->release(self);
2567}2593}
@@ -2588,8 +2614,8 @@
25882614
2589 dt->attachReference(self, fk);2615 dt->attachReference(self, fk);
25902616
2591 xt_xlock_rwlock(self, &dt_ref_lock);2617 xt_recurrwlock_xlock(self, &dt_ref_lock);
2592 pushr_(xt_unlock_rwlock, &dt_ref_lock);2618 pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
2593 /* Referenced the table, not the index!2619 /* Referenced the table, not the index!
2594 * We do this because we know that if the table is referenced, the2620 * We do this because we know that if the table is referenced, the
2595 * index will remain valid!2621 * index will remain valid!
@@ -2599,7 +2625,7 @@
2599 */2625 */
2600 xt_heap_reference(self, dt->dt_table);2626 xt_heap_reference(self, dt->dt_table);
2601 fk->fk_ref_table = dt;2627 fk->fk_ref_table = dt;
2602 freer_(); // xt_unlock_rwlock(&dt_ref_lock);2628 freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
2603 }2629 }
2604 }2630 }
2605}2631}
@@ -2626,7 +2652,7 @@
2626 /* get pointer to the referenced table, load it if needed2652 /* get pointer to the referenced table, load it if needed
2627 * cyclic references are being handled, absent table is ignored2653 * cyclic references are being handled, absent table is ignored
2628 */2654 */
2629 tab = xt_use_table_no_lock(self, db, fk->fk_ref_tab_name, /*TRUE*/FALSE, /*FALSE*/TRUE, NULL, NULL);2655 tab = xt_use_table_no_lock(self, db, fk->fk_ref_tab_name, /*TRUE*/FALSE, /*FALSE*/TRUE, NULL);
26302656
2631 if (tab) {2657 if (tab) {
2632 pushr_(xt_heap_release, tab);2658 pushr_(xt_heap_release, tab);
@@ -2663,8 +2689,8 @@
2663 XTDDTableRef *tr;2689 XTDDTableRef *tr;
2664 XTDDTable *tab;2690 XTDDTable *tab;
26652691
2666 xt_xlock_rwlock(self, &dt_ref_lock);2692 xt_recurrwlock_xlock(self, &dt_ref_lock);
2667 pushr_(xt_unlock_rwlock, &dt_ref_lock);2693 pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
26682694
2669 for (u_int i=0; i<dt_fkeys.size(); i++) {2695 for (u_int i=0; i<dt_fkeys.size(); i++) {
2670 fk = dt_fkeys.itemAt(i);2696 fk = dt_fkeys.itemAt(i);
@@ -2675,13 +2701,13 @@
2675 /* To avoid deadlock we do not hold more than2701 /* To avoid deadlock we do not hold more than
2676 * one lock at a time!2702 * one lock at a time!
2677 */2703 */
2678 freer_(); // xt_unlock_rwlock(&dt_ref_lock);2704 freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
2679 2705
2680 tab->removeReference(self, fk);2706 tab->removeReference(self, fk);
2681 xt_heap_release(self, tab->dt_table); /* We referenced the table, not the index! */2707 xt_heap_release(self, tab->dt_table); /* We referenced the table, not the index! */
2682 2708
2683 xt_xlock_rwlock(self, &dt_ref_lock);2709 xt_recurrwlock_xlock(self, &dt_ref_lock);
2684 pushr_(xt_unlock_rwlock, &dt_ref_lock);2710 pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
2685 }2711 }
2686 }2712 }
2687 }2713 }
@@ -2689,13 +2715,13 @@
2689 while (dt_trefs) {2715 while (dt_trefs) {
2690 tr = dt_trefs;2716 tr = dt_trefs;
2691 dt_trefs = tr->tr_next;2717 dt_trefs = tr->tr_next;
2692 freer_(); // xt_unlock_rwlock(&dt_ref_lock);2718 freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
2693 tr->release(self);2719 tr->release(self);
2694 xt_xlock_rwlock(self, &dt_ref_lock);2720 xt_recurrwlock_xlock(self, &dt_ref_lock);
2695 pushr_(xt_unlock_rwlock, &dt_ref_lock);2721 pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
2696 }2722 }
26972723
2698 freer_(); // xt_unlock_rwlock(&dt_ref_lock);2724 freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
2699}2725}
27002726
2701void XTDDTable::checkForeignKeys(XTThreadPtr self, bool temp_table)2727void XTDDTable::checkForeignKeys(XTThreadPtr self, bool temp_table)
@@ -2727,7 +2753,7 @@
2727 // TODO: dont close table immediately so it can be possibly reused in this loop2753 // TODO: dont close table immediately so it can be possibly reused in this loop
2728 XTTable *ref_tab;2754 XTTable *ref_tab;
27292755
2730 pushsr_(ref_tab, xt_heap_release, xt_use_table(self, fk->fk_ref_tab_name, FALSE, TRUE, NULL));2756 pushsr_(ref_tab, xt_heap_release, xt_use_table(self, fk->fk_ref_tab_name, FALSE, TRUE));
2731 if (ref_tab && !fk->checkReferencedTypes(ref_tab->tab_dic.dic_table))2757 if (ref_tab && !fk->checkReferencedTypes(ref_tab->tab_dic.dic_table))
2732 throw_();2758 throw_();
2733 freer_();2759 freer_();
@@ -2845,7 +2871,7 @@
2845 return false;2871 return false;
2846 rec_ptr = rec_buf.ib_db.db_data;2872 rec_ptr = rec_buf.ib_db.db_data;
28472873
2848 xt_slock_rwlock_ns(&dt_ref_lock);2874 xt_recurrwlock_slock_ns(&dt_ref_lock);
2849 tr = dt_trefs;2875 tr = dt_trefs;
2850 while (tr) {2876 while (tr) {
2851 if (!tr->checkReference(rec_ptr, ot->ot_thread)) {2877 if (!tr->checkReference(rec_ptr, ot->ot_thread)) {
@@ -2854,7 +2880,7 @@
2854 }2880 }
2855 tr = tr->tr_next;2881 tr = tr->tr_next;
2856 }2882 }
2857 xt_unlock_rwlock_ns(&dt_ref_lock);2883 xt_recurrwlock_unslock_ns(&dt_ref_lock);
2858 xt_ib_free(NULL, &rec_buf);2884 xt_ib_free(NULL, &rec_buf);
2859 return ok;2885 return ok;
2860}2886}
@@ -2875,7 +2901,7 @@
2875 rec_ptr = rec_buf.ib_db.db_data;2901 rec_ptr = rec_buf.ib_db.db_data;
2876 2902
2877 }2903 }
2878 xt_slock_rwlock_ns(&dt_ref_lock);2904 xt_recurrwlock_slock_ns(&dt_ref_lock);
2879 tr = dt_trefs;2905 tr = dt_trefs;
2880 while (tr) {2906 while (tr) {
2881 if (!tr->modifyRow(ot, rec_ptr, NULL, ot->ot_thread)) {2907 if (!tr->modifyRow(ot, rec_ptr, NULL, ot->ot_thread)) {
@@ -2884,7 +2910,7 @@
2884 }2910 }
2885 tr = tr->tr_next;2911 tr = tr->tr_next;
2886 }2912 }
2887 xt_unlock_rwlock_ns(&dt_ref_lock);2913 xt_recurrwlock_unslock_ns(&dt_ref_lock);
2888 xt_ib_free(NULL, &rec_buf);2914 xt_ib_free(NULL, &rec_buf);
2889 return ok;2915 return ok;
2890}2916}
@@ -2893,8 +2919,8 @@
2893{2919{
2894 XTDDTableRef *tr;2920 XTDDTableRef *tr;
28952921
2896 xt_slock_rwlock(self, &dt_ref_lock);2922 xt_recurrwlock_slock(self, &dt_ref_lock);
2897 pushr_(xt_unlock_rwlock, &dt_ref_lock);2923 pushr_(xt_recurrwlock_unslock, &dt_ref_lock);
28982924
2899 tr = dt_trefs;2925 tr = dt_trefs;
2900 while (tr) {2926 while (tr) {
@@ -2902,7 +2928,7 @@
2902 tr = tr->tr_next;2928 tr = tr->tr_next;
2903 }2929 }
29042930
2905 freer_(); // xt_unlock_rwlock(&dt_ref_lock);2931 freer_(); // xt_recurrwlock_unslock(&dt_ref_lock);
2906}2932}
29072933
2908bool XTDDTable::updateRow(XTOpenTablePtr ot, xtWord1 *before, xtWord1 *after)2934bool XTDDTable::updateRow(XTOpenTablePtr ot, xtWord1 *before, xtWord1 *after)
@@ -2932,7 +2958,7 @@
2932 ok = true;2958 ok = true;
2933 before_buf.ib_free = FALSE;2959 before_buf.ib_free = FALSE;
29342960
2935 xt_slock_rwlock_ns(&dt_ref_lock);2961 xt_recurrwlock_slock_ns(&dt_ref_lock);
2936 if ((tr = dt_trefs)) {2962 if ((tr = dt_trefs)) {
2937 if (!before) {2963 if (!before) {
2938 if (!xt_tab_load_record(ot, ot->ot_curr_rec_id, &before_buf))2964 if (!xt_tab_load_record(ot, ot->ot_curr_rec_id, &before_buf))
@@ -2948,7 +2974,7 @@
2948 tr = tr->tr_next;2974 tr = tr->tr_next;
2949 }2975 }
2950 }2976 }
2951 xt_unlock_rwlock_ns(&dt_ref_lock);2977 xt_recurrwlock_unslock_ns(&dt_ref_lock);
2952 2978
2953 xt_ib_free(NULL, &before_buf);2979 xt_ib_free(NULL, &before_buf);
2954 return ok;2980 return ok;
29552981
=== modified file 'storage/pbxt/src/datadic_xt.h'
--- storage/pbxt/src/datadic_xt.h 2009-08-18 07:46:53 +0000
+++ storage/pbxt/src/datadic_xt.h 2010-05-07 08:52:27 +0000
@@ -45,7 +45,6 @@
45#define XT_DD_KEY_PRIMARY 245#define XT_DD_KEY_PRIMARY 2
46#define XT_DD_KEY_FOREIGN 346#define XT_DD_KEY_FOREIGN 3
4747
48#define XT_KEY_ACTION_DEFAULT 0
49#define XT_KEY_ACTION_RESTRICT 148#define XT_KEY_ACTION_RESTRICT 1
50#define XT_KEY_ACTION_CASCADE 249#define XT_KEY_ACTION_CASCADE 2
51#define XT_KEY_ACTION_SET_NULL 350#define XT_KEY_ACTION_SET_NULL 3
@@ -259,7 +258,7 @@
259 XTList<XTDDColumn> dt_cols;258 XTList<XTDDColumn> dt_cols;
260 XTList<XTDDIndex> dt_indexes;259 XTList<XTDDIndex> dt_indexes;
261260
262 xt_rwlock_type dt_ref_lock; /* The lock for adding and using references. */261 XTRecurRWLockRec dt_ref_lock; /* The lock for adding and using references. */
263 XTList<XTDDForeignKey> dt_fkeys; /* The foreign keys on this table. */262 XTList<XTDDForeignKey> dt_fkeys; /* The foreign keys on this table. */
264 XTDDTableRef *dt_trefs; /* A list of tables that reference this table. */263 XTDDTableRef *dt_trefs; /* A list of tables that reference this table. */
265264
266265
=== modified file 'storage/pbxt/src/datalog_xt.cc'
--- storage/pbxt/src/datalog_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/datalog_xt.cc 2010-05-07 08:52:27 +0000
@@ -1148,6 +1148,11 @@
1148xtBool XTDataLogBuffer::dlb_close_log(XTThreadPtr thread)1148xtBool XTDataLogBuffer::dlb_close_log(XTThreadPtr thread)
1149{1149{
1150 if (dlb_data_log) {1150 if (dlb_data_log) {
1151 if (dlb_data_log->dlf_log_file) {
1152 if (!dl_write_log_header(dlb_data_log, dlb_data_log->dlf_log_file, 0, thread))
1153 return FAILED;
1154 }
1155
1151 /* Flush and commit the data in the old log: */1156 /* Flush and commit the data in the old log: */
1152 if (!dlb_flush_log(TRUE, thread))1157 if (!dlb_flush_log(TRUE, thread))
1153 return FAILED;1158 return FAILED;
@@ -1952,7 +1957,7 @@
1952 log_rec.xl_status_1 = XT_LOG_ENT_DEL_LOG;1957 log_rec.xl_status_1 = XT_LOG_ENT_DEL_LOG;
1953 log_rec.xl_checksum_1 = XT_CHECKSUM_1(data_log->dlf_log_id);1958 log_rec.xl_checksum_1 = XT_CHECKSUM_1(data_log->dlf_log_id);
1954 XT_SET_DISK_4(log_rec.xl_log_id_4, data_log->dlf_log_id);1959 XT_SET_DISK_4(log_rec.xl_log_id_4, data_log->dlf_log_id);
1955 if (!xt_xlog_log_data(self, sizeof(XTXactNewLogEntryDRec), (XTXactLogBufferDPtr) &log_rec, TRUE)) {1960 if (!xt_xlog_log_data(self, sizeof(XTXactNewLogEntryDRec), (XTXactLogBufferDPtr) &log_rec, XT_XLOG_WRITE_AND_FLUSH)) {
1956 db->db_datalogs.dls_set_log_state(data_log, XT_DL_TO_COMPACT);1961 db->db_datalogs.dls_set_log_state(data_log, XT_DL_TO_COMPACT);
1957 xt_throw(self);1962 xt_throw(self);
1958 }1963 }
19591964
=== modified file 'storage/pbxt/src/filesys_xt.h'
--- storage/pbxt/src/filesys_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/filesys_xt.h 2010-05-07 08:52:27 +0000
@@ -119,7 +119,7 @@
119#define FILE_MAP_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)119#define FILE_MAP_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
120#define FILE_MAP_FREE_LOCK(s, i) xt_spinxslock_free(s, i) 120#define FILE_MAP_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
121#define FILE_MAP_READ_LOCK(i, o) xt_spinxslock_slock(i, o)121#define FILE_MAP_READ_LOCK(i, o) xt_spinxslock_slock(i, o)
122#define FILE_MAP_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, o)122#define FILE_MAP_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, FALSE, o)
123#define FILE_MAP_UNLOCK(i, o) xt_spinxslock_unlock(i, o)123#define FILE_MAP_UNLOCK(i, o) xt_spinxslock_unlock(i, o)
124#endif124#endif
125125
126126
=== modified file 'storage/pbxt/src/ha_pbxt.cc'
--- storage/pbxt/src/ha_pbxt.cc 2010-01-06 21:27:53 +0000
+++ storage/pbxt/src/ha_pbxt.cc 2010-05-07 08:52:27 +0000
@@ -113,6 +113,7 @@
113static int pbxt_recover(handlerton *hton, XID *xid_list, uint len);113static int pbxt_recover(handlerton *hton, XID *xid_list, uint len);
114static int pbxt_commit_by_xid(handlerton *hton, XID *xid);114static int pbxt_commit_by_xid(handlerton *hton, XID *xid);
115static int pbxt_rollback_by_xid(handlerton *hton, XID *xid);115static int pbxt_rollback_by_xid(handlerton *hton, XID *xid);
116static int pbxt_start_consistent_snapshot(handlerton *hton, THD *thd);
116#endif117#endif
117static void ha_aquire_exclusive_use(XTThreadPtr self, XTSharePtr share, ha_pbxt *mine);118static void ha_aquire_exclusive_use(XTThreadPtr self, XTSharePtr share, ha_pbxt *mine);
118static void ha_release_exclusive_use(XTThreadPtr self, XTSharePtr share);119static void ha_release_exclusive_use(XTThreadPtr self, XTSharePtr share);
@@ -286,7 +287,7 @@
286 char func_buf[50], *ptr;287 char func_buf[50], *ptr;
287 XTThreadPtr thread = xt_get_self(); 288 XTThreadPtr thread = xt_get_self();
288289
289 if ((ptr = strchr(function, '('))) {290 if ((ptr = const_cast<char *>(strchr(function, '(')))) {
290 ptr--;291 ptr--;
291 while (ptr > function) {292 while (ptr > function) {
292 if (!(isalnum(*ptr) || *ptr == '_'))293 if (!(isalnum(*ptr) || *ptr == '_'))
@@ -345,13 +346,13 @@
345 return xt_ht_casehash(share->sh_table_path->ps_path);346 return xt_ht_casehash(share->sh_table_path->ps_path);
346}347}
347348
348static void ha_open_share(XTThreadPtr self, XTShareRec *share, xtBool *tabled_opened)349static void ha_open_share(XTThreadPtr self, XTShareRec *share)
349{350{
350 xt_lock_mutex(self, (xt_mutex_type *) share->sh_ex_mutex);351 xt_lock_mutex(self, (xt_mutex_type *) share->sh_ex_mutex);
351 pushr_(xt_unlock_mutex, share->sh_ex_mutex);352 pushr_(xt_unlock_mutex, share->sh_ex_mutex);
352353
353 if (!share->sh_table) {354 if (!share->sh_table) {
354 share->sh_table = xt_use_table(self, share->sh_table_path, FALSE, FALSE, tabled_opened);355 share->sh_table = xt_use_table(self, share->sh_table_path, FALSE, FALSE);
355 share->sh_dic_key_count = share->sh_table->tab_dic.dic_key_count;356 share->sh_dic_key_count = share->sh_table->tab_dic.dic_key_count;
356 share->sh_dic_keys = share->sh_table->tab_dic.dic_keys;357 share->sh_dic_keys = share->sh_table->tab_dic.dic_keys;
357 share->sh_recalc_selectivity = FALSE;358 share->sh_recalc_selectivity = FALSE;
@@ -411,7 +412,7 @@
411 * This structure contains information that is common to all handles.412 * This structure contains information that is common to all handles.
412 * (i.e. it is table specific).413 * (i.e. it is table specific).
413 */414 */
414static XTSharePtr ha_get_share(XTThreadPtr self, const char *table_path, bool open_table, xtBool *tabled_opened)415static XTSharePtr ha_get_share(XTThreadPtr self, const char *table_path, bool open_table)
415{416{
416 XTShareRec *share;417 XTShareRec *share;
417418
@@ -433,7 +434,7 @@
433 share->sh_table_path = (XTPathStrPtr) xt_dup_string(self, table_path);434 share->sh_table_path = (XTPathStrPtr) xt_dup_string(self, table_path);
434435
435 if (open_table)436 if (open_table)
436 ha_open_share(self, share, tabled_opened);437 ha_open_share(self, share);
437438
438 popr_(); // Discard ha_cleanup_share(share);439 popr_(); // Discard ha_cleanup_share(share);
439440
@@ -476,6 +477,25 @@
476 return removed;477 return removed;
477}478}
478479
480static inline void thd_init_xact(THD *thd, XTThreadPtr self, bool set_table_trans)
481{
482 self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ;
483 self->st_ignore_fkeys = (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) != 0;
484 self->st_auto_commit = (thd_test_options(thd,(OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0;
485 if (set_table_trans) {
486#ifdef DRIZZLED
487 self->st_table_trans = FALSE;
488#else
489 self->st_table_trans = thd_sql_command(thd) == SQLCOM_LOCK_TABLES;
490#endif
491 }
492 self->st_abort_trans = FALSE;
493 self->st_stat_ended = FALSE;
494 self->st_stat_trans = FALSE;
495 XT_PRINT0(self, "xt_xn_begin\n");
496 xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
497}
498
479/*499/*
480 * -----------------------------------------------------------------------500 * -----------------------------------------------------------------------
481 * PUBLIC FUNCTIONS501 * PUBLIC FUNCTIONS
@@ -1146,6 +1166,7 @@
1146 pbxt_hton->show_status = pbxt_show_status;1166 pbxt_hton->show_status = pbxt_show_status;
1147 pbxt_hton->flags = HTON_NO_FLAGS; /* HTON_CAN_RECREATE - Without this flags TRUNCATE uses delete_all_rows() */1167 pbxt_hton->flags = HTON_NO_FLAGS; /* HTON_CAN_RECREATE - Without this flags TRUNCATE uses delete_all_rows() */
1148 pbxt_hton->slot = (uint)-1; /* assign invald value, so we know when it's inited later */1168 pbxt_hton->slot = (uint)-1; /* assign invald value, so we know when it's inited later */
1169 pbxt_hton->start_consistent_snapshot = pbxt_start_consistent_snapshot;
1149#if defined(MYSQL_SUPPORTS_BACKUP) && defined(XT_ENABLE_ONLINE_BACKUP)1170#if defined(MYSQL_SUPPORTS_BACKUP) && defined(XT_ENABLE_ONLINE_BACKUP)
1150 pbxt_hton->get_backup_engine = pbxt_backup_engine;1171 pbxt_hton->get_backup_engine = pbxt_backup_engine;
1151#endif1172#endif
@@ -1175,13 +1196,8 @@
1175 * +1 Temporary thread (e.g. TempForClose, TempForEnd)1196 * +1 Temporary thread (e.g. TempForClose, TempForEnd)
1176 */1197 */
1177#ifndef DRIZZLED1198#ifndef DRIZZLED
1178 if (pbxt_max_threads == 0) {1199 if (pbxt_max_threads == 0)
1179 // Embedded server sets max_connections=11200 pbxt_max_threads = max_connections + 7;
1180 if (max_connections > 1)
1181 pbxt_max_threads = max_connections + 7;
1182 else
1183 pbxt_max_threads = 100;
1184 }
1185#endif1201#endif
1186 self = xt_init_threading(pbxt_max_threads); /* Create the main self: */1202 self = xt_init_threading(pbxt_max_threads); /* Create the main self: */
1187 if (!self)1203 if (!self)
@@ -1294,7 +1310,7 @@
1294 #6 0x000debe1 in THD::THD at sql_class.cc:6311310 #6 0x000debe1 in THD::THD at sql_class.cc:631
1295 #7 0x00e207a4 in myxt_create_thread at myxt_xt.cc:26661311 #7 0x00e207a4 in myxt_create_thread at myxt_xt.cc:2666
1296 #8 0x00e3134b in tabc_fr_run_thread at tabcache_xt.cc:9821312 #8 0x00e3134b in tabc_fr_run_thread at tabcache_xt.cc:982
1297 #9 0x00e422ca in thr_main_pbxt at thread_xt.cc:10061313 #9 0x00e422ca in xt_thread_main at thread_xt.cc:1006
1298 #10 0x91ff7c55 in _pthread_start1314 #10 0x91ff7c55 in _pthread_start
1299 #11 0x91ff7b12 in thread_start1315 #11 0x91ff7b12 in thread_start
1300 *1316 *
@@ -1427,8 +1443,43 @@
1427 * 1443 *
1428 * 3. If in BEGIN/END we must call ha_rollback() if we abort the transaction1444 * 3. If in BEGIN/END we must call ha_rollback() if we abort the transaction
1429 * internally.1445 * internally.
1446 *
1447 * NOTE ON CONSISTENT SNAPSHOTS:
1448 *
1449 * PBXT itself doesn't need this functiona as its transaction mechanism provides
1450 * consistent snapshots for all transactions by default. This function is needed
1451 * only for multi-engine cases like this:
1452 *
1453 * CREATE TABLE t1 ... ENGINE=INNODB
1454 * CREATE TABLE t2 ... ENGINE=PBXT
1455 * START TRANSACTION WITH CONSISTENT SNAPSHOT
1456 * SELECT * FROM t1 <-- at this point we need to know about the snapshot
1430 */1457 */
14311458
1459static int pbxt_start_consistent_snapshot(handlerton *hton, THD *thd)
1460{
1461 int err = 0;
1462 XTThreadPtr self = ha_set_current_thread(thd, &err);
1463
1464 if (!self->st_database && pbxt_database) {
1465 xt_ha_open_database_of_table(self, (XTPathStrPtr) NULL);
1466 }
1467
1468 thd_init_xact(thd, self, true);
1469
1470 if (xt_xn_begin(self)) {
1471 trans_register_ha(thd, TRUE, hton);
1472 } else {
1473 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
1474 }
1475
1476 /*
1477 * As of MySQL 5.1.41 the return value is not checked, so the server might assume
1478 * everything is fine even it isn't. InnoDB returns 0 on success.
1479 */
1480 return err;
1481}
1482
1432/*1483/*
1433 * Commit the PBXT transaction of the given thread.1484 * Commit the PBXT transaction of the given thread.
1434 * thd is the MySQL thread structure.1485 * thd is the MySQL thread structure.
@@ -1557,7 +1608,7 @@
1557 return err;1608 return err;
1558}1609}
15591610
1560static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, const char *thread_name, int *err)1611static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, char *thread_name, int *err)
1561{1612{
1562 THD *thd;1613 THD *thd;
1563 XTThreadPtr self = NULL;1614 XTThreadPtr self = NULL;
@@ -1870,7 +1921,6 @@
1870 THD *thd = current_thd;1921 THD *thd = current_thd;
1871 int err = 0;1922 int err = 0;
1872 XTThreadPtr self; 1923 XTThreadPtr self;
1873 xtBool tabled_opened = FALSE;
18741924
1875 if (!(self = ha_set_current_thread(thd, &err)))1925 if (!(self = ha_set_current_thread(thd, &err)))
1876 return xt_ha_pbxt_to_mysql_error(err);1926 return xt_ha_pbxt_to_mysql_error(err);
@@ -1878,24 +1928,30 @@
1878 try_(a) {1928 try_(a) {
1879 xt_ha_open_database_of_table(self, pb_share->sh_table_path);1929 xt_ha_open_database_of_table(self, pb_share->sh_table_path);
18801930
1881 ha_open_share(self, pb_share, &tabled_opened);1931 ha_open_share(self, pb_share);
18821932
1883 if (!(pb_open_tab = xt_db_open_table_using_tab(pb_share->sh_table, self)))1933 if (!(pb_open_tab = xt_db_open_table_using_tab(pb_share->sh_table, self)))
1884 xt_throw(self);1934 xt_throw(self);
1885 pb_open_tab->ot_thread = self;1935 pb_open_tab->ot_thread = self;
18861936
1887 if (tabled_opened) {1937 /* {TABLE-STATS}
1938 * We no longer use the information that a table
1939 * was opened in order to know when to calculate
1940 * statistics.
1941 */
1942 if (!pb_open_tab->ot_table->tab_ind_stat_calc_time) {
1888#ifdef LOAD_TABLE_ON_OPEN1943#ifdef LOAD_TABLE_ON_OPEN
1889 xt_tab_load_table(self, pb_open_tab);1944 xt_tab_load_table(self, pb_open_tab);
1890#else1945#else
1891 xt_tab_load_row_pointers(self, pb_open_tab);1946 xt_tab_load_row_pointers(self, pb_open_tab);
1892#endif1947#endif
1893 xt_ind_set_index_selectivity(self, pb_open_tab);1948 xt_ind_set_index_selectivity(pb_open_tab, self);
1894 /* If the number of rows is less than 150 we will recalculate the1949 /* If the number of rows is less than 150 we will recalculate the
1895 * selectity of the indices, as soon as the number of rows1950 * selectity of the indices, as soon as the number of rows
1896 * exceeds 200 (see [**])1951 * exceeds 200 (see [**])
1897 */1952 */
1898 pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;1953 /* {FREE-ROWS-BAD} */
1954 pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
1899 }1955 }
19001956
1901 /* I am not doing this anymore because it was only required1957 /* I am not doing this anymore because it was only required
@@ -2269,7 +2325,6 @@
2269 THD *thd = current_thd;2325 THD *thd = current_thd;
2270 int err = 0;2326 int err = 0;
2271 XTThreadPtr self;2327 XTThreadPtr self;
2272 xtBool tabled_opened = FALSE;
22732328
2274 ref_length = XT_RECORD_OFFS_SIZE;2329 ref_length = XT_RECORD_OFFS_SIZE;
22752330
@@ -2282,28 +2337,30 @@
2282 try_(a) {2337 try_(a) {
2283 xt_ha_open_database_of_table(self, (XTPathStrPtr) table_path);2338 xt_ha_open_database_of_table(self, (XTPathStrPtr) table_path);
22842339
2285 pb_share = ha_get_share(self, table_path, true, &tabled_opened);2340 pb_share = ha_get_share(self, table_path, false);
2286 ha_add_to_handler_list(self, pb_share, this);2341 ha_add_to_handler_list(self, pb_share, this);
2287 if (pb_share->sh_table_lock) {2342 if (pb_share->sh_table_lock) {
2288 if (!ha_wait_for_shared_use(this, pb_share))2343 if (!ha_wait_for_shared_use(this, pb_share))
2289 xt_throw(self);2344 xt_throw(self);
2290 }2345 }
22912346
2292 ha_open_share(self, pb_share, &tabled_opened);2347 ha_open_share(self, pb_share);
22932348
2294 thr_lock_data_init(&pb_share->sh_lock, &pb_lock, NULL);2349 thr_lock_data_init(&pb_share->sh_lock, &pb_lock, NULL);
2295 if (!(pb_open_tab = xt_db_open_table_using_tab(pb_share->sh_table, self)))2350 if (!(pb_open_tab = xt_db_open_table_using_tab(pb_share->sh_table, self)))
2296 xt_throw(self);2351 xt_throw(self);
2297 pb_open_tab->ot_thread = self;2352 pb_open_tab->ot_thread = self;
22982353
2299 if (tabled_opened) {2354 /* {TABLE-STATS} */
2355 if (!pb_open_tab->ot_table->tab_ind_stat_calc_time) {
2300#ifdef LOAD_TABLE_ON_OPEN2356#ifdef LOAD_TABLE_ON_OPEN
2301 xt_tab_load_table(self, pb_open_tab);2357 xt_tab_load_table(self, pb_open_tab);
2302#else2358#else
2303 xt_tab_load_row_pointers(self, pb_open_tab);2359 xt_tab_load_row_pointers(self, pb_open_tab);
2304#endif2360#endif
2305 xt_ind_set_index_selectivity(self, pb_open_tab);2361 xt_ind_set_index_selectivity(pb_open_tab, self);
2306 pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;2362 /* {FREE-ROWS-BAD} */
2363 pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
2307 }2364 }
23082365
2309 init_auto_increment(0);2366 init_auto_increment(0);
@@ -2411,7 +2468,7 @@
2411 self->st_abort_trans = FALSE;2468 self->st_abort_trans = FALSE;
2412 self->st_stat_ended = FALSE;2469 self->st_stat_ended = FALSE;
2413 self->st_stat_trans = FALSE;2470 self->st_stat_trans = FALSE;
2414 self->st_is_update = FALSE;2471 self->st_is_update = NULL;
2415 if (!xt_xn_begin(self)) {2472 if (!xt_xn_begin(self)) {
2416 xt_spinlock_unlock(&tab->tab_ainc_lock);2473 xt_spinlock_unlock(&tab->tab_ainc_lock);
2417 xt_throw(self);2474 xt_throw(self);
@@ -2651,8 +2708,14 @@
2651 * and if it gets dup-key error it tries UPDATE, so the same row can be overwriten multiple 2708 * and if it gets dup-key error it tries UPDATE, so the same row can be overwriten multiple
2652 * times within the same statement2709 * times within the same statement
2653 */2710 */
2654 if (err == HA_ERR_FOUND_DUPP_KEY && pb_open_tab->ot_thread->st_is_update)2711 if (err == HA_ERR_FOUND_DUPP_KEY && pb_open_tab->ot_thread->st_is_update) {
2655 pb_open_tab->ot_thread->st_update_id++;2712 /* Pop the update stack: */
2713 //pb_open_tab->ot_thread->st_update_id++;
2714 XTOpenTablePtr curr = pb_open_tab->ot_thread->st_is_update;
2715
2716 pb_open_tab->ot_thread->st_is_update = curr->ot_prev_update;
2717 curr->ot_prev_update = NULL;
2718 }
2656 }2719 }
26572720
2658 done:2721 done:
@@ -2720,9 +2783,12 @@
27202783
2721 xt_xlog_check_long_writer(self);2784 xt_xlog_check_long_writer(self);
27222785
2723 if (!self->st_is_update) {2786 /* {UPDATE-STACK} */
2724 self->st_is_update = TRUE;2787 if (self->st_is_update != pb_open_tab) {
2725 self->st_update_id++;2788 /* Push the update stack: */
2789 pb_open_tab->ot_prev_update = self->st_is_update;
2790 self->st_is_update = pb_open_tab;
2791 pb_open_tab->ot_update_id++;
2726 }2792 }
27272793
2728 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)2794 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
@@ -3120,6 +3186,7 @@
3120 active_index = idx;3186 active_index = idx;
31213187
3122 if (pb_open_tab->ot_table->tab_dic.dic_disable_index) {3188 if (pb_open_tab->ot_table->tab_dic.dic_disable_index) {
3189 active_index = MAX_KEY;
3123 xt_tab_set_index_error(pb_open_tab->ot_table);3190 xt_tab_set_index_error(pb_open_tab->ot_table);
3124 return ha_log_pbxt_thread_error_for_mysql(pb_ignore_dup_key);3191 return ha_log_pbxt_thread_error_for_mysql(pb_ignore_dup_key);
3125 }3192 }
@@ -3270,6 +3337,10 @@
3270 int prefix = 0;3337 int prefix = 0;
3271 XTIdxSearchKeyRec search_key;3338 XTIdxSearchKeyRec search_key;
32723339
3340 if (idx == MAX_KEY) {
3341 err = HA_ERR_WRONG_INDEX;
3342 goto done;
3343 }
3273#ifdef XT_TRACK_RETURNED_ROWS3344#ifdef XT_TRACK_RETURNED_ROWS
3274 ha_start_scan(pb_open_tab, idx);3345 ha_start_scan(pb_open_tab, idx);
3275#endif3346#endif
@@ -3320,6 +3391,7 @@
3320 ha_return_row(pb_open_tab, idx);3391 ha_return_row(pb_open_tab, idx);
3321#endif3392#endif
3322 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));3393 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));
3394 done:
3323 if (err)3395 if (err)
3324 table->status = STATUS_NOT_FOUND;3396 table->status = STATUS_NOT_FOUND;
3325 else {3397 else {
@@ -3364,6 +3436,10 @@
3364 //statistic_increment(ha_read_next_count,&LOCK_status);3436 //statistic_increment(ha_read_next_count,&LOCK_status);
3365 ASSERT_NS(pb_ex_in_use);3437 ASSERT_NS(pb_ex_in_use);
33663438
3439 if (active_index == MAX_KEY) {
3440 err = HA_ERR_WRONG_INDEX;
3441 goto done;
3442 }
3367 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];3443 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];
33683444
3369 if (!xt_idx_next(pb_open_tab, ind, NULL))3445 if (!xt_idx_next(pb_open_tab, ind, NULL))
@@ -3376,6 +3452,7 @@
3376 if (!err)3452 if (!err)
3377 ha_return_row(pb_open_tab, active_index);3453 ha_return_row(pb_open_tab, active_index);
3378#endif3454#endif
3455 done:
3379 if (err)3456 if (err)
3380 table->status = STATUS_NOT_FOUND;3457 table->status = STATUS_NOT_FOUND;
3381 else {3458 else {
@@ -3406,6 +3483,10 @@
3406 //statistic_increment(ha_read_next_count,&LOCK_status);3483 //statistic_increment(ha_read_next_count,&LOCK_status);
3407 ASSERT_NS(pb_ex_in_use);3484 ASSERT_NS(pb_ex_in_use);
34083485
3486 if (active_index == MAX_KEY) {
3487 err = HA_ERR_WRONG_INDEX;
3488 goto done;
3489 }
3409 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];3490 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];
34103491
3411 search_key.sk_key_value.sv_flags = HA_READ_KEY_EXACT;3492 search_key.sk_key_value.sv_flags = HA_READ_KEY_EXACT;
@@ -3425,6 +3506,7 @@
3425 if (!err)3506 if (!err)
3426 ha_return_row(pb_open_tab, active_index);3507 ha_return_row(pb_open_tab, active_index);
3427#endif3508#endif
3509 done:
3428 if (err)3510 if (err)
3429 table->status = STATUS_NOT_FOUND;3511 table->status = STATUS_NOT_FOUND;
3430 else {3512 else {
@@ -3446,6 +3528,10 @@
3446 //statistic_increment(ha_read_prev_count,&LOCK_status);3528 //statistic_increment(ha_read_prev_count,&LOCK_status);
3447 ASSERT_NS(pb_ex_in_use);3529 ASSERT_NS(pb_ex_in_use);
34483530
3531 if (active_index == MAX_KEY) {
3532 err = HA_ERR_WRONG_INDEX;
3533 goto done;
3534 }
3449 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];3535 ind = (XTIndexPtr) pb_share->sh_dic_keys[active_index];
34503536
3451 if (!xt_idx_prev(pb_open_tab, ind, NULL))3537 if (!xt_idx_prev(pb_open_tab, ind, NULL))
@@ -3458,6 +3544,7 @@
3458 if (!err)3544 if (!err)
3459 ha_return_row(pb_open_tab, active_index);3545 ha_return_row(pb_open_tab, active_index);
3460#endif3546#endif
3547 done:
3461 if (err)3548 if (err)
3462 table->status = STATUS_NOT_FOUND;3549 table->status = STATUS_NOT_FOUND;
3463 else {3550 else {
@@ -3480,6 +3567,18 @@
3480 //statistic_increment(ha_read_first_count,&LOCK_status);3567 //statistic_increment(ha_read_first_count,&LOCK_status);
3481 ASSERT_NS(pb_ex_in_use);3568 ASSERT_NS(pb_ex_in_use);
34823569
3570 /* This is required because MySQL ignores the error returned
3571 * init init_index sometimes, for example:
3572 *
3573 * if (!table->file->inited)
3574 * table->file->ha_index_init(tab->index, tab->sorted);
3575 * if ((error=tab->table->file->index_first(tab->table->record[0])))
3576 */
3577 if (active_index == MAX_KEY) {
3578 err = HA_ERR_WRONG_INDEX;
3579 goto done;
3580 }
3581
3483#ifdef XT_TRACK_RETURNED_ROWS3582#ifdef XT_TRACK_RETURNED_ROWS
3484 ha_start_scan(pb_open_tab, active_index);3583 ha_start_scan(pb_open_tab, active_index);
3485#endif3584#endif
@@ -3498,6 +3597,7 @@
3498 if (!err)3597 if (!err)
3499 ha_return_row(pb_open_tab, active_index);3598 ha_return_row(pb_open_tab, active_index);
3500#endif3599#endif
3600 done:
3501 if (err)3601 if (err)
3502 table->status = STATUS_NOT_FOUND;3602 table->status = STATUS_NOT_FOUND;
3503 else {3603 else {
@@ -3520,6 +3620,11 @@
3520 //statistic_increment(ha_read_last_count,&LOCK_status);3620 //statistic_increment(ha_read_last_count,&LOCK_status);
3521 ASSERT_NS(pb_ex_in_use);3621 ASSERT_NS(pb_ex_in_use);
35223622
3623 if (active_index == MAX_KEY) {
3624 err = HA_ERR_WRONG_INDEX;
3625 goto done;
3626 }
3627
3523#ifdef XT_TRACK_RETURNED_ROWS3628#ifdef XT_TRACK_RETURNED_ROWS
3524 ha_start_scan(pb_open_tab, active_index);3629 ha_start_scan(pb_open_tab, active_index);
3525#endif3630#endif
@@ -3538,6 +3643,7 @@
3538 if (!err)3643 if (!err)
3539 ha_return_row(pb_open_tab, active_index);3644 ha_return_row(pb_open_tab, active_index);
3540#endif3645#endif
3646 done:
3541 if (err)3647 if (err)
3542 table->status = STATUS_NOT_FOUND;3648 table->status = STATUS_NOT_FOUND;
3543 else {3649 else {
@@ -3825,8 +3931,34 @@
38253931
3826 if ((ot = pb_open_tab)) {3932 if ((ot = pb_open_tab)) {
3827 if (flag & HA_STATUS_VARIABLE) {3933 if (flag & HA_STATUS_VARIABLE) {
3828 stats.deleted = ot->ot_table->tab_row_fnum;3934 /* {FREE-ROWS-BAD}
3829 stats.records = (ha_rows) (ot->ot_table->tab_row_eof_id - 1 - stats.deleted);3935 * Free row count is not reliable, so ignore it.
3936 * The problem is if tab_row_fnum > tab_row_eof_id - 1 then
3937 * we have a very bad result.
3938 *
3939 * If stats.records+EXTRA_RECORDS == 0 as returned by
3940 * estimate_rows_upper_bound(), then filesort will crash here:
3941 *
3942 * make_sortkey(param,sort_keys[idx++],ref_pos);
3943 *
3944 * #0 0x000bf69c in Field_long::sort_string at field.cc:3766
3945 * #1 0x0022e1f1 in make_sortkey at filesort.cc:769
3946 * #2 0x0022f1cf in find_all_keys at filesort.cc:619
3947 * #3 0x00230eec in filesort at filesort.cc:243
3948 * #4 0x001b9d89 in mysql_update at sql_update.cc:415
3949 * #5 0x0010db12 in mysql_execute_command at sql_parse.cc:2959
3950 * #6 0x0011480d in mysql_parse at sql_parse.cc:5787
3951 * #7 0x00115afb in dispatch_command at sql_parse.cc:1200
3952 * #8 0x00116de2 in do_command at sql_parse.cc:857
3953 * #9 0x00101ee4 in handle_one_connection at sql_connect.cc:1115
3954 *
3955 * The problem is that sort_keys is allocated to handle just 1 vector.
3956 * Sorting one vector crashes. Although I could not find a check for
3957 * the actual number of vectors. But it must assume that it has at
3958 * least EXTRA_RECORDS vectors.
3959 */
3960 stats.deleted = /* ot->ot_table->tab_row_fnum */ 0;
3961 stats.records = (ha_rows) (ot->ot_table->tab_row_eof_id - 1 /* - stats.deleted */);
3830 stats.data_file_length = xt_rec_id_to_rec_offset(ot->ot_table, ot->ot_table->tab_rec_eof_id);3962 stats.data_file_length = xt_rec_id_to_rec_offset(ot->ot_table, ot->ot_table->tab_rec_eof_id);
3831 stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof);3963 stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof);
3832 stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size;3964 stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size;
@@ -4454,11 +4586,13 @@
4454 }4586 }
44554587
4456 if (pb_share->sh_recalc_selectivity) {4588 if (pb_share->sh_recalc_selectivity) {
4457 if ((pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) >= 200) {4589 /* {FREE-ROWS-BAD} */
4590 if ((pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) >= 200) {
4458 /* [**] */4591 /* [**] */
4459 pb_share->sh_recalc_selectivity = FALSE;4592 pb_share->sh_recalc_selectivity = FALSE;
4460 xt_ind_set_index_selectivity(self, pb_open_tab);4593 xt_ind_set_index_selectivity(pb_open_tab, self);
4461 pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150;4594 /* {FREE-ROWS-BAD} */
4595 pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150;
4462 }4596 }
4463 }4597 }
4464 }4598 }
@@ -4497,7 +4631,7 @@
4497 if (!pb_share->sh_table) {4631 if (!pb_share->sh_table) {
4498 xt_ha_open_database_of_table(self, pb_share->sh_table_path);4632 xt_ha_open_database_of_table(self, pb_share->sh_table_path);
44994633
4500 ha_open_share(self, pb_share, NULL);4634 ha_open_share(self, pb_share);
4501 }4635 }
4502 }4636 }
4503 catch_(a) {4637 catch_(a) {
@@ -4603,8 +4737,8 @@
4603 cont_(b);4737 cont_(b);
4604 }4738 }
46054739
4606 /* See {IS-UPDATE-STAT} */4740 /* See {IS-UPDATE-STAT} nad {UPDATE-STACK} */
4607 self->st_is_update = FALSE;4741 self->st_is_update = NULL;
46084742
4609 /* Auto begin a transaction (if one is not already running): */4743 /* Auto begin a transaction (if one is not already running): */
4610 if (!self->st_xact_data) {4744 if (!self->st_xact_data) {
@@ -4612,19 +4746,8 @@
4612 (void) ASSERT_NS(ISO_READ_UNCOMMITTED == XT_XACT_UNCOMMITTED_READ);4746 (void) ASSERT_NS(ISO_READ_UNCOMMITTED == XT_XACT_UNCOMMITTED_READ);
4613 (void) ASSERT_NS(ISO_SERIALIZABLE == XT_XACT_SERIALIZABLE);4747 (void) ASSERT_NS(ISO_SERIALIZABLE == XT_XACT_SERIALIZABLE);
46144748
4615 self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ;4749 thd_init_xact(thd, self, true);
4616 self->st_ignore_fkeys = (thd_test_options(thd,OPTION_NO_FOREIGN_KEY_CHECKS)) != 0;4750
4617 self->st_auto_commit = (thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0;
4618#ifdef DRIZZLED
4619 self->st_table_trans = FALSE;
4620#else
4621 self->st_table_trans = thd_sql_command(thd) == SQLCOM_LOCK_TABLES;
4622#endif
4623 self->st_abort_trans = FALSE;
4624 self->st_stat_ended = FALSE;
4625 self->st_stat_trans = FALSE;
4626 XT_PRINT0(self, "xt_xn_begin\n");
4627 xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
4628 if (!xt_xn_begin(self)) {4751 if (!xt_xn_begin(self)) {
4629 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);4752 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
4630 pb_ex_in_use = 0;4753 pb_ex_in_use = 0;
@@ -4847,19 +4970,27 @@
4847 * are nested within an open close of the select t14970 * are nested within an open close of the select t1
4848 * statement.4971 * statement.
4849 */4972 */
4850 self->st_is_update = FALSE;4973 /* {UPDATE-STACK}
4974 * Add to this I add the following:
4975 * A trigger in the middle of an update also causes nested
4976 * statements. If I reset st_is_update, then then
4977 * when the trigger returns the system thinks we
4978 * are in a different update statement, and may
4979 * update the same row again.
4980 */
4981 if (self->st_is_update == pb_open_tab) {
4982 /* Pop the update stack: */
4983 XTOpenTablePtr curr = pb_open_tab->ot_thread->st_is_update;
4984
4985 pb_open_tab->ot_thread->st_is_update = curr->ot_prev_update;
4986 curr->ot_prev_update = NULL;
4987 }
48514988
4852 /* See comment {START-TRANS} */4989 /* See comment {START-TRANS} */
4853 if (!self->st_xact_data) {4990 if (!self->st_xact_data) {
4854 self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ;4991
4855 self->st_ignore_fkeys = (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) != 0;4992 thd_init_xact(thd, self, false);
4856 self->st_auto_commit = (thd_test_options(thd,(OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0;4993
4857 /* self->st_table_trans = not set here! */
4858 self->st_abort_trans = FALSE;
4859 self->st_stat_ended = FALSE;
4860 self->st_stat_trans = FALSE;
4861 XT_PRINT0(self, "xt_xn_begin\n");
4862 xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
4863 if (!xt_xn_begin(self)) {4994 if (!xt_xn_begin(self)) {
4864 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);4995 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
4865 goto complete;4996 goto complete;
@@ -4915,6 +5046,18 @@
4915 */5046 */
4916THR_LOCK_DATA **ha_pbxt::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type)5047THR_LOCK_DATA **ha_pbxt::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type)
4917{5048{
5049 /*
5050 * TL_READ means concurrent INSERTs are allowed. This is a problem as in this mode
5051 * PBXT is not compatible with MyISAM which allows INSERTs but isolates them from
5052 * current "transaction" (started by LOCK TABLES, ended by UNLOCK TABLES). PBXT
5053 * used to allow INSERTs and made them visible to the locker (on commit).
5054 * While MySQL manual doesn't state anything regarding row visibility limitations
5055 * we choose to convert local locks into normal read locks for better compatibility
5056 * with MyISAM.
5057 */
5058 if (lock_type == TL_READ)
5059 lock_type = TL_READ_NO_INSERT;
5060
4918 if (lock_type != TL_IGNORE && pb_lock.type == TL_UNLOCK) {5061 if (lock_type != TL_IGNORE && pb_lock.type == TL_UNLOCK) {
4919 /* Set to TRUE for operations that require a table lock: */5062 /* Set to TRUE for operations that require a table lock: */
4920 switch (thd_sql_command(thd)) {5063 switch (thd_sql_command(thd)) {
@@ -5112,7 +5255,7 @@
5112 * We also cannot use pb_share because the handler used5255 * We also cannot use pb_share because the handler used
5113 * to delete a table is not openned correctly.5256 * to delete a table is not openned correctly.
5114 */5257 */
5115 share = ha_get_share(self, table_path, false, NULL);5258 share = ha_get_share(self, table_path, false);
5116 pushr_(ha_unget_share, share);5259 pushr_(ha_unget_share, share);
5117 ha_aquire_exclusive_use(self, share, NULL);5260 ha_aquire_exclusive_use(self, share, NULL);
5118 pushr_(ha_release_exclusive_use, share);5261 pushr_(ha_release_exclusive_use, share);
@@ -5271,7 +5414,7 @@
5271 * called without correctly initializing5414 * called without correctly initializing
5272 * the handler!5415 * the handler!
5273 */5416 */
5274 share = ha_get_share(self, from, true, NULL);5417 share = ha_get_share(self, from, true);
5275 pushr_(ha_unget_share, share);5418 pushr_(ha_unget_share, share);
5276 ha_aquire_exclusive_use(self, share, NULL);5419 ha_aquire_exclusive_use(self, share, NULL);
5277 pushr_(ha_release_exclusive_use, share);5420 pushr_(ha_release_exclusive_use, share);
@@ -5852,6 +5995,11 @@
5852 NULL, NULL, FALSE);5995 NULL, NULL, FALSE);
5853#endif5996#endif
58545997
5998static MYSQL_SYSVAR_INT(flush_log_at_trx_commit, xt_db_flush_log_at_trx_commit,
5999 PLUGIN_VAR_OPCMDARG,
6000 "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.",
6001 NULL, NULL, 1, 0, 2, 1);
6002
5855static struct st_mysql_sys_var* pbxt_system_variables[] = {6003static struct st_mysql_sys_var* pbxt_system_variables[] = {
5856 MYSQL_SYSVAR(index_cache_size),6004 MYSQL_SYSVAR(index_cache_size),
5857 MYSQL_SYSVAR(record_cache_size),6005 MYSQL_SYSVAR(record_cache_size),
@@ -5870,6 +6018,7 @@
5870 MYSQL_SYSVAR(sweeper_priority),6018 MYSQL_SYSVAR(sweeper_priority),
5871 MYSQL_SYSVAR(max_threads),6019 MYSQL_SYSVAR(max_threads),
5872 MYSQL_SYSVAR(support_xa),6020 MYSQL_SYSVAR(support_xa),
6021 MYSQL_SYSVAR(flush_log_at_trx_commit),
5873 NULL6022 NULL
5874};6023};
5875#endif6024#endif
58766025
=== modified file 'storage/pbxt/src/index_xt.cc'
--- storage/pbxt/src/index_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/index_xt.cc 2010-05-07 08:52:27 +0000
@@ -1328,10 +1328,12 @@
1328 XT_SET_DISK_2(leaf->tb_size_2, XT_MAKE_NODE_SIZE(result->sr_item.i_total_size));1328 XT_SET_DISK_2(leaf->tb_size_2, XT_MAKE_NODE_SIZE(result->sr_item.i_total_size));
1329}1329}
13301330
1331static void idx_get_middle_branch_item(XTIndexPtr ind, XTIdxBranchDPtr branch, XTIdxKeyValuePtr value, XTIdxResultPtr result)1331static xtBool idx_get_middle_branch_item(XTOpenTablePtr ot, XTIndexPtr ind, XTIdxBranchDPtr branch, XTIdxKeyValuePtr value, XTIdxResultPtr result)
1332{1332{
1333 xtWord1 *bitem;1333 xtWord1 *bitem;
13341334
1335 ASSERT_NS(result->sr_item.i_node_ref_size == 0 || result->sr_item.i_node_ref_size == XT_NODE_REF_SIZE);
1336 ASSERT_NS((int) result->sr_item.i_total_size >= 0 && result->sr_item.i_total_size <= XT_INDEX_PAGE_SIZE*2);
1335 if (ind->mi_fix_key) {1337 if (ind->mi_fix_key) {
1336 u_int full_item_size = result->sr_item.i_item_size + result->sr_item.i_node_ref_size;1338 u_int full_item_size = result->sr_item.i_item_size + result->sr_item.i_node_ref_size;
13371339
@@ -1346,18 +1348,25 @@
1346 }1348 }
1347 else {1349 else {
1348 u_int node_ref_size;1350 u_int node_ref_size;
1349 u_int ilen;1351 u_int ilen, tlen;
1350 xtWord1 *bend;1352 xtWord1 *bend;
13511353
1352 node_ref_size = result->sr_item.i_node_ref_size;1354 node_ref_size = result->sr_item.i_node_ref_size;
1353 bitem = branch->tb_data + node_ref_size;;1355 bitem = branch->tb_data + node_ref_size;
1354 bend = &branch->tb_data[(result->sr_item.i_total_size - node_ref_size) / 2 + node_ref_size];1356 bend = &branch->tb_data[(result->sr_item.i_total_size - node_ref_size) / 2 + node_ref_size];
1355 ilen = 0;1357 ilen = 0;
1356 if (bitem < bend) {1358 if (bitem < bend) {
1359 tlen = 0;
1357 for (;;) {1360 for (;;) {
1358 ilen = myxt_get_key_length(ind, bitem);1361 ilen = myxt_get_key_length(ind, bitem);
1359 if (bitem + ilen + XT_RECORD_REF_SIZE + node_ref_size >= bend)1362 tlen += ilen + XT_RECORD_REF_SIZE + node_ref_size;
1363 if (bitem + ilen + XT_RECORD_REF_SIZE + node_ref_size >= bend) {
1364 if (ilen > XT_INDEX_PAGE_SIZE || tlen > result->sr_item.i_total_size) {
1365 xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
1366 return FAILED;
1367 }
1360 break;1368 break;
1369 }
1361 bitem += ilen + XT_RECORD_REF_SIZE + node_ref_size;1370 bitem += ilen + XT_RECORD_REF_SIZE + node_ref_size;
1362 }1371 }
1363 }1372 }
@@ -1370,6 +1379,7 @@
1370 xt_get_record_ref(bitem + ilen, &value->sv_rec_id, &value->sv_row_id);1379 xt_get_record_ref(bitem + ilen, &value->sv_rec_id, &value->sv_row_id);
1371 memcpy(value->sv_key, bitem, value->sv_length);1380 memcpy(value->sv_key, bitem, value->sv_length);
1372 }1381 }
1382 return OK;
1373}1383}
13741384
1375static size_t idx_write_branch_item(XTIndexPtr XT_UNUSED(ind), xtWord1 *item, XTIdxKeyValuePtr value)1385static size_t idx_write_branch_item(XTIndexPtr XT_UNUSED(ind), xtWord1 *item, XTIdxKeyValuePtr value)
@@ -1438,7 +1448,8 @@
1438 /* We assume that value can be overwritten (which is the case) */1448 /* We assume that value can be overwritten (which is the case) */
1439 key_value.sv_flags = XT_SEARCH_WHOLE_KEY;1449 key_value.sv_flags = XT_SEARCH_WHOLE_KEY;
1440 key_value.sv_key = key_buf;1450 key_value.sv_key = key_buf;
1441 idx_get_middle_branch_item(ind, iref.ir_branch, &key_value, &result);1451 if (!idx_get_middle_branch_item(ot, ind, iref.ir_branch, &key_value, &result))
1452 goto failed_1;
14421453
1443 if (!idx_new_branch(ot, ind, &new_branch))1454 if (!idx_new_branch(ot, ind, &new_branch))
1444 goto failed_1;1455 goto failed_1;
@@ -1567,7 +1578,8 @@
1567 ASSERT_NS(result.sr_item.i_total_size > XT_INDEX_PAGE_DATA_SIZE);1578 ASSERT_NS(result.sr_item.i_total_size > XT_INDEX_PAGE_DATA_SIZE);
15681579
1569 /* We assume that value can be overwritten (which is the case) */1580 /* We assume that value can be overwritten (which is the case) */
1570 idx_get_middle_branch_item(ind, &ot->ot_ind_wbuf, key_value, &result);1581 if (!idx_get_middle_branch_item(ot, ind, &ot->ot_ind_wbuf, key_value, &result))
1582 goto failed_1;
15711583
1572 if (!idx_new_branch(ot, ind, &new_branch))1584 if (!idx_new_branch(ot, ind, &new_branch))
1573 goto failed_1;1585 goto failed_1;
@@ -2041,7 +2053,7 @@
2041 memcpy(&ot->ot_ind_wbuf, iref.ir_branch, offsetof(XTIdxBranchDRec, tb_data) + result.sr_item.i_total_size);2053 memcpy(&ot->ot_ind_wbuf, iref.ir_branch, offsetof(XTIdxBranchDRec, tb_data) + result.sr_item.i_total_size);
2042 idx_insert_leaf_item(ind, &ot->ot_ind_wbuf, &key_value, &result);2054 idx_insert_leaf_item(ind, &ot->ot_ind_wbuf, &key_value, &result);
2043 IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2));2055 IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2));
2044 ASSERT_NS(result.sr_item.i_total_size > XT_INDEX_PAGE_DATA_SIZE);2056 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);
20452057
2046 /* This is the number of potential writes. In other words, the total number2058 /* This is the number of potential writes. In other words, the total number
2047 * of blocks that may be accessed.2059 * of blocks that may be accessed.
@@ -2053,7 +2065,8 @@
2053 goto failed_1;2065 goto failed_1;
20542066
2055 /* Key does not fit, must split... */2067 /* Key does not fit, must split... */
2056 idx_get_middle_branch_item(ind, &ot->ot_ind_wbuf, &key_value, &result);2068 if (!idx_get_middle_branch_item(ot, ind, &ot->ot_ind_wbuf, &key_value, &result))
2069 goto failed_1;
20572070
2058 if (!idx_new_branch(ot, ind, &new_branch))2071 if (!idx_new_branch(ot, ind, &new_branch))
2059 goto failed_1;2072 goto failed_1;
@@ -3317,7 +3330,7 @@
3317 return FALSE;3330 return FALSE;
3318}3331}
33193332
3320static void idx_set_index_selectivity(XTThreadPtr self, XTOpenTablePtr ot, XTIndexPtr ind)3333static void idx_set_index_selectivity(XTOpenTablePtr ot, XTIndexPtr ind, XTThreadPtr thread)
3321{3334{
3322 static const xtRecordID MAX_RECORDS = 100;3335 static const xtRecordID MAX_RECORDS = 100;
33233336
@@ -3368,7 +3381,7 @@
3368 last_rec = ot->ot_curr_rec_id;3381 last_rec = ot->ot_curr_rec_id;
33693382
3370 key_len = ot->ot_ind_state.i_item_size - XT_RECORD_REF_SIZE;3383 key_len = ot->ot_ind_state.i_item_size - XT_RECORD_REF_SIZE;
3371 xt_ind_unlock_handle(ot->ot_ind_rhandle);3384 xt_ind_lock_handle(ot->ot_ind_rhandle);
3372 memcpy(key_buf, ot->ot_ind_rhandle->ih_branch->tb_data + ot->ot_ind_state.i_item_offset, key_len);3385 memcpy(key_buf, ot->ot_ind_rhandle->ih_branch->tb_data + ot->ot_ind_state.i_item_offset, key_len);
3373 xt_ind_unlock_handle(ot->ot_ind_rhandle);3386 xt_ind_unlock_handle(ot->ot_ind_rhandle);
3374 }3387 }
@@ -3410,7 +3423,7 @@
3410 last_iter_rec = last_rec;3423 last_iter_rec = last_rec;
34113424
3412 if (ot->ot_ind_rhandle) {3425 if (ot->ot_ind_rhandle) {
3413 xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, self);3426 xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, thread);
3414 ot->ot_ind_rhandle = NULL;3427 ot->ot_ind_rhandle = NULL;
3415 }3428 }
3416 }3429 }
@@ -3431,8 +3444,10 @@
3431 return;3444 return;
34323445
3433 failed_1:3446 failed_1:
3434 xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, self);3447 if (ot->ot_ind_rhandle) {
3435 ot->ot_ind_rhandle = NULL;3448 xt_ind_release_handle(ot->ot_ind_rhandle, FALSE, thread);
3449 ot->ot_ind_rhandle = NULL;
3450 }
34363451
3437 failed:3452 failed:
3438 xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED);3453 xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED);
@@ -3440,16 +3455,23 @@
3440 return;3455 return;
3441}3456}
34423457
3443xtPublic void xt_ind_set_index_selectivity(XTThreadPtr self, XTOpenTablePtr ot)3458xtPublic void xt_ind_set_index_selectivity(XTOpenTablePtr ot, XTThreadPtr thread)
3444{3459{
3445 XTTableHPtr tab = ot->ot_table;3460 XTTableHPtr tab = ot->ot_table;
3446 XTIndexPtr *ind;3461 XTIndexPtr *ind;
3447 u_int i;3462 u_int i;
3463 time_t now;
34483464
3449 if (!tab->tab_dic.dic_disable_index) {3465 now = time(NULL);
3450 for (i=0, ind=tab->tab_dic.dic_keys; i<tab->tab_dic.dic_key_count; i++, ind++)3466 xt_lock_mutex_ns(&tab->tab_ind_stat_lock);
3451 idx_set_index_selectivity(self, ot, *ind);3467 if (tab->tab_ind_stat_calc_time < now) {
3468 if (!tab->tab_dic.dic_disable_index) {
3469 for (i=0, ind=tab->tab_dic.dic_keys; i<tab->tab_dic.dic_key_count; i++, ind++)
3470 idx_set_index_selectivity(ot, *ind, thread);
3471 }
3472 tab->tab_ind_stat_calc_time = time(NULL);
3452 }3473 }
3474 xt_unlock_mutex_ns(&tab->tab_ind_stat_lock);
3453}3475}
34543476
3455/*3477/*
@@ -3740,7 +3762,8 @@
3740static xtBool idx_flush_dirty_list(XTIndexLogPtr il, XTOpenTablePtr ot, u_int *flush_count, XTIndBlockPtr *flush_list)3762static xtBool idx_flush_dirty_list(XTIndexLogPtr il, XTOpenTablePtr ot, u_int *flush_count, XTIndBlockPtr *flush_list)
3741{3763{
3742 for (u_int i=0; i<*flush_count; i++)3764 for (u_int i=0; i<*flush_count; i++)
3743 il->il_write_block(ot, flush_list[i]);3765 if (!il->il_write_block(ot, flush_list[i]))
3766 return FAILED;
3744 *flush_count = 0;3767 *flush_count = 0;
3745 return OK;3768 return OK;
3746}3769}
@@ -3793,7 +3816,7 @@
3793 xtIndexNodeID ind_free;3816 xtIndexNodeID ind_free;
3794 xtBool something_to_free = FALSE;3817 xtBool something_to_free = FALSE;
3795 xtIndexNodeID last_address, next_address;3818 xtIndexNodeID last_address, next_address;
3796 xtWord2 curr_flush_seq;3819 xtWord4 curr_flush_seq;
3797 XTIndFreeListPtr list_ptr;3820 XTIndFreeListPtr list_ptr;
3798 u_int dirty_blocks;3821 u_int dirty_blocks;
3799 XTCheckPointTablePtr cp_tab;3822 XTCheckPointTablePtr cp_tab;
@@ -3810,8 +3833,9 @@
3810 if (!tab->tab_db->db_indlogs.ilp_get_log(&il, ot->ot_thread))3833 if (!tab->tab_db->db_indlogs.ilp_get_log(&il, ot->ot_thread))
3811 goto failed_3;3834 goto failed_3;
38123835
3813 il->il_reset(tab->tab_id);3836 if (!il->il_reset(ot))
3814 if (!il->il_write_byte(ot, XT_DT_FREE_LIST))3837 goto failed_2;
3838 if (!il->il_write_byte(ot, XT_DT_LOG_HEAD))
3815 goto failed_2;3839 goto failed_2;
3816 if (!il->il_write_word4(ot, tab->tab_id))3840 if (!il->il_write_word4(ot, tab->tab_id))
3817 goto failed_2;3841 goto failed_2;
@@ -3849,7 +3873,7 @@
3849 wrote_something = TRUE;3873 wrote_something = TRUE;
3850 while (block) {3874 while (block) {
3851 ASSERT_NS(block->cb_state == IDX_CAC_BLOCK_DIRTY);3875 ASSERT_NS(block->cb_state == IDX_CAC_BLOCK_DIRTY);
3852 ASSERT_NS(block->cp_flush_seq == curr_flush_seq);3876 ASSERT_NS((block->cp_flush_seq == curr_flush_seq) || xt_xn_is_before(block->cp_flush_seq, curr_flush_seq));
3853 if (!ind_add_to_dirty_list(il, ot, &flush_count, flush_list, block))3877 if (!ind_add_to_dirty_list(il, ot, &flush_count, flush_list, block))
3854 goto failed;3878 goto failed;
3855 block = block->cb_dirty_next;3879 block = block->cb_dirty_next;
@@ -4023,7 +4047,7 @@
4023 fblock = block;4047 fblock = block;
4024 block = block->cb_dirty_next;4048 block = block->cb_dirty_next;
4025 ASSERT_NS(fblock->cb_state == IDX_CAC_BLOCK_DIRTY);4049 ASSERT_NS(fblock->cb_state == IDX_CAC_BLOCK_DIRTY);
4026 if (fblock->cp_flush_seq == curr_flush_seq) {4050 if (fblock->cp_flush_seq == curr_flush_seq || xt_xn_is_before(fblock->cp_flush_seq, curr_flush_seq)) {
4027 /* Take the block off the dirty list: */4051 /* Take the block off the dirty list: */
4028 if (fblock->cb_dirty_next)4052 if (fblock->cb_dirty_next)
4029 fblock->cb_dirty_next->cb_dirty_prev = fblock->cb_dirty_prev;4053 fblock->cb_dirty_next->cb_dirty_prev = fblock->cb_dirty_prev;
@@ -4254,12 +4278,32 @@
4254 xt_unlock_mutex_ns(&ilp_lock);4278 xt_unlock_mutex_ns(&ilp_lock);
4255}4279}
42564280
4257void XTIndexLog::il_reset(xtTableID tab_id)4281xtBool XTIndexLog::il_reset(XTOpenTable *ot)
4258{4282{
4283 XTIndLogHeadDRec log_head;
4284 xtTableID tab_id = ot->ot_table->tab_id;
4285
4259 il_tab_id = tab_id;4286 il_tab_id = tab_id;
4260 il_log_eof = 0;4287 il_log_eof = 0;
4261 il_buffer_len = 0;4288 il_buffer_len = 0;
4262 il_buffer_offset = 0;4289 il_buffer_offset = 0;
4290
4291 /* We must write the header and flush here or the "previous" status (from the
4292 * last flush run) could remain. Failure to write the file completely leave the
4293 * old header in place, and other parts of the file changed.
4294 * This would lead to index corruption.
4295 */
4296 log_head.ilh_data_type = XT_DT_LOG_HEAD;
4297 XT_SET_DISK_4(log_head.ilh_tab_id_4, tab_id);
4298 XT_SET_DISK_4(log_head.ilh_log_eof_4, 0);
4299
4300 if (!xt_pwrite_file(il_of, 0, sizeof(XTIndLogHeadDRec), (xtWord1 *) &log_head, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
4301 return FAILED;
4302
4303 if (!xt_flush_file(il_of, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
4304 return FAILED;
4305
4306 return OK;
4263}4307}
42644308
4265void XTIndexLog::il_close(xtBool delete_it)4309void XTIndexLog::il_close(xtBool delete_it)
42664310
=== modified file 'storage/pbxt/src/index_xt.h'
--- storage/pbxt/src/index_xt.h 2009-08-17 11:12:36 +0000
+++ storage/pbxt/src/index_xt.h 2010-05-07 08:52:27 +0000
@@ -30,6 +30,7 @@
30#include <mysql_version.h>30#include <mysql_version.h>
31#include <my_bitmap.h>31#include <my_bitmap.h>
32#endif32#endif
33#include <time.h>
3334
34#include "thread_xt.h"35#include "thread_xt.h"
35#include "linklist_xt.h"36#include "linklist_xt.h"
@@ -293,7 +294,6 @@
293 */294 */
294typedef struct XTIndex {295typedef struct XTIndex {
295 u_int mi_index_no; /* The index number (used by MySQL). */296 u_int mi_index_no; /* The index number (used by MySQL). */
296 xt_mutex_type mi_flush_lock; /* Lock the index during flushing. */
297297
298 /* Protected by the mi_rwlock lock: */298 /* Protected by the mi_rwlock lock: */
299 XT_INDEX_LOCK_TYPE mi_rwlock; /* This lock protects the structure of the index.299 XT_INDEX_LOCK_TYPE mi_rwlock; /* This lock protects the structure of the index.
@@ -407,7 +407,7 @@
407 off_t il_buffer_offset;407 off_t il_buffer_offset;
408408
409409
410 void il_reset(xtTableID tab_id);410 xtBool il_reset(XTOpenTable *ot);
411 void il_close(xtBool delete_it);411 void il_close(xtBool delete_it);
412 void il_release();412 void il_release();
413413
@@ -478,7 +478,7 @@
478xtBool xt_idx_next(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);478xtBool xt_idx_next(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
479xtBool xt_idx_prev(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);479xtBool xt_idx_prev(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
480xtBool xt_idx_read(struct XTOpenTable *ot, struct XTIndex *ind, xtWord1 *rec_buf);480xtBool xt_idx_read(struct XTOpenTable *ot, struct XTIndex *ind, xtWord1 *rec_buf);
481void xt_ind_set_index_selectivity(XTThreadPtr self, struct XTOpenTable *ot);481void xt_ind_set_index_selectivity(struct XTOpenTable *ot, XTThreadPtr thread);
482void xt_check_indices(struct XTOpenTable *ot);482void xt_check_indices(struct XTOpenTable *ot);
483void xt_load_indices(XTThreadPtr self, struct XTOpenTable *ot);483void xt_load_indices(XTThreadPtr self, struct XTOpenTable *ot);
484void xt_ind_count_deleted_items(struct XTTable *ot, struct XTIndex *ind, struct XTIndBlock *block);484void xt_ind_count_deleted_items(struct XTTable *ot, struct XTIndex *ind, struct XTIndBlock *block);
485485
=== modified file 'storage/pbxt/src/lock_xt.cc'
--- storage/pbxt/src/lock_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/lock_xt.cc 2010-05-07 08:52:27 +0000
@@ -1444,7 +1444,7 @@
1444#endif1444#endif
1445}1445}
14461446
1447xtPublic xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtThreadID XT_NDEBUG_UNUSED(thd_id))1447xtPublic xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtBool try_lock, xtThreadID XT_NDEBUG_UNUSED(thd_id))
1448{1448{
1449 register xtWord2 set;1449 register xtWord2 set;
14501450
@@ -1453,6 +1453,8 @@
1453 set = xt_atomic_tas2(&sxs->sxs_xlocked, 1);1453 set = xt_atomic_tas2(&sxs->sxs_xlocked, 1);
1454 if (!set)1454 if (!set)
1455 break;1455 break;
1456 if (try_lock)
1457 return FALSE;
1456 xt_yield();1458 xt_yield();
1457 }1459 }
14581460
@@ -1460,9 +1462,25 @@
1460 sxs->sxs_locker = thd_id;1462 sxs->sxs_locker = thd_id;
1461#endif1463#endif
14621464
1463 /* Wait for all the reader to wait! */1465 /* Wait for all the readers to wait! */
1464 while (sxs->sxs_wait_count < sxs->sxs_rlock_count)1466 while (sxs->sxs_wait_count < sxs->sxs_rlock_count) {
1465 xt_yield();1467 sxs->sxs_xwaiter = 1;
1468 xt_yield(); //*
1469 /* This should not be required, because there is only one thread
1470 * accessing this value. However, the lock fails if this
1471 * is not done with an atomic op.
1472 *
1473 * This is because threads on other processors have the
1474 * value in processor cache. So they do not
1475 * notice that the value has been set to zero.
1476 * They think it is still 1 and march through
1477 * the barrier (sxs->sxs_xwaiter < sxs->sxs_xlocked) below.
1478 *
1479 * In the meantime, this X locker has gone on thinking
1480 * all is OK.
1481 */
1482 xt_atomic_tas2(&sxs->sxs_xwaiter, 0);
1483 }
14661484
1467#ifdef XT_THREAD_LOCK_INFO1485#ifdef XT_THREAD_LOCK_INFO
1468 xt_thread_lock_info_add_owner(&sxs->sxs_lock_info);1486 xt_thread_lock_info_add_owner(&sxs->sxs_lock_info);
@@ -1474,12 +1492,12 @@
1474{1492{
1475 xt_atomic_inc2(&sxs->sxs_rlock_count);1493 xt_atomic_inc2(&sxs->sxs_rlock_count);
14761494
1477 /* Check if there could be an X locker: */1495 /* Wait as long as the locker is not waiting: */
1478 if (sxs->sxs_xlocked) {1496 while (sxs->sxs_xwaiter < sxs->sxs_xlocked) {
1479 /* I am waiting... */
1480 xt_atomic_inc2(&sxs->sxs_wait_count);1497 xt_atomic_inc2(&sxs->sxs_wait_count);
1481 while (sxs->sxs_xlocked)1498 while (sxs->sxs_xwaiter < sxs->sxs_xlocked) {
1482 xt_yield();1499 xt_yield();
1500 }
1483 xt_atomic_dec2(&sxs->sxs_wait_count);1501 xt_atomic_dec2(&sxs->sxs_wait_count);
1484 }1502 }
14851503
@@ -1493,12 +1511,17 @@
1493{1511{
1494 if (xlocked) {1512 if (xlocked) {
1495#ifdef DEBUG1513#ifdef DEBUG
1514 ASSERT_NS(sxs->sxs_locker && sxs->sxs_xlocked);
1496 sxs->sxs_locker = 0;1515 sxs->sxs_locker = 0;
1497#endif1516#endif
1498 sxs->sxs_xlocked = 0;1517 sxs->sxs_xlocked = 0;
1499 }1518 }
1500 else1519 else {
1520#ifdef DEBUG
1521 ASSERT_NS(sxs->sxs_rlock_count > 0);
1522#endif
1501 xt_atomic_dec2(&sxs->sxs_rlock_count);1523 xt_atomic_dec2(&sxs->sxs_rlock_count);
1524 }
15021525
1503#ifdef XT_THREAD_LOCK_INFO1526#ifdef XT_THREAD_LOCK_INFO
1504 xt_thread_lock_info_release_owner(&sxs->sxs_lock_info);1527 xt_thread_lock_info_release_owner(&sxs->sxs_lock_info);
@@ -1698,7 +1721,7 @@
1698#endif1721#endif
1699}1722}
17001723
1701xtPublic xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr arw, xtThreadID XT_NDEBUG_UNUSED(thr_id))1724xtPublic xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr arw, xtBool try_lock, xtThreadID XT_NDEBUG_UNUSED(thr_id))
1702{1725{
1703 register xtWord2 set;1726 register xtWord2 set;
17041727
@@ -1707,6 +1730,8 @@
1707 set = xt_atomic_tas2(&arw->arw_xlock_set, 1);1730 set = xt_atomic_tas2(&arw->arw_xlock_set, 1);
1708 if (!set)1731 if (!set)
1709 break;1732 break;
1733 if (try_lock)
1734 return FALSE;
1710 xt_yield();1735 xt_yield();
1711 }1736 }
17121737
@@ -1721,7 +1746,7 @@
1721#ifdef XT_THREAD_LOCK_INFO1746#ifdef XT_THREAD_LOCK_INFO
1722 xt_thread_lock_info_add_owner(&arw->arw_lock_info);1747 xt_thread_lock_info_add_owner(&arw->arw_lock_info);
1723#endif1748#endif
1724 return OK;1749 return TRUE;
1725}1750}
17261751
1727xtPublic xtBool xt_atomicrwlock_slock(XTAtomicRWLockPtr arw)1752xtPublic xtBool xt_atomicrwlock_slock(XTAtomicRWLockPtr arw)
@@ -1799,7 +1824,7 @@
1799#endif1824#endif
1800}1825}
18011826
1802xtPublic xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr srw, xtThreadID XT_NDEBUG_UNUSED(thr_id))1827xtPublic xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr srw, xtBool try_lock, xtThreadID XT_NDEBUG_UNUSED(thr_id))
1803{1828{
1804 register xtWord2 set;1829 register xtWord2 set;
18051830
@@ -1808,6 +1833,8 @@
1808 set = xt_atomic_tas2(&srw->srw_xlock_set, 1);1833 set = xt_atomic_tas2(&srw->srw_xlock_set, 1);
1809 if (!set)1834 if (!set)
1810 break;1835 break;
1836 if (try_lock)
1837 return FALSE;
1811 xt_yield();1838 xt_yield();
1812 }1839 }
18131840
@@ -1822,7 +1849,7 @@
1822#ifdef XT_THREAD_LOCK_INFO1849#ifdef XT_THREAD_LOCK_INFO
1823 xt_thread_lock_info_add_owner(&srw->srw_lock_info);1850 xt_thread_lock_info_add_owner(&srw->srw_lock_info);
1824#endif1851#endif
1825 return OK;1852 return TRUE;
1826}1853}
18271854
1828xtPublic xtBool xt_skewrwlock_slock(XTSkewRWLockPtr srw)1855xtPublic xtBool xt_skewrwlock_slock(XTSkewRWLockPtr srw)
@@ -1869,6 +1896,124 @@
18691896
1870/*1897/*
1871 * -----------------------------------------------------------------------1898 * -----------------------------------------------------------------------
1899 * RECURSIVE R/W LOCK (allows X lockers to lock again)
1900 */
1901
1902#ifdef XT_THREAD_LOCK_INFO
1903void xt_recursivemutex_init(XTThreadPtr self, XTRecursiveMutexPtr rm, const char *name)
1904{
1905 rm->rm_locker = NULL;
1906 rm->rm_lock_count = 0;
1907 xt_init_mutex(self, &rm->rm_mutex, name);
1908}
1909#else
1910xtPublic void xt_recursivemutex_init(XTThreadPtr self, XTRecursiveMutexPtr rm)
1911{
1912 rm->rm_locker = NULL;
1913 rm->rm_lock_count = 0;
1914 xt_init_mutex(self, &rm->rm_mutex);
1915}
1916#endif
1917
1918xtPublic void xt_recursivemutex_free(XTRecursiveMutexPtr rm)
1919{
1920 xt_free_mutex(&rm->rm_mutex);
1921#ifdef XT_THREAD_LOCK_INFO
1922 xt_thread_lock_info_free(&rm->rm_lock_info);
1923#endif
1924}
1925
1926xtPublic void xt_recursivemutex_lock(XTThreadPtr self, XTRecursiveMutexPtr rm)
1927{
1928 if (self != rm->rm_locker) {
1929 xt_lock_mutex(self, &rm->rm_mutex);
1930 rm->rm_locker = self;
1931 }
1932 rm->rm_lock_count++;
1933}
1934
1935xtPublic void xt_recursivemutex_unlock(XTThreadPtr self, XTRecursiveMutexPtr rm)
1936{
1937 ASSERT(self == rm->rm_locker);
1938 ASSERT(rm->rm_lock_count > 0);
1939 rm->rm_lock_count--;
1940 if (!rm->rm_lock_count) {
1941 rm->rm_locker = NULL;
1942 xt_unlock_mutex(self, &rm->rm_mutex);
1943 }
1944}
1945
1946/*
1947 * -----------------------------------------------------------------------
1948 * RECURSIVE MUTEX (allows lockers to lock again)
1949 */
1950
1951#ifdef XT_THREAD_LOCK_INFO
1952void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw, const char *name)
1953{
1954 rrw->rrw_locker = NULL;
1955 rrw->rrw_lock_count = 0;
1956 xt_init_rwlock(self, &rrw->rrw_lock, name);
1957}
1958#else
1959void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw)
1960{
1961 rrw->rrw_locker = NULL;
1962 rrw->rrw_lock_count = 0;
1963 xt_init_rwlock(self, &rrw->rrw_lock);
1964}
1965#endif
1966
1967void xt_recurrwlock_free(XTRecurRWLockPtr rrw)
1968{
1969 xt_free_rwlock(&rrw->rrw_lock);
1970#ifdef XT_THREAD_LOCK_INFO
1971 xt_thread_lock_info_free(&rrw->rrw_lock_info);
1972#endif
1973}
1974
1975void xt_recurrwlock_xlock(struct XTThread *self, XTRecurRWLockPtr rrw)
1976{
1977 if (self != rrw->rrw_locker) {
1978 xt_xlock_rwlock(self, &rrw->rrw_lock);
1979 rrw->rrw_locker = self;
1980 }
1981 rrw->rrw_lock_count++;
1982}
1983
1984void xt_recurrwlock_slock(struct XTThread *self, XTRecurRWLockPtr rrw)
1985{
1986 xt_slock_rwlock(self, &rrw->rrw_lock);
1987}
1988
1989void xt_recurrwlock_slock_ns(XTRecurRWLockPtr rrw)
1990{
1991 xt_slock_rwlock_ns(&rrw->rrw_lock);
1992}
1993
1994void xt_recurrwlock_unxlock(struct XTThread *self, XTRecurRWLockPtr rrw)
1995{
1996 ASSERT(self == rrw->rrw_locker);
1997 ASSERT(rrw->rrw_lock_count > 0);
1998 rrw->rrw_lock_count--;
1999 if (!rrw->rrw_lock_count) {
2000 rrw->rrw_locker = NULL;
2001 xt_unlock_rwlock(self, &rrw->rrw_lock);
2002 }
2003}
2004
2005void xt_recurrwlock_unslock(struct XTThread *self, XTRecurRWLockPtr rrw)
2006{
2007 xt_unlock_rwlock(self, &rrw->rrw_lock);
2008}
2009
2010void xt_recurrwlock_unslock_ns(XTRecurRWLockPtr rrw)
2011{
2012 xt_unlock_rwlock_ns(&rrw->rrw_lock);
2013}
2014
2015/*
2016 * -----------------------------------------------------------------------
1872 * UNIT TESTS2017 * UNIT TESTS
1873 */2018 */
18742019
@@ -2031,7 +2176,7 @@
2031 xt_rwmutex_unlock(&data->xs_lock, self->t_id);2176 xt_rwmutex_unlock(&data->xs_lock, self->t_id);
2032 }2177 }
2033 else if (data->xs_which_lock == LOCK_SPINXSLOCK) {2178 else if (data->xs_which_lock == LOCK_SPINXSLOCK) {
2034 xt_spinxslock_xlock(&data->xs_spinrwlock, self->t_id);2179 xt_spinxslock_xlock(&data->xs_spinrwlock, FALSE, self->t_id);
2035 lck_do_job(self, data->xs_which_job, data, FALSE);2180 lck_do_job(self, data->xs_which_job, data, FALSE);
2036 xt_spinxslock_unlock(&data->xs_spinrwlock, TRUE);2181 xt_spinxslock_unlock(&data->xs_spinrwlock, TRUE);
2037 }2182 }
@@ -2041,12 +2186,12 @@
2041 xt_xsmutex_unlock(&data->xs_fastrwlock, self->t_id);2186 xt_xsmutex_unlock(&data->xs_fastrwlock, self->t_id);
2042 }2187 }
2043 else if (data->xs_which_lock == LOCK_ATOMICRWLOCK) {2188 else if (data->xs_which_lock == LOCK_ATOMICRWLOCK) {
2044 xt_atomicrwlock_xlock(&data->xs_atomicrwlock, self->t_id);2189 xt_atomicrwlock_xlock(&data->xs_atomicrwlock, FALSE, self->t_id);
2045 lck_do_job(self, data->xs_which_job, data, FALSE);2190 lck_do_job(self, data->xs_which_job, data, FALSE);
2046 xt_atomicrwlock_unlock(&data->xs_atomicrwlock, TRUE);2191 xt_atomicrwlock_unlock(&data->xs_atomicrwlock, TRUE);
2047 }2192 }
2048 else if (data->xs_which_lock == LOCK_SKEWRWLOCK) {2193 else if (data->xs_which_lock == LOCK_SKEWRWLOCK) {
2049 xt_skewrwlock_xlock(&data->xs_skewrwlock, self->t_id);2194 xt_skewrwlock_xlock(&data->xs_skewrwlock, FALSE, self->t_id);
2050 lck_do_job(self, data->xs_which_job, data, FALSE);2195 lck_do_job(self, data->xs_which_job, data, FALSE);
2051 xt_skewrwlock_unlock(&data->xs_skewrwlock, TRUE);2196 xt_skewrwlock_unlock(&data->xs_skewrwlock, TRUE);
2052 }2197 }
20532198
=== modified file 'storage/pbxt/src/lock_xt.h'
--- storage/pbxt/src/lock_xt.h 2009-08-17 11:12:36 +0000
+++ storage/pbxt/src/lock_xt.h 2010-05-07 08:52:27 +0000
@@ -109,7 +109,8 @@
109inline void xt_atomic_inc2(volatile xtWord2 *mptr)109inline void xt_atomic_inc2(volatile xtWord2 *mptr)
110{110{
111#ifdef XT_ATOMIC_WIN32_X86111#ifdef XT_ATOMIC_WIN32_X86
112 __asm LOCK INC WORD PTR mptr112 __asm MOV ECX, mptr
113 __asm LOCK INC WORD PTR [ECX]
113#elif defined(XT_ATOMIC_GNUC_X86)114#elif defined(XT_ATOMIC_GNUC_X86)
114 asm volatile ("lock; incw %0" : : "m" (*mptr) : "memory");115 asm volatile ("lock; incw %0" : : "m" (*mptr) : "memory");
115#elif defined(XT_ATOMIC_GCC_OPS)116#elif defined(XT_ATOMIC_GCC_OPS)
@@ -125,7 +126,8 @@
125inline void xt_atomic_dec2(volatile xtWord2 *mptr)126inline void xt_atomic_dec2(volatile xtWord2 *mptr)
126{127{
127#ifdef XT_ATOMIC_WIN32_X86128#ifdef XT_ATOMIC_WIN32_X86
128 __asm LOCK DEC WORD PTR mptr129 __asm MOV ECX, mptr
130 __asm LOCK DEC WORD PTR [ECX]
129#elif defined(XT_ATOMIC_GNUC_X86)131#elif defined(XT_ATOMIC_GNUC_X86)
130 asm volatile ("lock; decw %0" : : "m" (*mptr) : "memory");132 asm volatile ("lock; decw %0" : : "m" (*mptr) : "memory");
131#elif defined(XT_ATOMIC_GCC_OPS)133#elif defined(XT_ATOMIC_GCC_OPS)
@@ -427,6 +429,7 @@
427429
428typedef struct XTSpinXSLock {430typedef struct XTSpinXSLock {
429 volatile xtWord2 sxs_xlocked;431 volatile xtWord2 sxs_xlocked;
432 volatile xtWord2 sxs_xwaiter;
430 volatile xtWord2 sxs_rlock_count;433 volatile xtWord2 sxs_rlock_count;
431 volatile xtWord2 sxs_wait_count; /* The number of readers waiting for the xlocker. */434 volatile xtWord2 sxs_wait_count; /* The number of readers waiting for the xlocker. */
432#ifdef DEBUG435#ifdef DEBUG
@@ -446,7 +449,7 @@
446void xt_spinxslock_init(struct XTThread *self, XTSpinXSLockPtr sxs);449void xt_spinxslock_init(struct XTThread *self, XTSpinXSLockPtr sxs);
447#endif450#endif
448void xt_spinxslock_free(struct XTThread *self, XTSpinXSLockPtr sxs);451void xt_spinxslock_free(struct XTThread *self, XTSpinXSLockPtr sxs);
449xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtThreadID thd_id);452xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtBool try_lock, xtThreadID thd_id);
450xtBool xt_spinxslock_slock(XTSpinXSLockPtr sxs);453xtBool xt_spinxslock_slock(XTSpinXSLockPtr sxs);
451xtBool xt_spinxslock_unlock(XTSpinXSLockPtr sxs, xtBool xlocked);454xtBool xt_spinxslock_unlock(XTSpinXSLockPtr sxs, xtBool xlocked);
452455
@@ -500,7 +503,7 @@
500void xt_atomicrwlock_init(struct XTThread *self, XTAtomicRWLockPtr xsl);503void xt_atomicrwlock_init(struct XTThread *self, XTAtomicRWLockPtr xsl);
501#endif504#endif
502void xt_atomicrwlock_free(struct XTThread *self, XTAtomicRWLockPtr xsl);505void xt_atomicrwlock_free(struct XTThread *self, XTAtomicRWLockPtr xsl);
503xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr xsl, xtThreadID thr_id);506xtBool xt_atomicrwlock_xlock(XTAtomicRWLockPtr xsl, xtBool try_lock, xtThreadID thr_id);
504xtBool xt_atomicrwlock_slock(XTAtomicRWLockPtr xsl);507xtBool xt_atomicrwlock_slock(XTAtomicRWLockPtr xsl);
505xtBool xt_atomicrwlock_unlock(XTAtomicRWLockPtr xsl, xtBool xlocked);508xtBool xt_atomicrwlock_unlock(XTAtomicRWLockPtr xsl, xtBool xlocked);
506509
@@ -525,7 +528,7 @@
525void xt_skewrwlock_init(struct XTThread *self, XTSkewRWLockPtr xsl);528void xt_skewrwlock_init(struct XTThread *self, XTSkewRWLockPtr xsl);
526#endif529#endif
527void xt_skewrwlock_free(struct XTThread *self, XTSkewRWLockPtr xsl);530void xt_skewrwlock_free(struct XTThread *self, XTSkewRWLockPtr xsl);
528xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr xsl, xtThreadID thr_id);531xtBool xt_skewrwlock_xlock(XTSkewRWLockPtr xsl, xtBool try_lock, xtThreadID thr_id);
529xtBool xt_skewrwlock_slock(XTSkewRWLockPtr xsl);532xtBool xt_skewrwlock_slock(XTSkewRWLockPtr xsl);
530xtBool xt_skewrwlock_unlock(XTSkewRWLockPtr xsl, xtBool xlocked);533xtBool xt_skewrwlock_unlock(XTSkewRWLockPtr xsl, xtBool xlocked);
531534
@@ -713,4 +716,57 @@
713#define XT_HAVE_LOCK 2716#define XT_HAVE_LOCK 2
714#define XT_WAITING 3717#define XT_WAITING 3
715718
719/*
720 * -----------------------------------------------------------------------
721 * RECURSIVE MUTEX (allows lockers to lock again)
722 */
723
724typedef struct XTRecursiveMutex {
725 struct XTThread *rm_locker;
726 u_int rm_lock_count;
727 xt_mutex_type rm_mutex;
728
729#ifdef XT_THREAD_LOCK_INFO
730 XTThreadLockInfoRec rm_lock_info;
731 const char *rm_name;
732#endif
733} XTRecursiveMutexRec, *XTRecursiveMutexPtr;
734
735#ifdef XT_THREAD_LOCK_INFO
736#define xt_recursivemutex_init_with_autoname(a,b) xt_recursivemutex_init(a,b,LOCKLIST_ARG_SUFFIX(b))
737void xt_recursivemutex_init(struct XTThread *self, XTRecursiveMutexPtr rm, const char *name);
738#else
739#define xt_recursivemutex_init_with_autoname(a,b) xt_recursivemutex_init(a,b)
740void xt_recursivemutex_init(struct XTThread *self, XTRecursiveMutexPtr rm);
741#endif
742void xt_recursivemutex_free(XTRecursiveMutexPtr rm);
743void xt_recursivemutex_lock(struct XTThread *self, XTRecursiveMutexPtr rm);
744void xt_recursivemutex_unlock(struct XTThread *self, XTRecursiveMutexPtr rm);
745
746typedef struct XTRecurRWLock {
747 struct XTThread *rrw_locker;
748 u_int rrw_lock_count;
749 xt_rwlock_type rrw_lock;
750
751#ifdef XT_THREAD_LOCK_INFO
752 XTThreadLockInfoRec rrw_lock_info;
753 const char *rrw_name;
754#endif
755} XTRecurRWLockRec, *XTRecurRWLockPtr;
756
757#ifdef XT_THREAD_LOCK_INFO
758#define xt_recurrwlock_init_with_autoname(a,b) xt_recurrwlock_init(a,b,LOCKLIST_ARG_SUFFIX(b))
759void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw, const char *name);
760#else
761#define xt_recurrwlock_init_with_autoname(a,b) xt_recurrwlock_init(a,b)
762void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw);
763#endif
764void xt_recurrwlock_free(XTRecurRWLockPtr rrw);
765void xt_recurrwlock_xlock(struct XTThread *self, XTRecurRWLockPtr rrw);
766void xt_recurrwlock_slock(struct XTThread *self, XTRecurRWLockPtr rrw);
767void xt_recurrwlock_slock_ns(XTRecurRWLockPtr rrw);
768void xt_recurrwlock_unxlock(struct XTThread *self, XTRecurRWLockPtr rrw);
769void xt_recurrwlock_unslock(struct XTThread *self, XTRecurRWLockPtr rrw);
770void xt_recurrwlock_unslock_ns(XTRecurRWLockPtr rrw);
771
716#endif772#endif
717773
=== modified file 'storage/pbxt/src/locklist_xt.cc'
--- storage/pbxt/src/locklist_xt.cc 2010-04-21 00:25:59 +0000
+++ storage/pbxt/src/locklist_xt.cc 2010-05-07 08:52:27 +0000
@@ -180,6 +180,10 @@
180 lock_type = "XTAtomicRWLock";180 lock_type = "XTAtomicRWLock";
181 lock_name = li->li_atomic_rwlock->arw_name;181 lock_name = li->li_atomic_rwlock->arw_name;
182 break;182 break;
183 case XTThreadLockInfo::SKEW_RW_LOCK:
184 lock_type = "XTSkewRWLock";
185 lock_name = li->li_skew_rwlock->srw_name;
186 break;
183 }187 }
184188
185 xt_ttracef(self, " #lock#%d: type: %s name: %s \n", count, lock_type, lock_name);189 xt_ttracef(self, " #lock#%d: type: %s name: %s \n", count, lock_type, lock_name);
186190
=== modified file 'storage/pbxt/src/myxt_xt.cc'
--- storage/pbxt/src/myxt_xt.cc 2009-12-10 11:36:05 +0000
+++ storage/pbxt/src/myxt_xt.cc 2010-05-07 08:52:27 +0000
@@ -255,6 +255,11 @@
255 xtWord1 *end;255 xtWord1 *end;
256 xtWord1 *start;256 xtWord1 *start;
257257
258#ifdef HAVE_valgrind
259 if (ind->mi_fix_key)
260 memset((byte*) key, 0,(size_t) (ind->mi_key_size) );
261#endif
262
258 start = key;263 start = key;
259 for (u_int i=0; i<ind->mi_seg_count; i++, keyseg++)264 for (u_int i=0; i<ind->mi_seg_count; i++, keyseg++)
260 {265 {
@@ -531,7 +536,7 @@
531 key += length;536 key += length;
532 }537 }
533538
534 return fkey_ind->mi_fix_key ? fkey_ind->mi_key_size : (u_int) (key - start); /* Return keylength */539 return (u_int) (key - start);
535}540}
536541
537/* I may be overcautious here, but can I assume that542/* I may be overcautious here, but can I assume that
@@ -2132,10 +2137,10 @@
2132{2137{
2133 enter_();2138 enter_();
2134 /* The dirty list of cache pages should be empty here! */2139 /* The dirty list of cache pages should be empty here! */
2135 ASSERT(!mi->mi_dirty_list);2140 /* This is not the case if we were not able to flush data. E.g. when running out of disk space */
2141 //ASSERT(!mi->mi_dirty_list);
2136 ASSERT(!mi->mi_free_list);2142 ASSERT(!mi->mi_free_list);
21372143
2138 xt_free_mutex(&mi->mi_flush_lock);
2139 xt_spinlock_free(self, &mi->mi_dirty_lock);2144 xt_spinlock_free(self, &mi->mi_dirty_lock);
2140 XT_INDEX_FREE_LOCK(self, mi);2145 XT_INDEX_FREE_LOCK(self, mi);
2141 myxt_bitmap_free(self, &mi->mi_col_map);2146 myxt_bitmap_free(self, &mi->mi_col_map);
@@ -2174,7 +2179,6 @@
2174 pushsr_(ind, my_deref_index_data, (XTIndexPtr) xt_calloc(self, MX_OFFSETOF(XTIndexRec, mi_seg) + sizeof(XTIndexSegRec) * index->key_parts));2179 pushsr_(ind, my_deref_index_data, (XTIndexPtr) xt_calloc(self, MX_OFFSETOF(XTIndexRec, mi_seg) + sizeof(XTIndexSegRec) * index->key_parts));
21752180
2176 XT_INDEX_INIT_LOCK(self, ind);2181 XT_INDEX_INIT_LOCK(self, ind);
2177 xt_init_mutex_with_autoname(self, &ind->mi_flush_lock);
2178 xt_spinlock_init_with_autoname(self, &ind->mi_dirty_lock);2182 xt_spinlock_init_with_autoname(self, &ind->mi_dirty_lock);
2179 ind->mi_index_no = idx;2183 ind->mi_index_no = idx;
2180 ind->mi_flags = (index->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL | HA_UNIQUE_CHECK));2184 ind->mi_flags = (index->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL | HA_UNIQUE_CHECK));
@@ -2556,8 +2560,12 @@
2556 ave_row_size += 3 + ave_data_size;2560 ave_row_size += 3 + ave_data_size;
25572561
2558 /* This is the length of the record required for all indexes: */2562 /* This is the length of the record required for all indexes: */
2559 if (field_count + 1 == dic->dic_ind_cols_req)2563 /* This was calculated incorrectly. Not a serius bug because it
2560 dic->dic_ind_rec_len = max_data_size;2564 * is only used in the case of fixed length row, and in this
2565 * case the dic_ind_rec_len is set correctly below.
2566 */
2567 if (field_count == dic->dic_ind_cols_req)
2568 dic->dic_ind_rec_len = max_row_size;
2561 }2569 }
25622570
2563 dic->dic_min_row_size = min_row_size;2571 dic->dic_min_row_size = min_row_size;
@@ -2624,6 +2632,20 @@
2624 }2632 }
2625 }2633 }
26262634
2635 /* Ensure that handle data record size is big enough to
2636 * include the extended record reference, in the case of
2637 * variable length rows
2638 */
2639 if (!dic_rec_fixed) {
2640 if (dic_rec_size < offsetof(XTTabRecExtDRec, re_data))
2641 dic_rec_size = offsetof(XTTabRecExtDRec, re_data);
2642 }
2643#ifdef DEBUG
2644 else {
2645 ASSERT_NS(dic_rec_size > offsetof(XTTabRecFix, rf_data));
2646 }
2647#endif
2648
2627 if (!dic->dic_rec_size) {2649 if (!dic->dic_rec_size) {
2628 dic->dic_rec_size = dic_rec_size;2650 dic->dic_rec_size = dic_rec_size;
2629 dic->dic_rec_fixed = dic_rec_fixed;2651 dic->dic_rec_fixed = dic_rec_fixed;
@@ -2861,6 +2883,7 @@
2861 for (key_part = key->key_part; key_part != key_part_end; key_part++) {2883 for (key_part = key->key_part; key_part != key_part_end; key_part++) {
2862 if (!(cref = new XTDDColumnRef()))2884 if (!(cref = new XTDDColumnRef()))
2863 xt_throw_errno(XT_CONTEXT, XT_ENOMEM);2885 xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
2886 cref->init(self);
2864 ind->co_cols.append(self, cref);2887 ind->co_cols.append(self, cref);
2865 cref->cr_col_name = xt_dup_string(self, (char *) key_part->field->field_name);2888 cref->cr_col_name = xt_dup_string(self, (char *) key_part->field->field_name);
2866 }2889 }
28672890
=== modified file 'storage/pbxt/src/pthread_xt.cc'
--- storage/pbxt/src/pthread_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/pthread_xt.cc 2010-05-07 08:52:27 +0000
@@ -39,25 +39,25 @@
3939
40#ifdef XT_WIN40#ifdef XT_WIN
4141
42void xt_p_init_threading(void)42xtPublic void xt_p_init_threading(void)
43{43{
44}44}
4545
46int xt_p_set_normal_priority(pthread_t thr)46xtPublic int xt_p_set_normal_priority(pthread_t thr)
47{47{
48 if (!SetThreadPriority (thr, THREAD_PRIORITY_NORMAL))48 if (!SetThreadPriority (thr, THREAD_PRIORITY_NORMAL))
49 return GetLastError();49 return GetLastError();
50 return 0;50 return 0;
51}51}
5252
53int xt_p_set_low_priority(pthread_t thr)53xtPublic int xt_p_set_low_priority(pthread_t thr)
54{54{
55 if (!SetThreadPriority (thr, THREAD_PRIORITY_LOWEST))55 if (!SetThreadPriority (thr, THREAD_PRIORITY_LOWEST))
56 return GetLastError();56 return GetLastError();
57 return 0;57 return 0;
58}58}
5959
60int xt_p_set_high_priority(pthread_t thr)60xtPublic int xt_p_set_high_priority(pthread_t thr)
61{61{
62 if (!SetThreadPriority (thr, THREAD_PRIORITY_HIGHEST))62 if (!SetThreadPriority (thr, THREAD_PRIORITY_HIGHEST))
63 return GetLastError();63 return GetLastError();
@@ -67,9 +67,9 @@
67#define XT_RWLOCK_MAGIC 0x78AC390E67#define XT_RWLOCK_MAGIC 0x78AC390E
6868
69#ifdef XT_THREAD_LOCK_INFO69#ifdef XT_THREAD_LOCK_INFO
70int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr, const char *n)70xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr, const char *n)
71#else71#else
72int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr)72xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr)
73#endif73#endif
74{74{
75 InitializeCriticalSection(&mutex->mt_cs);75 InitializeCriticalSection(&mutex->mt_cs);
@@ -80,7 +80,7 @@
80 return 0;80 return 0;
81}81}
8282
83int xt_p_mutex_destroy(xt_mutex_type *mutex)83xtPublic int xt_p_mutex_destroy(xt_mutex_type *mutex)
84{84{
85 DeleteCriticalSection(&mutex->mt_cs);85 DeleteCriticalSection(&mutex->mt_cs);
86#ifdef XT_THREAD_LOCK_INFO86#ifdef XT_THREAD_LOCK_INFO
@@ -89,7 +89,7 @@
89 return 0;89 return 0;
90}90}
9191
92int xt_p_mutex_lock(xt_mutex_type *mx)92xtPublic int xt_p_mutex_lock(xt_mutex_type *mx)
93{93{
94 EnterCriticalSection(&mx->mt_cs);94 EnterCriticalSection(&mx->mt_cs);
95#ifdef XT_THREAD_LOCK_INFO95#ifdef XT_THREAD_LOCK_INFO
@@ -98,7 +98,7 @@
98 return 0;98 return 0;
99}99}
100100
101int xt_p_mutex_unlock(xt_mutex_type *mx)101xtPublic int xt_p_mutex_unlock(xt_mutex_type *mx)
102{102{
103 LeaveCriticalSection(&mx->mt_cs);103 LeaveCriticalSection(&mx->mt_cs);
104#ifdef XT_THREAD_LOCK_INFO104#ifdef XT_THREAD_LOCK_INFO
@@ -107,7 +107,7 @@
107 return 0;107 return 0;
108}108}
109109
110int xt_p_mutex_trylock(xt_mutex_type *mutex)110xtPublic int xt_p_mutex_trylock(xt_mutex_type *mutex)
111{111{
112#if(_WIN32_WINNT >= 0x0400)112#if(_WIN32_WINNT >= 0x0400)
113 /* NOTE: MySQL bug! was using?!113 /* NOTE: MySQL bug! was using?!
@@ -130,9 +130,9 @@
130}130}
131131
132#ifdef XT_THREAD_LOCK_INFO132#ifdef XT_THREAD_LOCK_INFO
133int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr, const char *n)133xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr, const char *n)
134#else134#else
135int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr)135xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr)
136#endif136#endif
137{137{
138 int result;138 int result;
@@ -173,7 +173,7 @@
173 return result;173 return result;
174}174}
175175
176int xt_p_rwlock_destroy(xt_rwlock_type *rwl)176xtPublic int xt_p_rwlock_destroy(xt_rwlock_type *rwl)
177{177{
178 int result = 0, result1 = 0, result2 = 0;178 int result = 0, result1 = 0, result2 = 0;
179179
@@ -225,7 +225,7 @@
225}225}
226226
227227
228int xt_p_rwlock_rdlock(xt_rwlock_type *rwl)228xtPublic int xt_p_rwlock_rdlock(xt_rwlock_type *rwl)
229{229{
230 int result;230 int result;
231231
@@ -262,7 +262,7 @@
262 return (xt_p_mutex_unlock (&(rwl->rw_ex_lock)));262 return (xt_p_mutex_unlock (&(rwl->rw_ex_lock)));
263}263}
264264
265int xt_p_rwlock_wrlock(xt_rwlock_type *rwl)265xtPublic int xt_p_rwlock_wrlock(xt_rwlock_type *rwl)
266{266{
267 int result;267 int result;
268268
@@ -309,7 +309,54 @@
309 return result;309 return result;
310}310}
311311
312int xt_p_rwlock_unlock(xt_rwlock_type *rwl)312xtPublic xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwl)
313{
314 int result;
315
316 if (rwl == NULL)
317 return FALSE;
318
319 if (rwl->rw_magic != XT_RWLOCK_MAGIC)
320 return FALSE;
321
322 if ((result = xt_p_mutex_trylock(&rwl->rw_ex_lock)) != 0)
323 return FALSE;
324
325 if ((result = xt_p_mutex_lock(&rwl->rw_sh_lock)) != 0) {
326 (void) xt_p_mutex_unlock(&rwl->rw_ex_lock);
327 return FALSE;
328 }
329
330 if (rwl->rw_ex_count == 0) {
331 if (rwl->rw_sh_complete_count > 0) {
332 rwl->rw_sh_count -= rwl->rw_sh_complete_count;
333 rwl->rw_sh_complete_count = 0;
334 }
335
336 if (rwl->rw_sh_count > 0) {
337 rwl->rw_sh_complete_count = -rwl->rw_sh_count;
338
339 do {
340 result = pthread_cond_wait (&rwl->rw_sh_cond, &rwl->rw_sh_lock.mt_cs);
341 }
342 while (result == 0 && rwl->rw_sh_complete_count < 0);
343
344 if (result == 0)
345 rwl->rw_sh_count = 0;
346 }
347 }
348
349 if (result == 0)
350 rwl->rw_ex_count++;
351
352#ifdef XT_THREAD_LOCK_INFO
353 xt_thread_lock_info_add_owner(&rwl->rw_lock_info);
354#endif
355
356 return TRUE;
357}
358
359xtPublic int xt_p_rwlock_unlock(xt_rwlock_type *rwl)
313{360{
314 int result, result1;361 int result, result1;
315362
@@ -342,12 +389,12 @@
342 return ((result != 0) ? result : result1);389 return ((result != 0) ? result : result1);
343}390}
344391
345int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex)392xtPublic int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex)
346{393{
347 return xt_p_cond_timedwait(cond, mutex, NULL);394 return xt_p_cond_timedwait(cond, mutex, NULL);
348}395}
349396
350int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mt, struct timespec *abstime)397xtPublic int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mt, struct timespec *abstime)
351{398{
352 pthread_mutex_t *mutex = &mt->mt_cs;399 pthread_mutex_t *mutex = &mt->mt_cs;
353 int result;400 int result;
@@ -393,7 +440,7 @@
393 return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;440 return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
394}441}
395442
396int xt_p_join(pthread_t thread, void **value)443xtPublic int xt_p_join(pthread_t thread, void **value)
397{444{
398 DWORD exitcode;445 DWORD exitcode;
399446
@@ -676,6 +723,23 @@
676 return r;723 return r;
677}724}
678725
726xtPublic xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwlock)
727{
728 XTThreadPtr self = xt_get_self();
729 int r;
730
731 ASSERT_NS(rwlock->rw_init == 67890);
732 r = pthread_rwlock_trywrlock(&rwlock->rw_plock);
733 if (r == 0) {
734 ASSERT_NS(!rwlock->rw_locker);
735 rwlock->rw_locker = self;
736#ifdef XT_THREAD_LOCK_INFO
737 xt_thread_lock_info_add_owner(&rwlock->rw_lock_info);
738#endif
739 }
740 return r == 0;
741}
742
679xtPublic int xt_p_rwlock_unlock(xt_rwlock_type *rwlock)743xtPublic int xt_p_rwlock_unlock(xt_rwlock_type *rwlock)
680{744{
681 XTThreadPtr self = xt_get_self();745 XTThreadPtr self = xt_get_self();
682746
=== modified file 'storage/pbxt/src/pthread_xt.h'
--- storage/pbxt/src/pthread_xt.h 2009-03-26 12:18:01 +0000
+++ storage/pbxt/src/pthread_xt.h 2010-05-07 08:52:27 +0000
@@ -101,13 +101,14 @@
101#else101#else
102int xt_p_rwlock_init(xt_rwlock_type *rwlock, const pthread_condattr_t *attr);102int xt_p_rwlock_init(xt_rwlock_type *rwlock, const pthread_condattr_t *attr);
103#endif103#endif
104int xt_p_rwlock_destroy(xt_rwlock_type *rwlock);104int xt_p_rwlock_destroy(xt_rwlock_type *rwlock);
105int xt_p_rwlock_rdlock(xt_rwlock_type *mx);105int xt_p_rwlock_rdlock(xt_rwlock_type *mx);
106int xt_p_rwlock_wrlock(xt_rwlock_type *mx);106int xt_p_rwlock_wrlock(xt_rwlock_type *mx);
107int xt_p_rwlock_unlock(xt_rwlock_type *mx);107xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwl);
108int xt_p_rwlock_unlock(xt_rwlock_type *mx);
108109
109int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex);110int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex);
110int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mutex, struct timespec *abstime);111int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mutex, struct timespec *abstime);
111112
112int xt_p_join(pthread_t thread, void **value);113int xt_p_join(pthread_t thread, void **value);
113114
@@ -125,6 +126,7 @@
125126
126#define xt_slock_rwlock_ns xt_p_rwlock_rdlock127#define xt_slock_rwlock_ns xt_p_rwlock_rdlock
127#define xt_xlock_rwlock_ns xt_p_rwlock_wrlock128#define xt_xlock_rwlock_ns xt_p_rwlock_wrlock
129#define xt_xlock_try_rwlock_ns xt_p_rwlock_try_wrlock
128#define xt_unlock_rwlock_ns xt_p_rwlock_unlock130#define xt_unlock_rwlock_ns xt_p_rwlock_unlock
129131
130#ifdef XT_THREAD_LOCK_INFO132#ifdef XT_THREAD_LOCK_INFO
@@ -225,9 +227,10 @@
225#endif227#endif
226} xt_rwlock_type;228} xt_rwlock_type;
227229
228int xt_p_rwlock_rdlock(xt_rwlock_type *mx);230int xt_p_rwlock_rdlock(xt_rwlock_type *mx);
229int xt_p_rwlock_wrlock(xt_rwlock_type *mx);231int xt_p_rwlock_wrlock(xt_rwlock_type *mx);
230int xt_p_rwlock_unlock(xt_rwlock_type *mx);232xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *mx);
233int xt_p_rwlock_unlock(xt_rwlock_type *mx);
231234
232int xt_p_mutex_lock(xt_mutex_type *mx, u_int line, const char *file);235int xt_p_mutex_lock(xt_mutex_type *mx, u_int line, const char *file);
233int xt_p_mutex_unlock(xt_mutex_type *mx);236int xt_p_mutex_unlock(xt_mutex_type *mx);
@@ -251,37 +254,39 @@
251}254}
252#endif255#endif
253256
254#define xt_slock_rwlock_ns xt_p_rwlock_rdlock257#define xt_slock_rwlock_ns xt_p_rwlock_rdlock
255#define xt_xlock_rwlock_ns xt_p_rwlock_wrlock258#define xt_xlock_rwlock_ns xt_p_rwlock_wrlock
256#define xt_unlock_rwlock_ns xt_p_rwlock_unlock259#define xt_xlock_try_rwlock_ns xt_p_rwlock_try_wrlock
260#define xt_unlock_rwlock_ns xt_p_rwlock_unlock
257261
258#define xt_lock_mutex_ns(x) xt_p_mutex_lock(x, __LINE__, __FILE__)262#define xt_lock_mutex_ns(x) xt_p_mutex_lock(x, __LINE__, __FILE__)
259#define xt_unlock_mutex_ns xt_p_mutex_unlock263#define xt_unlock_mutex_ns xt_p_mutex_unlock
260#define xt_mutex_trylock xt_p_mutex_trylock264#define xt_mutex_trylock xt_p_mutex_trylock
261265
262#else // DEBUG_LOCKING266#else // DEBUG_LOCKING
263267
264#define xt_rwlock_struct _opaque_pthread_rwlock_t268#define xt_rwlock_struct _opaque_pthread_rwlock_t
265#define xt_mutex_struct _opaque_pthread_mutex_t269#define xt_mutex_struct _opaque_pthread_mutex_t
266270
267#define xt_rwlock_type pthread_rwlock_t271#define xt_rwlock_type pthread_rwlock_t
268#define xt_mutex_type pthread_mutex_t272#define xt_mutex_type pthread_mutex_t
269273
270#define xt_slock_rwlock_ns pthread_rwlock_rdlock274#define xt_slock_rwlock_ns pthread_rwlock_rdlock
271#define xt_xlock_rwlock_ns pthread_rwlock_wrlock275#define xt_xlock_rwlock_ns pthread_rwlock_wrlock
272#define xt_unlock_rwlock_ns pthread_rwlock_unlock276#define xt_xlock_try_rwlock_ns(x) (pthread_rwlock_trywrlock(x) == 0)
273277#define xt_unlock_rwlock_ns pthread_rwlock_unlock
274#define xt_lock_mutex_ns pthread_mutex_lock278
275#define xt_unlock_mutex_ns pthread_mutex_unlock279#define xt_lock_mutex_ns pthread_mutex_lock
276#define xt_mutex_trylock pthread_mutex_trylock280#define xt_unlock_mutex_ns pthread_mutex_unlock
277281#define xt_mutex_trylock pthread_mutex_trylock
278#define xt_p_mutex_trylock pthread_mutex_trylock282
279#define xt_p_mutex_destroy pthread_mutex_destroy283#define xt_p_mutex_trylock pthread_mutex_trylock
280#define xt_p_mutex_init pthread_mutex_init284#define xt_p_mutex_destroy pthread_mutex_destroy
281#define xt_p_rwlock_destroy pthread_rwlock_destroy285#define xt_p_mutex_init pthread_mutex_init
282#define xt_p_rwlock_init pthread_rwlock_init286#define xt_p_rwlock_destroy pthread_rwlock_destroy
283#define xt_p_cond_wait pthread_cond_wait287#define xt_p_rwlock_init pthread_rwlock_init
284#define xt_p_cond_timedwait pthread_cond_timedwait288#define xt_p_cond_wait pthread_cond_wait
289#define xt_p_cond_timedwait pthread_cond_timedwait
285290
286#endif // DEBUG_LOCKING291#endif // DEBUG_LOCKING
287292
288293
=== modified file 'storage/pbxt/src/restart_xt.cc'
--- storage/pbxt/src/restart_xt.cc 2010-01-06 21:27:53 +0000
+++ storage/pbxt/src/restart_xt.cc 2010-05-07 08:52:27 +0000
@@ -1315,7 +1315,7 @@
1315 tab->tab_head_op_seq = op->or_op_seq;1315 tab->tab_head_op_seq = op->or_op_seq;
1316 if (tab->tab_wr_wake_freeer) {1316 if (tab->tab_wr_wake_freeer) {
1317 if (!XTTableSeq::xt_op_is_before(tab->tab_head_op_seq, tab->tab_wake_freeer_op))1317 if (!XTTableSeq::xt_op_is_before(tab->tab_head_op_seq, tab->tab_wake_freeer_op))
1318 xt_wr_wake_freeer(self);1318 xt_wr_wake_freeer(self, ws->ws_db);
1319 }1319 }
1320 i++;1320 i++;
1321 }1321 }
@@ -1498,7 +1498,7 @@
1498 tab->tab_head_op_seq = op_seq;1498 tab->tab_head_op_seq = op_seq;
1499 if (tab->tab_wr_wake_freeer) {1499 if (tab->tab_wr_wake_freeer) {
1500 if (!XTTableSeq::xt_op_is_before(tab->tab_head_op_seq, tab->tab_wake_freeer_op))1500 if (!XTTableSeq::xt_op_is_before(tab->tab_head_op_seq, tab->tab_wake_freeer_op))
1501 xt_wr_wake_freeer(self);1501 xt_wr_wake_freeer(self, ws->ws_db);
1502 }1502 }
15031503
1504 /* Apply any operations in the list that now follow on...1504 /* Apply any operations in the list that now follow on...
@@ -1575,10 +1575,12 @@
1575static void xres_init_checkpoint_state(XTThreadPtr self, XTCheckPointStatePtr cp)1575static void xres_init_checkpoint_state(XTThreadPtr self, XTCheckPointStatePtr cp)
1576{1576{
1577 xt_init_mutex_with_autoname(self, &cp->cp_state_lock);1577 xt_init_mutex_with_autoname(self, &cp->cp_state_lock);
1578 cp->cp_inited = TRUE;
1578}1579}
15791580
1580static void xres_free_checkpoint_state(XTThreadPtr self, XTCheckPointStatePtr cp)1581static void xres_free_checkpoint_state(XTThreadPtr self, XTCheckPointStatePtr cp)
1581{1582{
1583 cp->cp_inited = FALSE;
1582 xt_free_mutex(&cp->cp_state_lock);1584 xt_free_mutex(&cp->cp_state_lock);
1583 if (cp->cp_table_ids) {1585 if (cp->cp_table_ids) {
1584 xt_free_sortedlist(self, cp->cp_table_ids);1586 xt_free_sortedlist(self, cp->cp_table_ids);
@@ -1616,6 +1618,7 @@
16161618
1617 xt_init_mutex_with_autoname(self, &db->db_cp_lock);1619 xt_init_mutex_with_autoname(self, &db->db_cp_lock);
1618 xt_init_cond(self, &db->db_cp_cond);1620 xt_init_cond(self, &db->db_cp_cond);
1621 xt_init_mutex_with_autoname(self, &db->db_fl_lock);
1619 1622
1620 xres_init_checkpoint_state(self, &db->db_cp_state);1623 xres_init_checkpoint_state(self, &db->db_cp_state);
1621 db->db_restart.xres_init(self, db, &db->db_wr_log_id, &db->db_wr_log_offset, &max_log_id);1624 db->db_restart.xres_init(self, db, &db->db_wr_log_id, &db->db_wr_log_offset, &max_log_id);
@@ -1633,6 +1636,7 @@
1633 xres_free_checkpoint_state(self, &db->db_cp_state);1636 xres_free_checkpoint_state(self, &db->db_cp_state);
1634 xt_free_mutex(&db->db_cp_lock);1637 xt_free_mutex(&db->db_cp_lock);
1635 xt_free_cond(&db->db_cp_cond);1638 xt_free_cond(&db->db_cp_cond);
1639 xt_free_mutex(&db->db_fl_lock);
1636}1640}
16371641
1638/* ----------------------------------------------------------------------1642/* ----------------------------------------------------------------------
@@ -2182,7 +2186,7 @@
21822186
2183xtBool XTXactRestart::xres_is_checkpoint_pending(xtLogID curr_log_id, xtLogOffset curr_log_offset)2187xtBool XTXactRestart::xres_is_checkpoint_pending(xtLogID curr_log_id, xtLogOffset curr_log_offset)
2184{2188{
2185 return xt_bytes_since_last_checkpoint(xres_db, curr_log_id, curr_log_offset) >= xt_db_checkpoint_frequency / 2;2189 return xt_bytes_since_last_checkpoint(xres_db, curr_log_id, curr_log_offset) >= xt_db_checkpoint_frequency;
2186}2190}
21872191
2188/*2192/*
@@ -2531,10 +2535,10 @@
2531 XTDatabaseHPtr db = self->st_database;2535 XTDatabaseHPtr db = self->st_database;
2532 u_int curr_writer_total;2536 u_int curr_writer_total;
2533 time_t now;2537 time_t now;
2538 xtXactID sweep_count;
25342539
2535 xt_set_low_priority(self);2540 xt_set_low_priority(self);
25362541
2537
2538 while (!self->t_quit) {2542 while (!self->t_quit) {
2539 /* Wait 2 seconds: */2543 /* Wait 2 seconds: */
2540 curr_writer_total = db->db_xn_total_writer_count;2544 curr_writer_total = db->db_xn_total_writer_count;
@@ -2549,9 +2553,13 @@
2549 if (self->t_quit)2553 if (self->t_quit)
2550 break;2554 break;
25512555
2552 if (curr_writer_total == db->db_xn_total_writer_count)2556 sweep_count = db->db_xn_curr_id + 1 - db->db_xn_to_clean_id;
2557 if (curr_writer_total == db->db_xn_total_writer_count &&
2558 !sweep_count &&
2559 db->db_wr_idle == XT_THREAD_IDLE) {
2553 /* No activity in 2 seconds: */2560 /* No activity in 2 seconds: */
2554 xres_cp_checkpoint(self, db, curr_writer_total, FALSE);2561 xres_cp_checkpoint(self, db, curr_writer_total, FALSE);
2562 }
2555 else {2563 else {
2556 /* There server is busy, check if we need to2564 /* There server is busy, check if we need to
2557 * write a checkpoint anyway...2565 * write a checkpoint anyway...
@@ -2672,6 +2680,10 @@
2672 XTOperationPtr op;2680 XTOperationPtr op;
2673 XTCheckPointTableRec cpt;2681 XTCheckPointTableRec cpt;
2674 XTSortedListPtr tables = NULL;2682 XTSortedListPtr tables = NULL;
2683
2684 /* during startup we can get an error before the checkpointer is inited */
2685 if (!cp->cp_inited)
2686 return FAILED;
26752687
2676 /* First check if a checkpoint is already running: */2688 /* First check if a checkpoint is already running: */
2677 xt_lock_mutex_ns(&cp->cp_state_lock);2689 xt_lock_mutex_ns(&cp->cp_state_lock);
@@ -3314,7 +3326,7 @@
3314 * #7 0x000c0db2 in THD::~THD at sql_class.cc:9343326 * #7 0x000c0db2 in THD::~THD at sql_class.cc:934
3315 * #8 0x003b025b in myxt_destroy_thread at myxt_xt.cc:29993327 * #8 0x003b025b in myxt_destroy_thread at myxt_xt.cc:2999
3316 * #9 0x003b66b5 in xn_xres_run_recovery_thread at restart_xt.cc:31963328 * #9 0x003b66b5 in xn_xres_run_recovery_thread at restart_xt.cc:3196
3317 * #10 0x003cbfbb in thr_main_pbxt at thread_xt.cc:10203329 * #10 0x003cbfbb in xt_thread_main at thread_xt.cc:1020
3318 *3330 *
3319 myxt_destroy_thread(mysql_thread, TRUE);3331 myxt_destroy_thread(mysql_thread, TRUE);
3320 */3332 */
@@ -3350,3 +3362,123 @@
3350 xt_wait_for_thread(tid, TRUE);3362 xt_wait_for_thread(tid, TRUE);
3351 }3363 }
3352}3364}
3365
3366/* ----------------------------------------------------------------------
3367 * L O G F L U S H P R O C E S S
3368 */
3369
3370static void *xres_fl_run_thread(XTThreadPtr self)
3371{
3372 XTDatabaseHPtr db = (XTDatabaseHPtr) self->t_data;
3373 int count;
3374 void *mysql_thread;
3375 xtWord8 to_flush;
3376
3377 if (!(mysql_thread = myxt_create_thread()))
3378 xt_throw(self);
3379
3380 while (!self->t_quit) {
3381 try_(a) {
3382 /*
3383 * The garbage collector requires that the database
3384 * is in use because.
3385 */
3386 xt_use_database(self, db, XT_FOR_CHECKPOINTER);
3387
3388 /* This action is both safe and required (see details elsewhere) */
3389 xt_heap_release(self, self->st_database);
3390
3391 xt_set_low_priority(self);
3392
3393 to_flush = xt_trace_clock() + XT_XLOG_FLUSH_FREQ * 1000;
3394 for (;;) {
3395 /* Wait 1 second: */
3396 while (!self->t_quit && xt_trace_clock() < to_flush)
3397 xt_sleep_milli_second(10);
3398
3399 if (self->t_quit)
3400 break;
3401
3402 if (!db->db_xlog.xlog_flush(self))
3403 xt_throw(self);
3404
3405 to_flush += XT_XLOG_FLUSH_FREQ * 1000;
3406 }
3407 }
3408 catch_(a) {
3409 /* This error is "normal"! */
3410 if (self->t_exception.e_xt_err != XT_ERR_NO_DICTIONARY &&
3411 !(self->t_exception.e_xt_err == XT_SIGNAL_CAUGHT &&
3412 self->t_exception.e_sys_err == SIGTERM))
3413 xt_log_and_clear_exception(self);
3414 }
3415 cont_(a);
3416
3417 /* Avoid releasing the database (done above) */
3418 self->st_database = NULL;
3419 xt_unuse_database(self, self);
3420
3421 /* After an exception, pause before trying again... */
3422 /* Number of seconds */
3423 count = 60;
3424 while (!self->t_quit && count > 0) {
3425 sleep(1);
3426 count--;
3427 }
3428 }
3429
3430 /*
3431 * {MYSQL-THREAD-KILL}
3432 myxt_destroy_thread(mysql_thread, TRUE);
3433 */
3434 return NULL;
3435}
3436
3437static void xres_fl_free_thread(XTThreadPtr self, void *data)
3438{
3439 XTDatabaseHPtr db = (XTDatabaseHPtr) data;
3440
3441 if (db->db_fl_thread) {
3442 xt_lock_mutex(self, &db->db_fl_lock);
3443 pushr_(xt_unlock_mutex, &db->db_fl_lock);
3444 db->db_fl_thread = NULL;
3445 freer_(); // xt_unlock_mutex(&db->db_fl_lock)
3446 }
3447}
3448
3449xtPublic void xt_start_flusher(XTThreadPtr self, XTDatabaseHPtr db)
3450{
3451 char name[PATH_MAX];
3452
3453 sprintf(name, "FL-%s", xt_last_directory_of_path(db->db_main_path));
3454 xt_remove_dir_char(name);
3455 db->db_fl_thread = xt_create_daemon(self, name);
3456 xt_set_thread_data(db->db_fl_thread, db, xres_fl_free_thread);
3457 xt_run_thread(self, db->db_fl_thread, xres_fl_run_thread);
3458}
3459
3460xtPublic void xt_stop_flusher(XTThreadPtr self, XTDatabaseHPtr db)
3461{
3462 XTThreadPtr thr_fl;
3463
3464 if (db->db_fl_thread) {
3465 xt_lock_mutex(self, &db->db_fl_lock);
3466 pushr_(xt_unlock_mutex, &db->db_fl_lock);
3467
3468 /* This pointer is safe as long as you have the transaction lock. */
3469 if ((thr_fl = db->db_fl_thread)) {
3470 xtThreadID tid = thr_fl->t_id;
3471
3472 /* Make sure the thread quits when woken up. */
3473 xt_terminate_thread(self, thr_fl);
3474
3475 freer_(); // xt_unlock_mutex(&db->db_cp_lock)
3476
3477 xt_wait_for_thread(tid, FALSE);
3478 db->db_fl_thread = NULL;
3479 }
3480 else
3481 freer_(); // xt_unlock_mutex(&db->db_cp_lock)
3482 }
3483}
3484
33533485
=== modified file 'storage/pbxt/src/restart_xt.h'
--- storage/pbxt/src/restart_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/restart_xt.h 2010-05-07 08:52:27 +0000
@@ -92,6 +92,7 @@
92} XTXactRestartRec, *XTXactRestartPtr;92} XTXactRestartRec, *XTXactRestartPtr;
9393
94typedef struct XTCheckPointState {94typedef struct XTCheckPointState {
95 xtBool cp_inited; /* TRUE if structure was inited */
95 xt_mutex_type cp_state_lock; /* Lock and the entire checkpoint state. */96 xt_mutex_type cp_state_lock; /* Lock and the entire checkpoint state. */
96 xtBool cp_running; /* TRUE if a checkpoint is running. */97 xtBool cp_running; /* TRUE if a checkpoint is running. */
97 xtLogID cp_log_id;98 xtLogID cp_log_id;
@@ -136,6 +137,9 @@
136void xt_xres_start_database_recovery(XTThreadPtr self);137void xt_xres_start_database_recovery(XTThreadPtr self);
137void xt_xres_terminate_recovery(XTThreadPtr self);138void xt_xres_terminate_recovery(XTThreadPtr self);
138139
140void xt_start_flusher(struct XTThread *self, struct XTDatabase *db);
141void xt_stop_flusher(struct XTThread *self, struct XTDatabase *db);
142
139#define XT_RECOVER_PENDING 0143#define XT_RECOVER_PENDING 0
140#define XT_RECOVER_DONE 1144#define XT_RECOVER_DONE 1
141#define XT_RECOVER_SWEPT 2145#define XT_RECOVER_SWEPT 2
142146
=== modified file 'storage/pbxt/src/strutil_xt.cc'
--- storage/pbxt/src/strutil_xt.cc 2009-12-21 13:13:15 +0000
+++ storage/pbxt/src/strutil_xt.cc 2010-05-07 08:52:27 +0000
@@ -380,7 +380,7 @@
380/* Version number must also be set in configure.in! */380/* Version number must also be set in configure.in! */
381xtPublic c_char *xt_get_version(void)381xtPublic c_char *xt_get_version(void)
382{382{
383 return "1.0.09g RC";383 return "1.0.11 Pre-GA";
384}384}
385385
386/* Copy and URL decode! */386/* Copy and URL decode! */
387387
=== modified file 'storage/pbxt/src/tabcache_xt.cc'
--- storage/pbxt/src/tabcache_xt.cc 2009-11-27 15:37:02 +0000
+++ storage/pbxt/src/tabcache_xt.cc 2010-05-07 08:52:27 +0000
@@ -46,8 +46,10 @@
46xtPublic void xt_tc_set_cache_size(size_t cache_size)46xtPublic void xt_tc_set_cache_size(size_t cache_size)
47{47{
48 xt_tab_cache.tcm_cache_size = cache_size;48 xt_tab_cache.tcm_cache_size = cache_size;
49 xt_tab_cache.tcm_low_level = cache_size / 4 * 3; // Current 75%49 /* Multiplying by this number can overflow a 4 byte value! */
50 xt_tab_cache.tcm_high_level = cache_size / 100 * 95; // Current 95%50 xt_tab_cache.tcm_low_level = (size_t) ((xtWord8) cache_size * (xtWord8) 70 / (xtWord8) 100); // Current 70%
51 xt_tab_cache.tcm_high_level = (size_t) ((xtWord8) cache_size * 95 / (xtWord8) 100); // Current 95%
52 xt_tab_cache.tcm_mid_level = (size_t) ((xtWord8) cache_size * 85 / (xtWord8) 100); // Current 85%
51}53}
5254
53/*55/*
@@ -84,25 +86,30 @@
8486
85xtPublic void xt_tc_exit(XTThreadPtr self)87xtPublic void xt_tc_exit(XTThreadPtr self)
86{88{
89 XTTabCacheSegPtr seg;
90
87 for (u_int i=0; i<XT_TC_SEGMENT_COUNT; i++) {91 for (u_int i=0; i<XT_TC_SEGMENT_COUNT; i++) {
88 if (xt_tab_cache.tcm_segment[i].tcs_hash_table) {92 seg = &xt_tab_cache.tcm_segment[i];
89 if (xt_tab_cache.tcm_segment[i].tcs_cache_in_use) {93 if (seg->tcs_hash_table) {
90 XTTabCachePagePtr page, tmp_page;94 XTTabCachePagePtr page, tmp_page;
9195
92 for (size_t j=0; j<xt_tab_cache.tcm_hash_size; j++) {96 for (size_t j=0; j<xt_tab_cache.tcm_hash_size; j++) {
93 page = xt_tab_cache.tcm_segment[i].tcs_hash_table[j];97 page = seg->tcs_hash_table[j];
94 while (page) {98 while (page) {
95 tmp_page = page;99 tmp_page = page;
96 page = page->tcp_next;100 page = page->tcp_next;
97 xt_free(self, tmp_page);101 ASSERT_NS(seg->tcs_cache_in_use >= offsetof(XTTabCachePageRec, tcp_data) + tmp_page->tcp_data_size);
98 }102 seg->tcs_cache_in_use -= (offsetof(XTTabCachePageRec, tcp_data) + tmp_page->tcp_data_size);
103 ASSERT_NS(seg->tcs_cache_in_use == 0 || seg->tcs_cache_in_use >= 25000);
104 xt_free(self, tmp_page);
99 }105 }
100 }106 }
101107
102 xt_free(self, xt_tab_cache.tcm_segment[i].tcs_hash_table);108 xt_free(self, seg->tcs_hash_table);
103 xt_tab_cache.tcm_segment[i].tcs_hash_table = NULL;109 seg->tcs_hash_table = NULL;
104 TAB_CAC_FREE_LOCK(self, &xt_tab_cache.tcm_segment[i].tcs_lock);110 TAB_CAC_FREE_LOCK(self, &seg->tcs_lock);
105 }111 }
112 ASSERT_NS(seg->tcs_cache_in_use == 0);
106 }113 }
107114
108 xt_free_mutex(&xt_tab_cache.tcm_lock);115 xt_free_mutex(&xt_tab_cache.tcm_lock);
@@ -554,24 +561,24 @@
554 }561 }
555 page = page->tcp_next;562 page = page->tcp_next;
556 }563 }
564
565 size_t page_size = offsetof(XTTabCachePageRec, tcp_data) + this->tci_page_size;
566
557 TAB_CAC_UNLOCK(&seg->tcs_lock, thread->t_id);567 TAB_CAC_UNLOCK(&seg->tcs_lock, thread->t_id);
558 568
559 /* Page not found, allocate a new page: */569 /* Page not found, allocate a new page: */
560 size_t page_size = offsetof(XTTabCachePageRec, tcp_data) + this->tci_page_size;
561 if (!(new_page = (XTTabCachePagePtr) xt_malloc_ns(page_size)))570 if (!(new_page = (XTTabCachePagePtr) xt_malloc_ns(page_size)))
562 return FAILED;571 return FAILED;
563 /* Increment cache used. */
564 seg->tcs_cache_in_use += page_size;
565572
566 /* Check the level of the cache: */573 /* Check the level of the cache: */
567 size_t cache_used = 0;574 size_t cache_used = 0;
568 for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)575 for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)
569 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;576 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
570577
571 if (cache_used > dcg->tcm_cache_high)578 if (cache_used + page_size > dcg->tcm_cache_high)
572 dcg->tcm_cache_high = cache_used;579 dcg->tcm_cache_high = cache_used;
573580
574 if (cache_used > dcg->tcm_cache_size) {581 if (cache_used + page_size > dcg->tcm_cache_size) {
575 XTThreadPtr self;582 XTThreadPtr self;
576 time_t now;583 time_t now;
577584
@@ -638,7 +645,7 @@
638 for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)645 for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)
639 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;646 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
640647
641 if (cache_used <= dcg->tcm_high_level)648 if (cache_used + page_size <= dcg->tcm_high_level)
642 break;649 break;
643 /*650 /*
644 * If there is too little cache we can get stuck here.651 * If there is too little cache we can get stuck here.
@@ -663,7 +670,7 @@
663 while (time(NULL) < now + 5);670 while (time(NULL) < now + 5);
664 xt_unlock_mutex_ns(&dcg->tcm_freeer_lock);671 xt_unlock_mutex_ns(&dcg->tcm_freeer_lock);
665 }672 }
666 else if (cache_used > dcg->tcm_high_level) {673 else if (cache_used + page_size > dcg->tcm_high_level) {
667 /* Wake up the freeer because the cache level,674 /* Wake up the freeer because the cache level,
668 * is higher than the high level.675 * is higher than the high level.
669 */676 */
@@ -693,6 +700,9 @@
693 }700 }
694 701
695#ifdef XT_MEMSET_UNUSED_SPACE702#ifdef XT_MEMSET_UNUSED_SPACE
703 else
704 red_size = 0;
705
696 /* Removing this is an optimization. It should not be required706 /* Removing this is an optimization. It should not be required
697 * to clear the unused space in the page.707 * to clear the unused space in the page.
698 */708 */
@@ -727,6 +737,15 @@
727 page->tcp_next = seg->tcs_hash_table[hash_idx];737 page->tcp_next = seg->tcs_hash_table[hash_idx];
728 seg->tcs_hash_table[hash_idx] = page;738 seg->tcs_hash_table[hash_idx] = page;
729739
740 /* GOTCHA! This increment was done just after the malloc!
741 * So it was not protected by the segment lock!
742 * The result was that this count was no longer reliable,
743 * This resulted in the amount of cache being used becoming less, and\
744 * less, because increments were lost over time!
745 */
746 /* Increment cache used. */
747 seg->tcs_cache_in_use += page_size;
748
730 done_ok:749 done_ok:
731 *ret_seg = seg;750 *ret_seg = seg;
732 *ret_page = page;751 *ret_page = page;
@@ -761,7 +780,7 @@
761 * some will be missing, so the writer will not780 * some will be missing, so the writer will not
762 * be able to contniue.781 * be able to contniue.
763 */782 */
764 return xt_xlog_log_data(thread, sizeof(XTactNoOpEntryDRec), (XTXactLogBufferDPtr) &ent_rec, FALSE);783 return xt_xlog_log_data(thread, sizeof(XTactNoOpEntryDRec), (XTXactLogBufferDPtr) &ent_rec, XT_XLOG_NO_WRITE_NO_FLUSH);
765}784}
766785
767#ifdef XT_NOT_INLINE786#ifdef XT_NOT_INLINE
@@ -828,13 +847,23 @@
828/*847/*
829 * Used by the writer to wake the freeer.848 * Used by the writer to wake the freeer.
830 */849 */
831xtPublic void xt_wr_wake_freeer(XTThreadPtr self)850xtPublic void xt_wr_wake_freeer(XTThreadPtr self, XTDatabaseHPtr db)
832{851{
852 /* BUG FIX: Was using tcm_freeer_cond.
853 * This is incorrect. When the freeer waits for the
854 * writter, it uses the writer's condition!
855 */
856 xt_lock_mutex_ns(&db->db_wr_lock);
857 if (!xt_broadcast_cond_ns(&db->db_wr_cond))
858 xt_log_and_clear_exception_ns();
859 xt_unlock_mutex_ns(&db->db_wr_lock);
860/*
833 xt_lock_mutex(self, &xt_tab_cache.tcm_freeer_lock);861 xt_lock_mutex(self, &xt_tab_cache.tcm_freeer_lock);
834 pushr_(xt_unlock_mutex, &xt_tab_cache.tcm_freeer_lock);862 pushr_(xt_unlock_mutex, &xt_tab_cache.tcm_freeer_lock);
835 if (!xt_broadcast_cond_ns(&xt_tab_cache.tcm_freeer_cond))863 if (!xt_broadcast_cond_ns(&xt_tab_cache.tcm_freeer_cond))
836 xt_log_and_clear_exception_ns();864 xt_log_and_clear_exception_ns();
837 freer_(); // xt_unlock_mutex(&xt_tab_cache.tcm_freeer_lock)865 freer_(); // xt_unlock_mutex(&xt_tab_cache.tcm_freeer_lock)
866*/
838}867}
839868
840/* Wait for a transaction to quit: */869/* Wait for a transaction to quit: */
@@ -1070,7 +1099,9 @@
10701099
1071 /* Free the page: */1100 /* Free the page: */
1072 size_t freed_space = offsetof(XTTabCachePageRec, tcp_data) + page->tcp_data_size;1101 size_t freed_space = offsetof(XTTabCachePageRec, tcp_data) + page->tcp_data_size;
1102 ASSERT_NS(seg->tcs_cache_in_use >= freed_space);
1073 seg->tcs_cache_in_use -= freed_space;1103 seg->tcs_cache_in_use -= freed_space;
1104 ASSERT_NS(seg->tcs_cache_in_use == 0 || seg->tcs_cache_in_use >= 25000);
1074 xt_free_ns(page);1105 xt_free_ns(page);
10751106
1076 TAB_CAC_UNLOCK(&seg->tcs_lock, self->t_id);1107 TAB_CAC_UNLOCK(&seg->tcs_lock, self->t_id);
@@ -1083,6 +1114,7 @@
1083{1114{
1084 register XTTabCacheMemPtr dcg = &xt_tab_cache;1115 register XTTabCacheMemPtr dcg = &xt_tab_cache;
1085 TCResourceRec tc = { 0 };1116 TCResourceRec tc = { 0 };
1117 int i;
10861118
1087 xt_set_low_priority(self);1119 xt_set_low_priority(self);
1088 dcg->tcm_freeer_busy = TRUE;1120 dcg->tcm_freeer_busy = TRUE;
@@ -1095,14 +1127,20 @@
1095 while (!self->t_quit) {1127 while (!self->t_quit) {
1096 /* Total up the cache memory used: */1128 /* Total up the cache memory used: */
1097 cache_used = 0;1129 cache_used = 0;
1098 for (int i=0; i<XT_TC_SEGMENT_COUNT; i++)1130 for (i=0; i<XT_TC_SEGMENT_COUNT; i++)
1099 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;1131 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
1100 if (cache_used > dcg->tcm_cache_high) {1132
1133 if (cache_used > dcg->tcm_cache_high)
1101 dcg->tcm_cache_high = cache_used;1134 dcg->tcm_cache_high = cache_used;
1102 }
11031135
1104 /* Check if the cache usage is over 95%: */1136 /* Check if the cache usage is over 95%: */
1105 if (self->t_quit || cache_used < dcg->tcm_high_level)1137 if (self->t_quit)
1138 break;
1139
1140 /* If threads are waiting then we are more aggressive about freeing
1141 * cache.
1142 */
1143 if (cache_used < (dcg->tcm_threads_waiting ? dcg->tcm_mid_level : dcg->tcm_high_level))
1106 break;1144 break;
11071145
1108 /* Reduce cache to the 75% level: */1146 /* Reduce cache to the 75% level: */
@@ -1137,7 +1175,23 @@
1137 */1175 */
1138 xt_db_approximate_time = time(NULL);1176 xt_db_approximate_time = time(NULL);
1139 dcg->tcm_freeer_busy = FALSE;1177 dcg->tcm_freeer_busy = FALSE;
1140 tabc_fr_wait_for_cache(self, 500);1178 /* No idea, why, but I am getting an uneccesarry pause here.
1179 * I run DBT2 with low record cache.
1180 *
1181 * Every now and then there is a pause where the freeer is here,
1182 * and all user threads are waiting for the freeer.
1183 *
1184 * So adding the tcm_threads_waiting condition.
1185 */
1186 if (dcg->tcm_threads_waiting) {
1187 cache_used = 0;
1188 for (i=0; i<XT_TC_SEGMENT_COUNT; i++)
1189 cache_used += dcg->tcm_segment[i].tcs_cache_in_use;
1190 if (cache_used < dcg->tcm_mid_level)
1191 tabc_fr_wait_for_cache(self, 500);
1192 }
1193 else
1194 tabc_fr_wait_for_cache(self, 500);
1141 //tabc_fr_wait_for_cache(self, 30*1000);1195 //tabc_fr_wait_for_cache(self, 30*1000);
1142 dcg->tcm_freeer_busy = TRUE;1196 dcg->tcm_freeer_busy = TRUE;
1143 xt_db_approximate_time = time(NULL);1197 xt_db_approximate_time = time(NULL);
@@ -1174,7 +1228,7 @@
1174 count = 2*60;1228 count = 2*60;
1175#endif1229#endif
1176 while (!self->t_quit && count > 0) {1230 while (!self->t_quit && count > 0) {
1177 xt_db_approximate_time = xt_trace_clock();1231 xt_db_approximate_time = time(NULL);
1178 sleep(1);1232 sleep(1);
1179 count--;1233 count--;
1180 }1234 }
11811235
=== modified file 'storage/pbxt/src/tabcache_xt.h'
--- storage/pbxt/src/tabcache_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/tabcache_xt.h 2010-05-07 08:52:27 +0000
@@ -29,6 +29,7 @@
29struct XTTable;29struct XTTable;
30struct XTOpenTable;30struct XTOpenTable;
31struct XTTabCache;31struct XTTabCache;
32struct XTDatabase;
3233
33#include "thread_xt.h"34#include "thread_xt.h"
34#include "filesys_xt.h"35#include "filesys_xt.h"
@@ -226,6 +227,7 @@
226 size_t tcm_cache_high; /* The high water level of cache allocation. */227 size_t tcm_cache_high; /* The high water level of cache allocation. */
227 size_t tcm_low_level; /* This is the level to which the freeer will free, once it starts working. */228 size_t tcm_low_level; /* This is the level to which the freeer will free, once it starts working. */
228 size_t tcm_high_level; /* This is the level at which the freeer will start to work (to avoid waiting)! */229 size_t tcm_high_level; /* This is the level at which the freeer will start to work (to avoid waiting)! */
230 size_t tcm_mid_level; /* At this level the freeer will not sleep if there are threads waiting. */
229231
230 /* The free'er thread: */232 /* The free'er thread: */
231 struct XTThread *tcm_freeer_thread; /* The freeer thread . */233 struct XTThread *tcm_freeer_thread; /* The freeer thread . */
@@ -283,6 +285,6 @@
283void xt_quit_freeer(XTThreadPtr self);285void xt_quit_freeer(XTThreadPtr self);
284void xt_stop_freeer(XTThreadPtr self);286void xt_stop_freeer(XTThreadPtr self);
285void xt_start_freeer(XTThreadPtr self);287void xt_start_freeer(XTThreadPtr self);
286void xt_wr_wake_freeer(XTThreadPtr self);288void xt_wr_wake_freeer(XTThreadPtr self, struct XTDatabase *db);
287289
288#endif290#endif
289291
=== modified file 'storage/pbxt/src/table_xt.cc'
--- storage/pbxt/src/table_xt.cc 2009-12-22 10:33:20 +0000
+++ storage/pbxt/src/table_xt.cc 2010-05-07 08:52:27 +0000
@@ -61,6 +61,11 @@
6161
62#define CHECK_TABLE_STATS62#define CHECK_TABLE_STATS
6363
64/* The problem is that this can take a long time
65 * if the table is very large!
66 */
67//#define CHECK_TABLE_READ_DATA_LOG
68
64#ifdef TRACE_TABLE_IDS69#ifdef TRACE_TABLE_IDS
65//#define PRINTF xt_ftracef70//#define PRINTF xt_ftracef
66#define PRINTF xt_trace71#define PRINTF xt_trace
@@ -217,6 +222,7 @@
217 xt_spinlock_free(self, &tab->tab_ainc_lock);222 xt_spinlock_free(self, &tab->tab_ainc_lock);
218 xt_free_mutex(&tab->tab_rec_flush_lock);223 xt_free_mutex(&tab->tab_rec_flush_lock);
219 xt_free_mutex(&tab->tab_ind_flush_lock);224 xt_free_mutex(&tab->tab_ind_flush_lock);
225 xt_free_mutex(&tab->tab_ind_stat_lock);
220 xt_free_mutex(&tab->tab_dic_field_lock);226 xt_free_mutex(&tab->tab_dic_field_lock);
221 xt_free_mutex(&tab->tab_row_lock);227 xt_free_mutex(&tab->tab_row_lock);
222 xt_free_mutex(&tab->tab_ind_lock);228 xt_free_mutex(&tab->tab_ind_lock);
@@ -487,6 +493,12 @@
487 }493 }
488 freer_(); // xt_describe_tables_exit(&desc)494 freer_(); // xt_describe_tables_exit(&desc)
489495
496 /*
497 * When we open all tables, we ignore problems with foreign keys.
498 * This must be done or we will not be able to load tables that
499 * were created with foreign key checks off.
500 */
501 self->st_ignore_fkeys = 1;
490 /* 502 /*
491 * The purpose of this code is to ensure that all tables are opened and cached,503 * The purpose of this code is to ensure that all tables are opened and cached,
492 * which is actually only required if tables have foreign key references.504 * which is actually only required if tables have foreign key references.
@@ -499,14 +511,30 @@
499 * 511 *
500 * Cannot open tables in the loop above because db->db_table_by_id which is built 512 * Cannot open tables in the loop above because db->db_table_by_id which is built
501 * above is used by xt_use_table_no_lock() 513 * above is used by xt_use_table_no_lock()
514 *
515 * {TABLE-STATS}
516 * NOTE: The code also lead to the statistics failing to work because
517 * the tables were already open when the handler was opened.
518 * Previously we only caclulated statistics when a handler was opened
519 * and the underlying table was also opened.
502 */520 */
503 xt_enum_tables_init(&edx);521 xt_enum_tables_init(&edx);
504 while ((te_ptr = xt_enum_tables_next(self, db, &edx))) {522 while ((te_ptr = xt_enum_tables_next(self, db, &edx))) {
505 xt_strcpy(PATH_MAX, pbuf, te_ptr->te_tab_path->tp_path);523 xt_strcpy(PATH_MAX, pbuf, te_ptr->te_tab_path->tp_path);
506 xt_add_dir_char(PATH_MAX, pbuf);524 xt_add_dir_char(PATH_MAX, pbuf);
507 xt_strcat(PATH_MAX, pbuf, te_ptr->te_tab_name);525 xt_strcat(PATH_MAX, pbuf, te_ptr->te_tab_name);
508 xt_heap_release(self, xt_use_table_no_lock(self, db, (XTPathStrPtr)pbuf, FALSE, FALSE, NULL, NULL));526 try_(a) {
527 xt_heap_release(self, xt_use_table_no_lock(self, db, (XTPathStrPtr) pbuf, FALSE, FALSE, NULL));
528 }
529 catch_(a) {
530 /* ignore errors, because we are just loading all
531 * the tables that we can...
532 */
533 xt_log_and_clear_warning(self);
534 }
535 cont_(a);
509 }536 }
537 self->st_ignore_fkeys = 0;
510538
511 popr_(); // Discard xt_tab_exit_db(db)539 popr_(); // Discard xt_tab_exit_db(db)
512 exit_();540 exit_();
@@ -651,7 +679,7 @@
651 xt_strcpy(PATH_MAX, path, te_ptr->te_tab_path->tp_path);679 xt_strcpy(PATH_MAX, path, te_ptr->te_tab_path->tp_path);
652 xt_add_dir_char(PATH_MAX, path);680 xt_add_dir_char(PATH_MAX, path);
653 xt_strcat(PATH_MAX, path, te_ptr->te_tab_name);681 xt_strcat(PATH_MAX, path, te_ptr->te_tab_name);
654 tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);682 tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE);
655 tab_check_table(self, tab);683 tab_check_table(self, tab);
656 xt_heap_release(self, tab);684 xt_heap_release(self, tab);
657 tab = NULL;685 tab = NULL;
@@ -1009,6 +1037,7 @@
1009/* a helper function to remove table from the open tables hash on exception1037/* a helper function to remove table from the open tables hash on exception
1010 * used in tab_new_handle() below1038 * used in tab_new_handle() below
1011 */1039 */
1040 #ifdef NO_LONGER_REQ
1012static void xt_del_from_db_tables_ht(XTThreadPtr self, XTTableHPtr tab)1041static void xt_del_from_db_tables_ht(XTThreadPtr self, XTTableHPtr tab)
1013{1042{
1014 XTTableEntryPtr te_ptr;1043 XTTableEntryPtr te_ptr;
@@ -1024,6 +1053,7 @@
1024 if ((te_ptr = (XTTableEntryPtr) xt_sl_find(self, db->db_table_by_id, &tab_id)))1053 if ((te_ptr = (XTTableEntryPtr) xt_sl_find(self, db->db_table_by_id, &tab_id)))
1025 te_ptr->te_table = NULL;1054 te_ptr->te_table = NULL;
1026}1055}
1056#endif
10271057
1028/*1058/*
1029 * Create a new table handle (i.e. open a table).1059 * Create a new table handle (i.e. open a table).
@@ -1067,6 +1097,7 @@
1067 xt_spinlock_init_with_autoname(self, &tab->tab_ainc_lock);1097 xt_spinlock_init_with_autoname(self, &tab->tab_ainc_lock);
1068 xt_init_mutex_with_autoname(self, &tab->tab_rec_flush_lock);1098 xt_init_mutex_with_autoname(self, &tab->tab_rec_flush_lock);
1069 xt_init_mutex_with_autoname(self, &tab->tab_ind_flush_lock);1099 xt_init_mutex_with_autoname(self, &tab->tab_ind_flush_lock);
1100 xt_init_mutex_with_autoname(self, &tab->tab_ind_stat_lock);
1070 xt_init_mutex_with_autoname(self, &tab->tab_dic_field_lock);1101 xt_init_mutex_with_autoname(self, &tab->tab_dic_field_lock);
1071 xt_init_mutex_with_autoname(self, &tab->tab_row_lock);1102 xt_init_mutex_with_autoname(self, &tab->tab_row_lock);
1072 xt_init_mutex_with_autoname(self, &tab->tab_ind_lock);1103 xt_init_mutex_with_autoname(self, &tab->tab_ind_lock);
@@ -1148,9 +1179,16 @@
1148 * will work if we have cyclic foreign key references.1179 * will work if we have cyclic foreign key references.
1149 */ 1180 */
1150 if (tab->tab_dic.dic_table) {1181 if (tab->tab_dic.dic_table) {
1151 pushr_(xt_del_from_db_tables_ht, tab);1182 try_(a) {
1152 tab->tab_dic.dic_table->attachReferences(self, db);1183 tab->tab_dic.dic_table->attachReferences(self, db);
1153 popr_();1184 }
1185 catch_(a) {
1186 /* Errors are thrown when: set foreign_key_checks = 1 */
1187 /* Undo everything done above: */
1188 xt_ht_del(self, db->db_tables, tab->tab_name);
1189 xt_throw(self);
1190 }
1191 cont_(a);
1154 }1192 }
11551193
1156 *r_tab = tab;1194 *r_tab = tab;
@@ -1162,7 +1200,7 @@
1162 * Get a reference to a table in the current database. The table reference is valid,1200 * Get a reference to a table in the current database. The table reference is valid,
1163 * as long as the thread is using the database!!!1201 * as long as the thread is using the database!!!
1164 */1202 */
1165xtPublic XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, XTDatabaseHPtr db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic, xtBool *opened)1203xtPublic XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, XTDatabaseHPtr db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic)
1166{1204{
1167 XTTableHPtr tab;1205 XTTableHPtr tab;
11681206
@@ -1181,9 +1219,6 @@
11811219
1182 if (tab_new_handle(self, &tab, db, tab_id, name, FALSE, dic) == XT_TAB_NO_DICTIONARY)1220 if (tab_new_handle(self, &tab, db, tab_id, name, FALSE, dic) == XT_TAB_NO_DICTIONARY)
1183 xt_throw_taberr(XT_CONTEXT, XT_ERR_NO_DICTIONARY, name);1221 xt_throw_taberr(XT_CONTEXT, XT_ERR_NO_DICTIONARY, name);
1184
1185 if (opened)
1186 *opened = TRUE;
1187 }1222 }
1188 1223
1189 if (tab)1224 if (tab)
@@ -1297,7 +1332,7 @@
1297 XTSortedListInfoRec li_undo;1332 XTSortedListInfoRec li_undo;
12981333
1299#ifdef TRACE_CREATE_TABLES1334#ifdef TRACE_CREATE_TABLES
1300 fprintf(stderr, "CREATE %s\n", name->ps_path);1335 printf("CREATE %s\n", name->ps_path);
1301#endif1336#endif
1302 enter_();1337 enter_();
1303 if (strlen(xt_last_name_of_path(name->ps_path)) > XT_TABLE_NAME_SIZE-1)1338 if (strlen(xt_last_name_of_path(name->ps_path)) > XT_TABLE_NAME_SIZE-1)
@@ -1528,7 +1563,7 @@
1528 * as well.1563 * as well.
1529 */1564 */
1530 if (!old_tab_id) {1565 if (!old_tab_id) {
1531 tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL, NULL);1566 tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL);
1532 xt_heap_release(self, tab);1567 xt_heap_release(self, tab);
1533 }1568 }
1534 }1569 }
@@ -1556,7 +1591,7 @@
1556 /* Same purpose as above {LOAD-FOR-FKS} (although this should work, 1591 /* Same purpose as above {LOAD-FOR-FKS} (although this should work,
1557 * beacuse this is a TRUNCATE TABLE.1592 * beacuse this is a TRUNCATE TABLE.
1558 */1593 */
1559 tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL, NULL);1594 tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL);
1560 xt_heap_release(self, tab);1595 xt_heap_release(self, tab);
1561 }1596 }
1562 catch_(b) {1597 catch_(b) {
@@ -1599,7 +1634,7 @@
1599 /* this code is not needed anymore as we open tables referred by FKs as necessary during checks1634 /* this code is not needed anymore as we open tables referred by FKs as necessary during checks
1600 xt_ht_lock(self, db->db_tables);1635 xt_ht_lock(self, db->db_tables);
1601 pushr_(xt_ht_unlock, db->db_tables);1636 pushr_(xt_ht_unlock, db->db_tables);
1602 tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL, NULL);1637 tab = xt_use_table_no_lock(self, db, name, FALSE, FALSE, NULL);
1603 freer_(); // xt_ht_unlock(db->db_tables)1638 freer_(); // xt_ht_unlock(db->db_tables)
1604 xt_heap_release(self, tab);1639 xt_heap_release(self, tab);
1605 * CHANGED see {LOAD-FOR-FKS} above.1640 * CHANGED see {LOAD-FOR-FKS} above.
@@ -1619,7 +1654,7 @@
1619 enter_();1654 enter_();
16201655
1621#ifdef TRACE_CREATE_TABLES1656#ifdef TRACE_CREATE_TABLES
1622 fprintf(stderr, "DROP %s\n", tab_name->ps_path);1657 printf("DROP %s\n", tab_name->ps_path);
1623#endif1658#endif
16241659
1625 table_pool = tab_lock_table(self, tab_name, FALSE, TRUE, TRUE, &tab);1660 table_pool = tab_lock_table(self, tab_name, FALSE, TRUE, TRUE, &tab);
@@ -1775,9 +1810,10 @@
1775 size_t rec_size;1810 size_t rec_size;
1776 size_t row_size;1811 size_t row_size;
1777 u_llong ext_data_len = 0;1812 u_llong ext_data_len = 0;
1813 u_llong ext_rec_count = 0;
17781814
1779#if defined(DUMP_CHECK_TABLE) || defined(CHECK_TABLE_STATS)1815#if defined(DUMP_CHECK_TABLE) || defined(CHECK_TABLE_STATS)
1780 fprintf(stderr, "\nCHECK TABLE: %s\n", tab->tab_name->ps_path);1816 printf("\nCHECK TABLE: %s\n", tab->tab_name->ps_path);
1781#endif1817#endif
17821818
1783 xt_lock_mutex(self, &tab->tab_db->db_co_ext_lock);1819 xt_lock_mutex(self, &tab->tab_db->db_co_ext_lock);
@@ -1787,38 +1823,38 @@
1787 pushr_(xt_unlock_mutex, &tab->tab_rec_lock);1823 pushr_(xt_unlock_mutex, &tab->tab_rec_lock);
17881824
1789#ifdef CHECK_TABLE_STATS1825#ifdef CHECK_TABLE_STATS
1790 fprintf(stderr, "Record buffer size = %lu\n", (u_long) tab->tab_dic.dic_mysql_buf_size);1826 printf("Record buffer size = %lu\n", (u_long) tab->tab_dic.dic_mysql_buf_size);
1791 fprintf(stderr, "Fixed length rec. len. = %lu\n", (u_long) tab->tab_dic.dic_mysql_rec_size);1827 printf("Fixed length rec. len. = %lu\n", (u_long) tab->tab_dic.dic_mysql_rec_size);
1792 fprintf(stderr, "Handle data record size = %lu\n", (u_long) tab->tab_dic.dic_rec_size);1828 printf("Handle data record size = %lu\n", (u_long) tab->tab_dic.dic_rec_size);
1793 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));1829 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));
1794 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);1830 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);
1795 if (tab->tab_dic.dic_def_ave_row_size)1831 if (tab->tab_dic.dic_def_ave_row_size)
1796 fprintf(stderr, "Avg row len set for tab = %lu\n", (u_long) tab->tab_dic.dic_def_ave_row_size);1832 printf("Avg row len set for tab = %lu\n", (u_long) tab->tab_dic.dic_def_ave_row_size);
1797 else1833 else
1798 fprintf(stderr, "Avg row len set for tab = not specified\n");1834 printf("Avg row len set for tab = not specified\n");
1799 fprintf(stderr, "Rows fixed length = %s\n", tab->tab_dic.dic_rec_fixed ? "YES" : "NO");1835 printf("Rows fixed length = %s\n", tab->tab_dic.dic_rec_fixed ? "YES" : "NO");
1800 if (tab->tab_dic.dic_tab_flags & XT_TAB_FLAGS_TEMP_TAB)1836 if (tab->tab_dic.dic_tab_flags & XT_TAB_FLAGS_TEMP_TAB)
1801 fprintf(stderr, "Table type = TEMP\n");1837 printf("Table type = TEMP\n");
1802 if (tab->tab_dic.dic_def_ave_row_size)1838 if (tab->tab_dic.dic_def_ave_row_size)
1803 fprintf(stderr, "Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH_SPEC);1839 printf("Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH_SPEC);
1804 else1840 else
1805 fprintf(stderr, "Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH);1841 printf("Maximum fixed size = %lu\n", (u_long) XT_TAB_MAX_FIX_REC_LENGTH);
1806 fprintf(stderr, "Minimum variable size = %lu\n", (u_long) XT_TAB_MIN_VAR_REC_LENGTH);1842 printf("Minimum variable size = %lu\n", (u_long) XT_TAB_MIN_VAR_REC_LENGTH);
1807 fprintf(stderr, "Minimum auto-increment = %llu\n", (u_llong) tab->tab_dic.dic_min_auto_inc);1843 printf("Minimum auto-increment = %llu\n", (u_llong) tab->tab_dic.dic_min_auto_inc);
1808 fprintf(stderr, "Number of columns = %lu\n", (u_long) tab->tab_dic.dic_no_of_cols);1844 printf("Number of columns = %lu\n", (u_long) tab->tab_dic.dic_no_of_cols);
1809 fprintf(stderr, "Number of fixed columns = %lu\n", (u_long) tab->tab_dic.dic_fix_col_count);1845 printf("Number of fixed columns = %lu\n", (u_long) tab->tab_dic.dic_fix_col_count);
1810 fprintf(stderr, "Columns req. for index = %lu\n", (u_long) tab->tab_dic.dic_ind_cols_req);1846 printf("Columns req. for index = %lu\n", (u_long) tab->tab_dic.dic_ind_cols_req);
1811 if (tab->tab_dic.dic_ind_rec_len)1847 if (tab->tab_dic.dic_ind_rec_len)
1812 fprintf(stderr, "Rec len req. for index = %llu\n", (u_llong) tab->tab_dic.dic_ind_rec_len);1848 printf("Rec len req. for index = %llu\n", (u_llong) tab->tab_dic.dic_ind_rec_len);
1813 fprintf(stderr, "Columns req. for blobs = %lu\n", (u_long) tab->tab_dic.dic_blob_cols_req);1849 printf("Columns req. for blobs = %lu\n", (u_long) tab->tab_dic.dic_blob_cols_req);
1814 fprintf(stderr, "Number of blob columns = %lu\n", (u_long) tab->tab_dic.dic_blob_count);1850 printf("Number of blob columns = %lu\n", (u_long) tab->tab_dic.dic_blob_count);
1815 fprintf(stderr, "Number of indices = %lu\n", (u_long) tab->tab_dic.dic_key_count);1851 printf("Number of indices = %lu\n", (u_long) tab->tab_dic.dic_key_count);
1816#endif1852#endif
18171853
1818#ifdef DUMP_CHECK_TABLE1854#ifdef DUMP_CHECK_TABLE
1819 fprintf(stderr, "Records:-\n");1855 printf("Records:-\n");
1820 fprintf(stderr, "Free list: %llu (%llu)\n", (u_llong) tab->tab_rec_free_id, (u_llong) tab->tab_rec_fnum);1856 printf("Free list: %llu (%llu)\n", (u_llong) tab->tab_rec_free_id, (u_llong) tab->tab_rec_fnum);
1821 fprintf(stderr, "EOF: %llu\n", (u_llong) tab->tab_rec_eof_id);1857 printf("EOF: %llu\n", (u_llong) tab->tab_rec_eof_id);
1822#endif1858#endif
18231859
1824 rec_size = XT_REC_EXT_HEADER_SIZE;1860 rec_size = XT_REC_EXT_HEADER_SIZE;
@@ -1830,24 +1866,24 @@
1830 xt_throw(self);1866 xt_throw(self);
18311867
1832#ifdef DUMP_CHECK_TABLE1868#ifdef DUMP_CHECK_TABLE
1833 fprintf(stderr, "%-4llu ", (u_llong) rec_id);1869 printf("%-4llu ", (u_llong) rec_id);
1834#endif1870#endif
1835 switch (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_MASK) {1871 switch (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_MASK) {
1836 case XT_TAB_STATUS_FREED:1872 case XT_TAB_STATUS_FREED:
1837#ifdef DUMP_CHECK_TABLE1873#ifdef DUMP_CHECK_TABLE
1838 fprintf(stderr, "======== ");1874 printf("======== ");
1839#endif1875#endif
1840 free_rec_count++;1876 free_rec_count++;
1841 break;1877 break;
1842 case XT_TAB_STATUS_DELETE:1878 case XT_TAB_STATUS_DELETE:
1843#ifdef DUMP_CHECK_TABLE1879#ifdef DUMP_CHECK_TABLE
1844 fprintf(stderr, "delete ");1880 printf("delete ");
1845#endif1881#endif
1846 delete_rec_count++;1882 delete_rec_count++;
1847 break;1883 break;
1848 case XT_TAB_STATUS_FIXED:1884 case XT_TAB_STATUS_FIXED:
1849#ifdef DUMP_CHECK_TABLE1885#ifdef DUMP_CHECK_TABLE
1850 fprintf(stderr, "record-F ");1886 printf("record-F ");
1851#endif1887#endif
1852 alloc_rec_count++;1888 alloc_rec_count++;
1853 row_size = myxt_store_row_length(ot, (char *) ot->ot_row_rbuffer + XT_REC_FIX_HEADER_SIZE);1889 row_size = myxt_store_row_length(ot, (char *) ot->ot_row_rbuffer + XT_REC_FIX_HEADER_SIZE);
@@ -1859,7 +1895,7 @@
1859 break;1895 break;
1860 case XT_TAB_STATUS_VARIABLE:1896 case XT_TAB_STATUS_VARIABLE:
1861#ifdef DUMP_CHECK_TABLE1897#ifdef DUMP_CHECK_TABLE
1862 fprintf(stderr, "record-V ");1898 printf("record-V ");
1863#endif1899#endif
1864 alloc_rec_count++;1900 alloc_rec_count++;
1865 row_size = myxt_load_row_length(ot, tab->tab_dic.dic_rec_size, ot->ot_row_rbuffer + XT_REC_FIX_HEADER_SIZE, NULL);1901 row_size = myxt_load_row_length(ot, tab->tab_dic.dic_rec_size, ot->ot_row_rbuffer + XT_REC_FIX_HEADER_SIZE, NULL);
@@ -1871,9 +1907,10 @@
1871 break;1907 break;
1872 case XT_TAB_STATUS_EXT_DLOG:1908 case XT_TAB_STATUS_EXT_DLOG:
1873#ifdef DUMP_CHECK_TABLE1909#ifdef DUMP_CHECK_TABLE
1874 fprintf(stderr, "record-X ");1910 printf("record-X ");
1875#endif1911#endif
1876 alloc_rec_count++;1912 alloc_rec_count++;
1913 ext_rec_count++;
1877 ext_data_len += XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);1914 ext_data_len += XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
1878 row_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4) + ot->ot_rec_size - XT_REC_EXT_HEADER_SIZE;1915 row_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4) + ot->ot_rec_size - XT_REC_EXT_HEADER_SIZE;
1879 alloc_rec_bytes += row_size;1916 alloc_rec_bytes += row_size;
@@ -1885,9 +1922,9 @@
1885 }1922 }
1886#ifdef DUMP_CHECK_TABLE1923#ifdef DUMP_CHECK_TABLE
1887 if (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_CLEANED_BIT)1924 if (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_CLEANED_BIT)
1888 fprintf(stderr, "C");1925 printf("C");
1889 else1926 else
1890 fprintf(stderr, " ");1927 printf(" ");
1891#endif1928#endif
1892 prev_rec_id = XT_GET_DISK_4(rec_buf->tr_prev_rec_id_4);1929 prev_rec_id = XT_GET_DISK_4(rec_buf->tr_prev_rec_id_4);
1893 xn_id = XT_GET_DISK_4(rec_buf->tr_xact_id_4);1930 xn_id = XT_GET_DISK_4(rec_buf->tr_xact_id_4);
@@ -1895,14 +1932,15 @@
1895 switch (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_MASK) {1932 switch (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_MASK) {
1896 case XT_TAB_STATUS_FREED:1933 case XT_TAB_STATUS_FREED:
1897#ifdef DUMP_CHECK_TABLE1934#ifdef DUMP_CHECK_TABLE
1898 fprintf(stderr, " prev=%-3llu (xact=%-3llu row=%lu)\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);1935 printf(" prev=%-3llu (xact=%-3llu row=%lu)\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);
1899#endif1936#endif
1900 break;1937 break;
1901 case XT_TAB_STATUS_EXT_DLOG:1938 case XT_TAB_STATUS_EXT_DLOG:
1902#ifdef DUMP_CHECK_TABLE1939#ifdef DUMP_CHECK_TABLE
1903 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));1940 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));
1904#endif1941#endif
19051942
1943#ifdef CHECK_TABLE_READ_DATA_LOG
1906 log_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);1944 log_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
1907 XT_GET_LOG_REF(log_id, log_offset, rec_buf);1945 XT_GET_LOG_REF(log_id, log_offset, rec_buf);
1908 if (!self->st_dlog_buf.dlb_read_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data), (xtWord1 *) &ext_rec, self))1946 if (!self->st_dlog_buf.dlb_read_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data), (xtWord1 *) &ext_rec, self))
@@ -1919,10 +1957,11 @@
1919 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);1957 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);
1920 }1958 }
1921 }1959 }
1960#endif
1922 break;1961 break;
1923 default:1962 default:
1924#ifdef DUMP_CHECK_TABLE1963#ifdef DUMP_CHECK_TABLE
1925 fprintf(stderr, " prev=%-3llu xact=%-3llu row=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);1964 printf(" prev=%-3llu xact=%-3llu row=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id);
1926#endif1965#endif
1927 break;1966 break;
1928 }1967 }
@@ -1930,17 +1969,19 @@
1930 }1969 }
1931 1970
1932#ifdef CHECK_TABLE_STATS1971#ifdef CHECK_TABLE_STATS
1933 if (!tab->tab_dic.dic_rec_fixed)1972 if (!tab->tab_dic.dic_rec_fixed) {
1934 fprintf(stderr, "Extendend data length = %llu\n", ext_data_len);1973 printf("Extended data length = %llu\n", ext_data_len);
1974 printf("Extended record count = %llu\n", ext_rec_count);
1975 }
1935 1976
1936 if (alloc_rec_count) {1977 if (alloc_rec_count) {
1937 fprintf(stderr, "Minumum comp. rec. len. = %llu\n", (u_llong) min_comp_rec_len);1978 printf("Minumum comp. rec. len. = %llu\n", (u_llong) min_comp_rec_len);
1938 fprintf(stderr, "Average comp. rec. len. = %llu\n", (u_llong) ((double) alloc_rec_bytes / (double) alloc_rec_count + (double) 0.5));1979 printf("Average comp. rec. len. = %llu\n", (u_llong) ((double) alloc_rec_bytes / (double) alloc_rec_count + (double) 0.5));
1939 fprintf(stderr, "Maximum comp. rec. len. = %llu\n", (u_llong) max_comp_rec_len);1980 printf("Maximum comp. rec. len. = %llu\n", (u_llong) max_comp_rec_len);
1940 }1981 }
1941 fprintf(stderr, "Free record count = %llu\n", (u_llong) free_rec_count);1982 printf("Free record count = %llu\n", (u_llong) free_rec_count);
1942 fprintf(stderr, "Deleted record count = %llu\n", (u_llong) delete_rec_count);1983 printf("Deleted record count = %llu\n", (u_llong) delete_rec_count);
1943 fprintf(stderr, "Allocated record count = %llu\n", (u_llong) alloc_rec_count);1984 printf("Allocated record count = %llu\n", (u_llong) alloc_rec_count);
1944#endif1985#endif
1945 if (tab->tab_rec_fnum != free_rec_count)1986 if (tab->tab_rec_fnum != free_rec_count)
1946 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);1987 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);
@@ -1978,9 +2019,9 @@
1978 pushr_(xt_unlock_mutex, &tab->tab_row_lock);2019 pushr_(xt_unlock_mutex, &tab->tab_row_lock);
19792020
1980#ifdef DUMP_CHECK_TABLE2021#ifdef DUMP_CHECK_TABLE
1981 fprintf(stderr, "Rows:-\n");2022 printf("Rows:-\n");
1982 fprintf(stderr, "Free list: %llu (%llu)\n", (u_llong) tab->tab_row_free_id, (u_llong) tab->tab_row_fnum);2023 printf("Free list: %llu (%llu)\n", (u_llong) tab->tab_row_free_id, (u_llong) tab->tab_row_fnum);
1983 fprintf(stderr, "EOF: %llu\n", (u_llong) tab->tab_row_eof_id);2024 printf("EOF: %llu\n", (u_llong) tab->tab_row_eof_id);
1984#endif2025#endif
19852026
1986 rec_id = 1;2027 rec_id = 1;
@@ -1988,13 +2029,13 @@
1988 if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, rec_id, &ref_id, self))2029 if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, rec_id, &ref_id, self))
1989 xt_throw(self);2030 xt_throw(self);
1990#ifdef DUMP_CHECK_TABLE2031#ifdef DUMP_CHECK_TABLE
1991 fprintf(stderr, "%-3llu ", (u_llong) rec_id);2032 printf("%-3llu ", (u_llong) rec_id);
1992#endif2033#endif
1993#ifdef DUMP_CHECK_TABLE2034#ifdef DUMP_CHECK_TABLE
1994 if (ref_id == 0)2035 if (ref_id == 0)
1995 fprintf(stderr, "====== 0\n");2036 printf("====== 0\n");
1996 else2037 else
1997 fprintf(stderr, "in use %llu\n", (u_llong) ref_id);2038 printf("in use %llu\n", (u_llong) ref_id);
1998#endif2039#endif
1999 rec_id++;2040 rec_id++;
2000 }2041 }
@@ -2026,7 +2067,7 @@
2026 memset(&dic, 0, sizeof(dic));2067 memset(&dic, 0, sizeof(dic));
20272068
2028#ifdef TRACE_CREATE_TABLES2069#ifdef TRACE_CREATE_TABLES
2029 fprintf(stderr, "RENAME %s --> %s\n", old_name->ps_path, new_name->ps_path);2070 printf("RENAME %s --> %s\n", old_name->ps_path, new_name->ps_path);
2030#endif2071#endif
2031 if (strlen(xt_last_name_of_path(new_name->ps_path)) > XT_TABLE_NAME_SIZE-1)2072 if (strlen(xt_last_name_of_path(new_name->ps_path)) > XT_TABLE_NAME_SIZE-1)
2032 xt_throw_taberr(XT_CONTEXT, XT_ERR_NAME_TOO_LONG, new_name);2073 xt_throw_taberr(XT_CONTEXT, XT_ERR_NAME_TOO_LONG, new_name);
@@ -2100,7 +2141,7 @@
2100 popr_(); // Discard tab_free_table_path(te_new_path);2141 popr_(); // Discard tab_free_table_path(te_new_path);
2101 popr_(); // Discard xt_free(te_new_name);2142 popr_(); // Discard xt_free(te_new_name);
21022143
2103 tab = xt_use_table_no_lock(self, db, new_name, FALSE, FALSE, &dic, NULL);2144 tab = xt_use_table_no_lock(self, db, new_name, FALSE, FALSE, &dic);
2104 /* All renamed tables are considered repaired! */2145 /* All renamed tables are considered repaired! */
2105 xt_tab_table_repaired(tab);2146 xt_tab_table_repaired(tab);
2106 xt_heap_release(self, tab);2147 xt_heap_release(self, tab);
@@ -2110,14 +2151,14 @@
2110 freer_(); // xt_db_unlock_table_pool(table_pool)2151 freer_(); // xt_db_unlock_table_pool(table_pool)
2111}2152}
21122153
2113xtPublic XTTableHPtr xt_use_table(XTThreadPtr self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, xtBool *opened)2154xtPublic XTTableHPtr xt_use_table(XTThreadPtr self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok)
2114{2155{
2115 XTTableHPtr tab;2156 XTTableHPtr tab;
2116 XTDatabaseHPtr db = self->st_database;2157 XTDatabaseHPtr db = self->st_database;
21172158
2118 xt_ht_lock(self, db->db_tables);2159 xt_ht_lock(self, db->db_tables);
2119 pushr_(xt_ht_unlock, db->db_tables);2160 pushr_(xt_ht_unlock, db->db_tables);
2120 tab = xt_use_table_no_lock(self, db, name, no_load, missing_ok, NULL, opened);2161 tab = xt_use_table_no_lock(self, db, name, no_load, missing_ok, NULL);
2121 freer_();2162 freer_();
2122 return tab;2163 return tab;
2123}2164}
@@ -2221,7 +2262,7 @@
2221 xt_tab_store_header(ot, &rec_head);2262 xt_tab_store_header(ot, &rec_head);
22222263
2223#ifdef TRACE_FLUSH2264#ifdef TRACE_FLUSH
2224 fprintf(stderr, "FLUSH rec/row %d %s\n", (int) tab->tab_bytes_to_flush, tab->tab_name->ps_path);2265 printf("FLUSH rec/row %d %s\n", (int) tab->tab_bytes_to_flush, tab->tab_name->ps_path);
2225 fflush(stdout);2266 fflush(stdout);
2226#endif2267#endif
2227 /* Write the table header: */2268 /* Write the table header: */
@@ -2276,7 +2317,7 @@
2276 xt_unlock_mutex_ns(&cp->cp_state_lock);2317 xt_unlock_mutex_ns(&cp->cp_state_lock);
22772318
2278#ifdef TRACE_FLUSH2319#ifdef TRACE_FLUSH
2279 fprintf(stderr, "FLUSH --end-- %s\n", tab->tab_name->ps_path);2320 printf("FLUSH --end-- %s\n", tab->tab_name->ps_path);
2280 fflush(stdout);2321 fflush(stdout);
2281#endif2322#endif
2282 xt_unlock_mutex_ns(&tab->tab_rec_flush_lock);2323 xt_unlock_mutex_ns(&tab->tab_rec_flush_lock);
@@ -2858,7 +2899,7 @@
2858 /* This is a record written by this transaction. */2899 /* This is a record written by this transaction. */
2859 if (thread->st_is_update) {2900 if (thread->st_is_update) {
2860 /* Check that it was not written by the current update statement: */2901 /* Check that it was not written by the current update statement: */
2861 if (XT_STAT_ID_MASK(thread->st_update_id) == rec_head->tr_stat_id_1) {2902 if (XT_STAT_ID_MASK(ot->ot_update_id) == rec_head->tr_stat_id_1) {
2862#ifdef TRACE_VARIATIONS2903#ifdef TRACE_VARIATIONS
2863 if (len <= 450)2904 if (len <= 450)
2864 len += sprintf(t_buf+len, "MY UPDATE IN THIS STATEMENT T%d\n", (int) xn_id);2905 len += sprintf(t_buf+len, "MY UPDATE IN THIS STATEMENT T%d\n", (int) xn_id);
@@ -3139,7 +3180,7 @@
3139 }3180 }
3140 if (lw.lw_curr_lock != XT_NO_LOCK) {3181 if (lw.lw_curr_lock != XT_NO_LOCK) {
3141#ifdef TRACE_VARIATIONS3182#ifdef TRACE_VARIATIONS
3142 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);3183 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);
3143#endif3184#endif
3144 if (!xt_xn_wait_for_xact(thread, NULL, &lw)) {3185 if (!xt_xn_wait_for_xact(thread, NULL, &lw)) {
3145#ifdef DEBUG_LOCK_QUEUE3186#ifdef DEBUG_LOCK_QUEUE
@@ -3950,6 +3991,21 @@
3950 tab_restore_exception(&e);3991 tab_restore_exception(&e);
3951}3992}
39523993
3994static xtBool tab_write_ext_record(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, xtTableID tab_id, xtRecordID rec_id, xtLogID log_id, xtLogOffset log_offset, XTThreadPtr thread)
3995{
3996 xtWord1 tmp_buffer[offsetof(XTactExtRecEntryDRec, er_data)];
3997 xtBool ok;
3998
3999 memcpy(tmp_buffer, rec_info->ri_log_buf, sizeof(tmp_buffer));
4000 rec_info->ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;
4001 XT_SET_DISK_4(rec_info->ri_log_buf->er_data_size_4, rec_info->ri_log_data_size);
4002 XT_SET_DISK_4(rec_info->ri_log_buf->er_tab_id_4, tab_id);
4003 XT_SET_DISK_4(rec_info->ri_log_buf->er_rec_id_4, rec_id);
4004 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);
4005 memcpy(rec_info->ri_log_buf, tmp_buffer, sizeof(tmp_buffer));
4006 return ok;
4007}
4008
3953static xtBool tab_add_record(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, u_int status)4009static xtBool tab_add_record(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, u_int status)
3954{4010{
3955 register XTTableHPtr tab = ot->ot_table;4011 register XTTableHPtr tab = ot->ot_table;
@@ -4007,26 +4063,19 @@
4007 */4063 */
4008 read = ((rec_id - 1) % tab->tab_recs.tci_rows_per_page) != 0;4064 read = ((rec_id - 1) % tab->tab_recs.tci_rows_per_page) != 0;
40094065
4010 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)) {4066 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)) {
4011 xt_unlock_mutex_ns(&tab->tab_rec_lock);4067 xt_unlock_mutex_ns(&tab->tab_rec_lock);
4012 return FAILED;4068 return FAILED;
4013 }4069 }
4014 }4070 }
4015 xt_unlock_mutex_ns(&tab->tab_rec_lock);4071 xt_unlock_mutex_ns(&tab->tab_rec_lock);
40164072
4017 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))4073 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))
4018 return FAILED;4074 return FAILED;
40194075
4020 if (rec_info->ri_ext_rec) {4076 if (rec_info->ri_ext_rec) {
4021 /* Write the log buffer overflow: */ 4077 if (!tab_write_ext_record(ot, rec_info, tab->tab_id, rec_id, log_id, log_offset, thread))
4022 rec_info->ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;
4023 XT_SET_DISK_4(rec_info->ri_log_buf->er_data_size_4, rec_info->ri_log_data_size);
4024 XT_SET_DISK_4(rec_info->ri_log_buf->er_tab_id_4, tab->tab_id);
4025 XT_SET_DISK_4(rec_info->ri_log_buf->er_rec_id_4, rec_id);
4026 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)) {
4027 /* Failed to write the overflow, free the record allocated above: */
4028 return FAILED;4078 return FAILED;
4029 }
4030 }4079 }
40314080
4032 XT_DISABLED_TRACE(("new rec tx=%d val=%d\n", (int) thread->st_xact_data->xd_start_xn_id, (int) rec_id));4081 XT_DISABLED_TRACE(("new rec tx=%d val=%d\n", (int) thread->st_xact_data->xd_start_xn_id, (int) rec_id));
@@ -4062,8 +4111,11 @@
4062 }4111 }
4063 }4112 }
40644113
4114 /* This is not required because the extended record will be free
4115 * later when the record is freed!
4065 if (row_ptr->tr_rec_type_1 == XT_TAB_STATUS_EXT_DLOG || row_ptr->tr_rec_type_1 == XT_TAB_STATUS_EXT_CLEAN)4116 if (row_ptr->tr_rec_type_1 == XT_TAB_STATUS_EXT_DLOG || row_ptr->tr_rec_type_1 == XT_TAB_STATUS_EXT_CLEAN)
4066 tab_free_ext_record_on_fail(ot, rec_id, (XTTabRecExtDPtr) row_ptr, log_err);4117 tab_free_ext_record_on_fail(ot, rec_id, (XTTabRecExtDPtr) row_ptr, log_err);
4118 */
40674119
4068 rec_info.ri_fix_rec_buf = (XTTabRecFixDPtr) ot->ot_row_wbuffer;4120 rec_info.ri_fix_rec_buf = (XTTabRecFixDPtr) ot->ot_row_wbuffer;
4069 rec_info.ri_rec_buf_size = offsetof(XTTabRecFixDRec, rf_data);4121 rec_info.ri_rec_buf_size = offsetof(XTTabRecFixDRec, rf_data);
@@ -4369,7 +4421,7 @@
4369 if (!(row_id = tab_new_row(ot, tab)))4421 if (!(row_id = tab_new_row(ot, tab)))
4370 goto failed_0;4422 goto failed_0;
43714423
4372 rec_info.ri_fix_rec_buf->tr_stat_id_1 = self->st_update_id;4424 rec_info.ri_fix_rec_buf->tr_stat_id_1 = ot->ot_update_id;
4373 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);4425 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);
4374 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, 0);4426 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, 0);
4375 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);4427 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);
@@ -4458,7 +4510,7 @@
4458 * order to do this we'd need to read the before-image of the 4510 * order to do this we'd need to read the before-image of the
4459 * record before modifying it.4511 * record before modifying it.
4460 */4512 */
4461 if (!ot->ot_thread->t_exception.e_xt_err)4513 if (!thread->t_exception.e_xt_err)
4462 xt_register_xterr(XT_REG_CONTEXT, XT_ERR_NO_BEFORE_IMAGE);4514 xt_register_xterr(XT_REG_CONTEXT, XT_ERR_NO_BEFORE_IMAGE);
4463 return FAILED;4515 return FAILED;
4464 }4516 }
@@ -4471,7 +4523,7 @@
44714523
4472 if (rec_info->ri_ext_rec) {4524 if (rec_info->ri_ext_rec) {
4473 /* Determine where the overflow will go... */4525 /* Determine where the overflow will go... */
4474 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))4526 if (!thread->st_dlog_buf.dlb_get_log_offset(&log_id, &log_offset, rec_info->ri_log_data_size + offsetof(XTactExtRecEntryDRec, er_data), thread))
4475 return FAILED;4527 return FAILED;
4476 XT_SET_LOG_REF(rec_info->ri_ext_rec, log_id, log_offset);4528 XT_SET_LOG_REF(rec_info->ri_ext_rec, log_id, log_offset);
4477 }4529 }
@@ -4481,11 +4533,7 @@
44814533
4482 if (rec_info->ri_ext_rec) {4534 if (rec_info->ri_ext_rec) {
4483 /* Write the log buffer overflow: */ 4535 /* Write the log buffer overflow: */
4484 rec_info->ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;4536 if (!tab_write_ext_record(ot, rec_info, tab->tab_id, rec_id, log_id, log_offset, thread))
4485 XT_SET_DISK_4(rec_info->ri_log_buf->er_data_size_4, rec_info->ri_log_data_size);
4486 XT_SET_DISK_4(rec_info->ri_log_buf->er_tab_id_4, tab->tab_id);
4487 XT_SET_DISK_4(rec_info->ri_log_buf->er_rec_id_4, rec_id);
4488 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))
4489 return FAILED;4537 return FAILED;
4490 }4538 }
44914539
@@ -4529,12 +4577,12 @@
45294577
4530 if (rec_info.ri_ext_rec) {4578 if (rec_info.ri_ext_rec) {
4531 /* Determine where the overflow will go... */4579 /* Determine where the overflow will go... */
4532 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))4580 if (!self->st_dlog_buf.dlb_get_log_offset(&log_id, &log_offset, offsetof(XTactExtRecEntryDRec, er_data) + rec_info.ri_log_data_size, self))
4533 goto failed_0;4581 goto failed_0;
4534 XT_SET_LOG_REF(rec_info.ri_ext_rec, log_id, log_offset);4582 XT_SET_LOG_REF(rec_info.ri_ext_rec, log_id, log_offset);
4535 }4583 }
45364584
4537 rec_info.ri_fix_rec_buf->tr_stat_id_1 = self->st_update_id;4585 rec_info.ri_fix_rec_buf->tr_stat_id_1 = ot->ot_update_id;
4538 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);4586 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);
4539 XT_COPY_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, prev_rec_head.tr_prev_rec_id_4);4587 XT_COPY_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, prev_rec_head.tr_prev_rec_id_4);
4540 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);4588 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);
@@ -4555,11 +4603,7 @@
45554603
4556 if (rec_info.ri_ext_rec) {4604 if (rec_info.ri_ext_rec) {
4557 /* Write the log buffer overflow: */ 4605 /* Write the log buffer overflow: */
4558 rec_info.ri_log_buf->er_status_1 = XT_LOG_ENT_EXT_REC_OK;4606 if (!tab_write_ext_record(ot, &rec_info, tab->tab_id, rec_id, log_id, log_offset, self))
4559 XT_SET_DISK_4(rec_info.ri_log_buf->er_data_size_4, rec_info.ri_log_data_size);
4560 XT_SET_DISK_4(rec_info.ri_log_buf->er_tab_id_4, tab->tab_id);
4561 XT_SET_DISK_4(rec_info.ri_log_buf->er_rec_id_4, rec_id);
4562 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))
4563 goto failed_1;4607 goto failed_1;
4564 }4608 }
45654609
@@ -4678,7 +4722,7 @@
4678 if (!myxt_store_row(ot, &rec_info, (char *) after_buf))4722 if (!myxt_store_row(ot, &rec_info, (char *) after_buf))
4679 goto failed_0;4723 goto failed_0;
46804724
4681 rec_info.ri_fix_rec_buf->tr_stat_id_1 = self->st_update_id;4725 rec_info.ri_fix_rec_buf->tr_stat_id_1 = ot->ot_update_id;
4682 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);4726 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_row_id_4, row_id);
4683 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, ot->ot_curr_rec_id);4727 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_prev_rec_id_4, ot->ot_curr_rec_id);
4684 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);4728 XT_SET_DISK_4(rec_info.ri_fix_rec_buf->tr_xact_id_4, self->st_xact_data->xd_start_xn_id);
@@ -4688,7 +4732,7 @@
4688 goto failed_0;4732 goto failed_0;
46894733
4690 /* Link the new variation into the list: */4734 /* Link the new variation into the list: */
4691 XT_TAB_ROW_WRITE_LOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);4735 XT_TAB_ROW_WRITE_LOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], self);
46924736
4693 if (!xt_tab_get_row(ot, row_id, &curr_var_rec_id))4737 if (!xt_tab_get_row(ot, row_id, &curr_var_rec_id))
4694 goto failed_1;4738 goto failed_1;
@@ -4714,7 +4758,7 @@
4714 goto failed_1;4758 goto failed_1;
4715 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));4759 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));
47164760
4717 XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);4761 XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], self);
47184762
4719 /* Add the index references: */4763 /* Add the index references: */
4720 for (idx_cnt=0, ind=tab->tab_dic.dic_keys; idx_cnt<tab->tab_dic.dic_key_count; idx_cnt++, ind++) {4764 for (idx_cnt=0, ind=tab->tab_dic.dic_keys; idx_cnt<tab->tab_dic.dic_key_count; idx_cnt++, ind++) {
@@ -4729,7 +4773,7 @@
4729 goto failed_2;4773 goto failed_2;
4730 }4774 }
47314775
4732 ot->ot_thread->st_statistics.st_row_update++;4776 self->st_statistics.st_row_update++;
4733 return OK;4777 return OK;
47344778
4735 failed_2:4779 failed_2:
@@ -4737,7 +4781,7 @@
4737 goto failed_0;4781 goto failed_0;
47384782
4739 failed_1:4783 failed_1:
4740 XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);4784 XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], self);
47414785
4742 failed_0:4786 failed_0:
4743 return FAILED;4787 return FAILED;
47444788
=== modified file 'storage/pbxt/src/table_xt.h'
--- storage/pbxt/src/table_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/table_xt.h 2010-05-07 08:52:27 +0000
@@ -364,6 +364,9 @@
364 xtWord4 tab_rec_fnum; /* The count of the number of free rows on the free list. */364 xtWord4 tab_rec_fnum; /* The count of the number of free rows on the free list. */
365 xt_mutex_type tab_rec_lock; /* Lock for the free list. */365 xt_mutex_type tab_rec_lock; /* Lock for the free list. */
366366
367 xt_mutex_type tab_ind_stat_lock; /* Aquired when calculating index statistics. */
368 time_t tab_ind_stat_calc_time; /* Zero means the index stats have not be calculated, otherwize this is a time. */
369
367 xt_mutex_type tab_ind_flush_lock; /* Required while the index file is being flushed. */370 xt_mutex_type tab_ind_flush_lock; /* Required while the index file is being flushed. */
368 xtLogID tab_ind_rec_log_id; /* The point before which index entries have been written. */371 xtLogID tab_ind_rec_log_id; /* The point before which index entries have been written. */
369 xtLogOffset tab_ind_rec_log_offset; /* The log offset of the write point. */372 xtLogOffset tab_ind_rec_log_offset; /* The log offset of the write point. */
@@ -372,7 +375,7 @@
372 xtIndexNodeID tab_ind_free; /* The start of the free page list of the index. */375 xtIndexNodeID tab_ind_free; /* The start of the free page list of the index. */
373 XTIndFreeListPtr tab_ind_free_list; /* A cache of the free list (if exists, don't go to disk!) */376 XTIndFreeListPtr tab_ind_free_list; /* A cache of the free list (if exists, don't go to disk!) */
374 xt_mutex_type tab_ind_lock; /* Lock for reading and writing the index free list. */377 xt_mutex_type tab_ind_lock; /* Lock for reading and writing the index free list. */
375 xtWord2 tab_ind_flush_seq;378 xtWord4 tab_ind_flush_seq;
376} XTTableHRec, *XTTableHPtr; /* Heap pointer */379} XTTableHRec, *XTTableHPtr; /* Heap pointer */
377380
378/* Used for an in-memory list of the tables, ordered by ID. */381/* Used for an in-memory list of the tables, ordered by ID. */
@@ -403,6 +406,8 @@
403 size_t ot_rec_size; /* Cached from table for quick access. */406 size_t ot_rec_size; /* Cached from table for quick access. */
404 407
405 char ot_error_key[XT_IDENTIFIER_NAME_SIZE];408 char ot_error_key[XT_IDENTIFIER_NAME_SIZE];
409 struct XTOpenTable *ot_prev_update; /* The UPDATE statement stack! {UPDATE-STACK} */
410 u_int ot_update_id; /* The update statement ID. */
406 xtBool ot_for_update; /* True if reading FOR UPDATE. */411 xtBool ot_for_update; /* True if reading FOR UPDATE. */
407 xtBool ot_is_modify; /* True if UPDATE or DELETE. */412 xtBool ot_is_modify; /* True if UPDATE or DELETE. */
408 xtRowID ot_temp_row_lock; /* The temporary row lock set on this table. */413 xtRowID ot_temp_row_lock; /* The temporary row lock set on this table. */
@@ -507,11 +512,11 @@
507char *xt_tab_file_to_name(size_t size, char *tab_name, char *file_name);512char *xt_tab_file_to_name(size_t size, char *tab_name, char *file_name);
508513
509void xt_create_table(struct XTThread *self, XTPathStrPtr name, XTDictionaryPtr dic);514void xt_create_table(struct XTThread *self, XTPathStrPtr name, XTDictionaryPtr dic);
510XTTableHPtr xt_use_table(struct XTThread *self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, xtBool *opened);515XTTableHPtr xt_use_table(struct XTThread *self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok);
511void xt_sync_flush_table(struct XTThread *self, XTOpenTablePtr ot);516void xt_sync_flush_table(struct XTThread *self, XTOpenTablePtr ot);
512xtBool xt_flush_record_row(XTOpenTablePtr ot, off_t *bytes_flushed, xtBool have_table_loc);517xtBool xt_flush_record_row(XTOpenTablePtr ot, off_t *bytes_flushed, xtBool have_table_loc);
513void xt_flush_table(struct XTThread *self, XTOpenTablePtr ot);518void xt_flush_table(struct XTThread *self, XTOpenTablePtr ot);
514XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, struct XTDatabase *db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic, xtBool *opened);519XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, struct XTDatabase *db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic);
515int xt_use_table_by_id(struct XTThread *self, XTTableHPtr *tab, struct XTDatabase *db, xtTableID tab_id);520int xt_use_table_by_id(struct XTThread *self, XTTableHPtr *tab, struct XTDatabase *db, xtTableID tab_id);
516XTOpenTablePtr xt_open_table(XTTableHPtr tab);521XTOpenTablePtr xt_open_table(XTTableHPtr tab);
517void xt_close_table(XTOpenTablePtr ot, xtBool flush, xtBool have_table_lock);522void xt_close_table(XTOpenTablePtr ot, xtBool flush, xtBool have_table_lock);
518523
=== modified file 'storage/pbxt/src/thread_xt.cc'
--- storage/pbxt/src/thread_xt.cc 2010-01-06 21:27:53 +0000
+++ storage/pbxt/src/thread_xt.cc 2010-05-07 08:52:27 +0000
@@ -96,7 +96,7 @@
96{96{
97 int err;97 int err;
9898
99 log_file = stderr;99 log_file = stdout;
100 log_level = XT_LOG_TRACE;100 log_level = XT_LOG_TRACE;
101 err = xt_p_mutex_init_with_autoname(&log_mutex, NULL);101 err = xt_p_mutex_init_with_autoname(&log_mutex, NULL);
102 if (err) {102 if (err) {
@@ -413,7 +413,8 @@
413 vsnprintf(e->e_err_msg, XT_ERR_MSG_SIZE, fmt, ap);413 vsnprintf(e->e_err_msg, XT_ERR_MSG_SIZE, fmt, ap);
414414
415 /* Make the first character of the message upper case: */415 /* Make the first character of the message upper case: */
416 if (isalpha(e->e_err_msg[0]) && islower(e->e_err_msg[0]))416 /* This did not work for foreign languages! */
417 if (e->e_err_msg[0] >= 'a' && e->e_err_msg[0] <= 'z')
417 e->e_err_msg[0] = (char) toupper(e->e_err_msg[0]);418 e->e_err_msg[0] = (char) toupper(e->e_err_msg[0]);
418419
419 if (func && *func && *func != '-')420 if (func && *func && *func != '-')
@@ -793,11 +794,9 @@
793794
794 xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);795 xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);
795 xt_strcat(sizeof(buffer), buffer, ".");796 xt_strcat(sizeof(buffer), buffer, ".");
796 xt_strcpy(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));797 xt_strcat(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
797 xt_strcat(sizeof(buffer), buffer, ".");
798 xt_strcat(sizeof(buffer), buffer, item2);
799798
800 xt_register_ixterr(func, file, line, xt_err, buffer);799 xt_register_i2xterr(func, file, line, xt_err, buffer, item2);
801}800}
802801
803xtPublic void xt_register_taberr(c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item)802xtPublic void xt_register_taberr(c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item)
@@ -806,7 +805,7 @@
806805
807 xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);806 xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);
808 xt_strcat(sizeof(buffer), buffer, ".");807 xt_strcat(sizeof(buffer), buffer, ".");
809 xt_strcpy(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));808 xt_strcat(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
810809
811 xt_register_ixterr(func, file, line, xt_err, buffer);810 xt_register_ixterr(func, file, line, xt_err, buffer);
812}811}
@@ -1013,7 +1012,7 @@
10131012
1014typedef void *(*ThreadMainFunc)(XTThreadPtr self);1013typedef void *(*ThreadMainFunc)(XTThreadPtr self);
10151014
1016extern "C" void *thr_main_pbxt(void *data)1015extern "C" void *xt_thread_main(void *data)
1017{1016{
1018 ThreadDataPtr td = (ThreadDataPtr) data;1017 ThreadDataPtr td = (ThreadDataPtr) data;
1019 XTThreadPtr self = td->td_thr;1018 XTThreadPtr self = td->td_thr;
@@ -1168,6 +1167,14 @@
1168 /* Align the number of threads: */1167 /* Align the number of threads: */
1169 xt_thr_maximum_threads = xt_align_size(max_threads, XT_XS_LOCK_ALIGN);1168 xt_thr_maximum_threads = xt_align_size(max_threads, XT_XS_LOCK_ALIGN);
11701169
1170#ifdef XT_TRACK_CONNECTIONS
1171 if (xt_thr_maximum_threads > XT_TRACK_MAX_CONNS) {
1172 xt_log_error(XT_NS_CONTEXT, XT_LOG_FATAL, XT_ERR_TOO_MANY_THREADS, 0,
1173 "XT_TRACK_CONNECTIONS is enabled and xt_thr_maximum_threads > XT_TRACK_MAX_CONNS");
1174 goto failed;
1175 }
1176#endif
1177
1171#ifdef HANDLE_SIGNALS1178#ifdef HANDLE_SIGNALS
1172 if (!thr_setup_signals())1179 if (!thr_setup_signals())
1173 return NULL;1180 return NULL;
@@ -1503,10 +1510,10 @@
1503 pthread_attr_t attr = { 0, 0, 0 };1510 pthread_attr_t attr = { 0, 0, 0 };
15041511
1505 attr.priority = THREAD_PRIORITY_NORMAL;1512 attr.priority = THREAD_PRIORITY_NORMAL;
1506 err = pthread_create(&child_thread, &attr, thr_main_pbxt, &data);1513 err = pthread_create(&child_thread, &attr, xt_thread_main, &data);
1507 }1514 }
1508#else1515#else
1509 err = pthread_create(&child_thread, NULL, thr_main_pbxt, &data);1516 err = pthread_create(&child_thread, NULL, xt_thread_main, &data);
1510#endif1517#endif
1511 if (err) {1518 if (err) {
1512 xt_free_thread(child);1519 xt_free_thread(child);
15131520
=== modified file 'storage/pbxt/src/thread_xt.h'
--- storage/pbxt/src/thread_xt.h 2010-01-06 21:27:53 +0000
+++ storage/pbxt/src/thread_xt.h 2010-05-07 08:52:27 +0000
@@ -132,6 +132,7 @@
132struct XTXactLog;132struct XTXactLog;
133struct XTXactData;133struct XTXactData;
134struct XTDatabase;134struct XTDatabase;
135struct XTOpenTable;
135136
136typedef void (*XTThreadFreeFunc)(struct XTThread *self, void *data);137typedef void (*XTThreadFreeFunc)(struct XTThread *self, void *data);
137138
@@ -307,8 +308,7 @@
307 xtThreadID *st_thread_list;308 xtThreadID *st_thread_list;
308309
309 /* Used to prevent a record from being updated twice in one statement. */310 /* Used to prevent a record from being updated twice in one statement. */
310 xtBool st_is_update; /* TRUE if this is an UPDATE statement. */311 struct XTOpenTable *st_is_update; /* TRUE if this is an UPDATE statement. {UPDATE-STACK} */
311 u_int st_update_id; /* The update statement ID. */
312312
313 XTRowLockListRec st_lock_list; /* The thread row lock list (drop locks on transaction end). */313 XTRowLockListRec st_lock_list; /* The thread row lock list (drop locks on transaction end). */
314 XTStatisticsRec st_statistics; /* Accumulated statistics for this thread. */314 XTStatisticsRec st_statistics; /* Accumulated statistics for this thread. */
@@ -536,7 +536,10 @@
536 * Function prototypes536 * Function prototypes
537 */537 */
538538
539extern "C" void *thr_main_pbxt(void *data);539/* OpenSolaris has thr_main in /usr/include/thread.h (name conflict)
540 * Thanks for the tip Monty!
541 */
542extern "C" void *xt_thread_main(void *data);
540543
541void xt_get_now(char *buffer, size_t len);544void xt_get_now(char *buffer, size_t len);
542xtBool xt_init_logging(void);545xtBool xt_init_logging(void);
543546
=== modified file 'storage/pbxt/src/trace_xt.cc'
--- storage/pbxt/src/trace_xt.cc 2009-12-22 10:33:20 +0000
+++ storage/pbxt/src/trace_xt.cc 2010-05-07 08:52:27 +0000
@@ -36,6 +36,7 @@
36#ifdef DEBUG36#ifdef DEBUG
37//#define PRINT_TRACE37//#define PRINT_TRACE
38//#define RESET_AFTER_DUMP38//#define RESET_AFTER_DUMP
39//#define DUMP_TO_STDOUT
39#endif40#endif
4041
41static xtBool trace_initialized = FALSE;42static xtBool trace_initialized = FALSE;
@@ -109,10 +110,10 @@
109 xt_lock_mutex_ns(&trace_mutex);110 xt_lock_mutex_ns(&trace_mutex);
110 if (trace_log_end > trace_log_offset+1) {111 if (trace_log_end > trace_log_offset+1) {
111 trace_log_buffer[trace_log_end] = 0;112 trace_log_buffer[trace_log_end] = 0;
112 fprintf(stderr, "%s", trace_log_buffer + trace_log_offset + 1);113 printf("%s", trace_log_buffer + trace_log_offset + 1);
113 }114 }
114 trace_log_buffer[trace_log_offset] = 0;115 trace_log_buffer[trace_log_offset] = 0;
115 fprintf(stderr, "%s", trace_log_buffer);116 printf("%s", trace_log_buffer);
116 trace_log_offset = 0;117 trace_log_offset = 0;
117 trace_log_end = 0;118 trace_log_end = 0;
118 xt_unlock_mutex_ns(&trace_mutex);119 xt_unlock_mutex_ns(&trace_mutex);
@@ -121,9 +122,18 @@
121122
122xtPublic void xt_dump_trace(void)123xtPublic void xt_dump_trace(void)
123{124{
124 FILE *fp;125 if (trace_log_offset) {
126#ifdef DUMP_TO_STDOUT
127 if (trace_log_end > trace_log_offset+1) {
128 trace_log_buffer[trace_log_end] = 0;
129 printf("%s", trace_log_buffer + trace_log_offset + 1);
130 }
131 trace_log_buffer[trace_log_offset] = 0;
132 printf("%s", trace_log_buffer);
133 printf("\n");
134#else
135 FILE *fp;
125136
126 if (trace_log_offset) {
127 fp = fopen("pbxt.log", "w");137 fp = fopen("pbxt.log", "w");
128138
129 xt_lock_mutex_ns(&trace_mutex);139 xt_lock_mutex_ns(&trace_mutex);
@@ -136,6 +146,7 @@
136 fprintf(fp, "%s", trace_log_buffer);146 fprintf(fp, "%s", trace_log_buffer);
137 fclose(fp);147 fclose(fp);
138 }148 }
149#endif
139150
140#ifdef RESET_AFTER_DUMP151#ifdef RESET_AFTER_DUMP
141 trace_log_offset = 0;152 trace_log_offset = 0;
@@ -379,9 +390,9 @@
379 ptr = conn_info;390 ptr = conn_info;
380 for (int i=0; i<XT_TRACK_MAX_CONNS; i++) {391 for (int i=0; i<XT_TRACK_MAX_CONNS; i++) {
381 if (ptr->ci_curr_xact_id || ptr->ci_prev_xact_id) {392 if (ptr->ci_curr_xact_id || ptr->ci_prev_xact_id) {
382 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);393 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);
383 if (i+1<XT_TRACK_MAX_CONNS) {394 if (i+1<XT_TRACK_MAX_CONNS) {
384 fprintf(stderr, " diff=%d\n", (int) (ptr+1)->ci_curr_xact_id - (int) ptr->ci_curr_xact_id);395 printf(" diff=%d\n", (int) (ptr+1)->ci_curr_xact_id - (int) ptr->ci_curr_xact_id);
385 }396 }
386 }397 }
387 ptr++;398 ptr++;
388399
=== modified file 'storage/pbxt/src/trace_xt.h'
--- storage/pbxt/src/trace_xt.h 2009-08-17 11:12:36 +0000
+++ storage/pbxt/src/trace_xt.h 2010-05-07 08:52:27 +0000
@@ -51,7 +51,9 @@
51 * CONNECTION TRACKING51 * CONNECTION TRACKING
52 */52 */
5353
54#ifdef DEBUG
54#define XT_TRACK_CONNECTIONS55#define XT_TRACK_CONNECTIONS
56#endif
5557
56#ifdef XT_TRACK_CONNECTIONS58#ifdef XT_TRACK_CONNECTIONS
57#define XT_TRACK_MAX_CONNS 50059#define XT_TRACK_MAX_CONNS 500
5860
=== modified file 'storage/pbxt/src/xaction_xt.cc'
--- storage/pbxt/src/xaction_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/xaction_xt.cc 2010-05-07 08:52:27 +0000
@@ -1326,7 +1326,7 @@
1326 }1326 }
13271327
1328 /* Write and flush the transaction log: */1328 /* Write and flush the transaction log: */
1329 if (!xt_xlog_log_data(thread, sizeof(XTXactEndEntryDRec), (XTXactLogBufferDPtr) &entry, TRUE)) {1329 if (!xt_xlog_log_data(thread, sizeof(XTXactEndEntryDRec), (XTXactLogBufferDPtr) &entry, xt_db_flush_log_at_trx_commit)) {
1330 ok = FALSE;1330 ok = FALSE;
1331 status = XT_LOG_ENT_ABORT;1331 status = XT_LOG_ENT_ABORT;
1332 /* Make sure this is done, if we failed to log1332 /* Make sure this is done, if we failed to log
@@ -1440,16 +1440,23 @@
1440 /* Don't get too far ahead of the sweeper! */1440 /* Don't get too far ahead of the sweeper! */
1441 if (writer) {1441 if (writer) {
1442#ifdef XT_WAIT_FOR_CLEANUP1442#ifdef XT_WAIT_FOR_CLEANUP
1443 xtXactID wait_xn_id;1443 if (db->db_sw_faster & XT_SW_TOO_FAR_BEHIND) {
1444 1444 /* Set a maximum wait time (1/100s) */
1445 /* This is the transaction that was committed 3 transactions ago: */1445 xtWord8 then = xt_trace_clock() + (xtWord8) 100000;
1446 wait_xn_id = thread->st_prev_xact[thread->st_last_xact];1446 xtXactID wait_xn_id;
1447 thread->st_prev_xact[thread->st_last_xact] = xn_id;1447
1448 /* This works because XT_MAX_XACT_BEHIND == 2! */1448 /* This is the transaction that was committed 3 transactions ago: */
1449 ASSERT_NS((thread->st_last_xact + 1) % XT_MAX_XACT_BEHIND == (thread->st_last_xact ^ 1));1449 wait_xn_id = thread->st_prev_xact[thread->st_last_xact];
1450 thread->st_last_xact ^= 1;1450 thread->st_prev_xact[thread->st_last_xact] = xn_id;
1451 while (xt_xn_is_before(db->db_xn_to_clean_id, wait_xn_id) && (db->db_sw_faster & XT_SW_TOO_FAR_BEHIND)) {1451 /* This works because XT_MAX_XACT_BEHIND == 2! */
1452 xt_critical_wait();1452 ASSERT_NS((thread->st_last_xact + 1) % XT_MAX_XACT_BEHIND == (thread->st_last_xact ^ 1));
1453 thread->st_last_xact ^= 1;
1454
1455 while (xt_xn_is_before(db->db_xn_to_clean_id, wait_xn_id) && (db->db_sw_faster & XT_SW_TOO_FAR_BEHIND)) {
1456 if (xt_trace_clock() >= then)
1457 break;
1458 xt_critical_wait();
1459 }
1453 }1460 }
1454#else1461#else
1455 if ((db->db_sw_faster & XT_SW_TOO_FAR_BEHIND) != 0) {1462 if ((db->db_sw_faster & XT_SW_TOO_FAR_BEHIND) != 0) {
@@ -1486,7 +1493,7 @@
1486 entry.xt_status_1 = XT_LOG_ENT_NEW_TAB;1493 entry.xt_status_1 = XT_LOG_ENT_NEW_TAB;
1487 entry.xt_checksum_1 = XT_CHECKSUM_1(tab_id);1494 entry.xt_checksum_1 = XT_CHECKSUM_1(tab_id);
1488 XT_SET_DISK_4(entry.xt_tab_id_4, tab_id);1495 XT_SET_DISK_4(entry.xt_tab_id_4, tab_id);
1489 return xt_xlog_log_data(self, sizeof(XTXactNewTabEntryDRec), (XTXactLogBufferDPtr) &entry, TRUE);1496 return xt_xlog_log_data(self, sizeof(XTXactNewTabEntryDRec), (XTXactLogBufferDPtr) &entry, XT_XLOG_WRITE_AND_FLUSH);
1490}1497}
14911498
1492xtPublic int xt_xn_status(XTOpenTablePtr ot, xtXactID xn_id, xtRecordID XT_UNUSED(rec_id))1499xtPublic int xt_xn_status(XTOpenTablePtr ot, xtXactID xn_id, xtRecordID XT_UNUSED(rec_id))
@@ -2266,6 +2273,7 @@
2266 xt_log_and_clear_exception(self);2273 xt_log_and_clear_exception(self);
2267 break;2274 break;
2268 }2275 }
2276
2269 prev_rec_id = next_rec_id;2277 prev_rec_id = next_rec_id;
2270 next_rec_id = XT_GET_DISK_4(prev_rec_head.tr_prev_rec_id_4);2278 next_rec_id = XT_GET_DISK_4(prev_rec_head.tr_prev_rec_id_4);
2271 }2279 }
@@ -2461,7 +2469,7 @@
2461 cu.xc_checksum_1 = XT_CHECKSUM_1(XT_CHECKSUM4_XACT(xact->xd_start_xn_id));2469 cu.xc_checksum_1 = XT_CHECKSUM_1(XT_CHECKSUM4_XACT(xact->xd_start_xn_id));
2462 XT_SET_DISK_4(cu.xc_xact_id_4, xact->xd_start_xn_id);2470 XT_SET_DISK_4(cu.xc_xact_id_4, xact->xd_start_xn_id);
24632471
2464 if (!xt_xlog_log_data(self, sizeof(XTXactCleanupEntryDRec), (XTXactLogBufferDPtr) &cu, FALSE))2472 if (!xt_xlog_log_data(self, sizeof(XTXactCleanupEntryDRec), (XTXactLogBufferDPtr) &cu, XT_XLOG_NO_WRITE_NO_FLUSH))
2465 return FAILED;2473 return FAILED;
24662474
2467 ss->ss_flush_pending = TRUE;2475 ss->ss_flush_pending = TRUE;
@@ -2656,7 +2664,9 @@
2656 * we flush the log.2664 * we flush the log.
2657 */2665 */
2658 if (now >= idle_start + 2) {2666 if (now >= idle_start + 2) {
2659 if (!xt_xlog_flush_log(db, self))2667 /* Don't do this if flusher is active! */
2668 if (!db->db_fl_thread &&
2669 !xt_xlog_flush_log(db, self))
2660 xt_throw(self);2670 xt_throw(self);
2661 ss->ss_flush_pending = FALSE;2671 ss->ss_flush_pending = FALSE;
2662 }2672 }
26632673
=== modified file 'storage/pbxt/src/xaction_xt.h'
--- storage/pbxt/src/xaction_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/xaction_xt.h 2010-05-07 08:52:27 +0000
@@ -153,14 +153,14 @@
153#define XT_XACT_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)153#define XT_XACT_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
154#define XT_XACT_FREE_LOCK(s, i) xt_spinxslock_free(s, i) 154#define XT_XACT_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
155#define XT_XACT_READ_LOCK(i, s) xt_spinxslock_slock(i)155#define XT_XACT_READ_LOCK(i, s) xt_spinxslock_slock(i)
156#define XT_XACT_WRITE_LOCK(i, s) xt_spinxslock_xlock(i, (s)->t_id)156#define XT_XACT_WRITE_LOCK(i, s) xt_spinxslock_xlock(i, FALSE, (s)->t_id)
157#define XT_XACT_UNLOCK(i, s, b) xt_spinxslock_unlock(i, b)157#define XT_XACT_UNLOCK(i, s, b) xt_spinxslock_unlock(i, b)
158#else158#else
159#define XT_XACT_LOCK_TYPE XTSkewRWLockRec159#define XT_XACT_LOCK_TYPE XTSkewRWLockRec
160#define XT_XACT_INIT_LOCK(s, i) xt_skewrwlock_init_with_autoname(s, i)160#define XT_XACT_INIT_LOCK(s, i) xt_skewrwlock_init_with_autoname(s, i)
161#define XT_XACT_FREE_LOCK(s, i) xt_skewrwlock_free(s, i) 161#define XT_XACT_FREE_LOCK(s, i) xt_skewrwlock_free(s, i)
162#define XT_XACT_READ_LOCK(i, s) xt_skewrwlock_slock(i)162#define XT_XACT_READ_LOCK(i, s) xt_skewrwlock_slock(i)
163#define XT_XACT_WRITE_LOCK(i, s) xt_skewrwlock_xlock(i, (s)->t_id)163#define XT_XACT_WRITE_LOCK(i, s) xt_skewrwlock_xlock(i, FALSE, (s)->t_id)
164#define XT_XACT_UNLOCK(i, s, b) xt_skewrwlock_unlock(i, b)164#define XT_XACT_UNLOCK(i, s, b) xt_skewrwlock_unlock(i, b)
165#endif165#endif
166166
167167
=== modified file 'storage/pbxt/src/xactlog_xt.cc'
--- storage/pbxt/src/xactlog_xt.cc 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/xactlog_xt.cc 2010-05-07 08:52:27 +0000
@@ -719,14 +719,14 @@
719 }719 }
720}720}
721721
722#define WR_NO_SPACE 1722#define WR_NO_SPACE 1 /* Write because there is no space, or some other reason */
723#define WR_FLUSH 2723#define WR_FLUSH 2 /* Normal commit, write and flush */
724724
725xtBool XTDatabaseLog::xlog_flush(XTThreadPtr thread)725xtBool XTDatabaseLog::xlog_flush(XTThreadPtr thread)
726{726{
727 if (!xlog_flush_pending())727 if (!xlog_flush_pending())
728 return OK;728 return OK;
729 return xlog_append(thread, 0, NULL, 0, NULL, TRUE, NULL, NULL);729 return xlog_append(thread, 0, NULL, 0, NULL, XT_XLOG_WRITE_AND_FLUSH, NULL, NULL);
730}730}
731731
732xtBool XTDatabaseLog::xlog_flush_pending()732xtBool XTDatabaseLog::xlog_flush_pending()
@@ -754,7 +754,7 @@
754 * This function returns the log ID and offset of754 * This function returns the log ID and offset of
755 * the data write position.755 * the data write position.
756 */756 */
757xtBool XTDatabaseLog::xlog_append(XTThreadPtr thread, size_t size1, xtWord1 *data1, size_t size2, xtWord1 *data2, xtBool commit, xtLogID *log_id, xtLogOffset *log_offset)757xtBool 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)
758{758{
759 int write_reason = 0;759 int write_reason = 0;
760 xtLogID req_flush_log_id;760 xtLogID req_flush_log_id;
@@ -763,19 +763,20 @@
763 xtWord8 flush_time;763 xtWord8 flush_time;
764 xtWord2 sum;764 xtWord2 sum;
765765
766 /* The first size value must be set, of the second is set! */
767 ASSERT_NS(size1 || !size2);
768
766 if (!size1) {769 if (!size1) {
767 /* Just flush the buffer... */770 /* Just flush the buffer... */
768 xt_lck_slock(&xl_buffer_lock);771 xt_lck_slock(&xl_buffer_lock);
769 write_reason = WR_FLUSH;772 write_reason = flush_log_at_trx_commit == XT_XLOG_WRITE_AND_FLUSH ? WR_FLUSH : WR_NO_SPACE;
770 req_flush_log_id = xl_append_log_id;773 req_flush_log_id = xl_append_log_id;
771 req_flush_log_offset = xl_append_log_offset + xl_append_buf_pos;774 req_flush_log_offset = xl_append_log_offset + xl_append_buf_pos;
772 xt_spinlock_unlock(&xl_buffer_lock);775 xt_spinlock_unlock(&xl_buffer_lock);
773 goto write_log_to_file;776 goto write_log_to_file;
774 }777 }
775 else {778 req_flush_log_id = 0;
776 req_flush_log_id = 0;779 req_flush_log_offset = 0;
777 req_flush_log_offset = 0;
778 }
779780
780 /*781 /*
781 * This is a dirty read, which will send us to the782 * This is a dirty read, which will send us to the
@@ -866,11 +867,17 @@
866 return OK;867 return OK;
867 }868 }
868 }869 }
869 else {870 else if (size1) {
870 /* It may be that there is now space in the append buffer: */871 /* It may be that there is now space in the append buffer: */
871 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers)872 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers)
872 goto copy_to_log_buffer;873 goto copy_to_log_buffer;
873 }874 }
875 else {
876 /* We are just writing the buffer! */
877 ASSERT_NS(write_reason == WR_NO_SPACE);
878 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)
879 return OK;
880 }
874881
875 if (xt_trace_clock() >= then) {882 if (xt_trace_clock() >= then) {
876 xt_lock_mutex_ns(&xl_write_lock);883 xt_lock_mutex_ns(&xl_write_lock);
@@ -922,12 +929,18 @@
922 ASSERT_NS(xt_comp_log_pos(xl_write_log_id, xl_write_log_offset, xl_append_log_id, xl_append_log_offset) <= 0);929 ASSERT_NS(xt_comp_log_pos(xl_write_log_id, xl_write_log_offset, xl_append_log_id, xl_append_log_offset) <= 0);
923 return OK;930 return OK;
924 }931 }
925 goto write_log_to_file;932 }
926 }933 else if (size1) {
927934 /* It may be that there is now space in the append buffer: */
928 /* It may be that there is now space in the append buffer: */935 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers)
929 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers)936 goto copy_to_log_buffer;
930 goto copy_to_log_buffer;937 }
938 else {
939 /* We are just writing the buffer! */
940 ASSERT_NS(write_reason == WR_NO_SPACE);
941 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)
942 return OK;
943 }
931 944
932 goto write_log_to_file;945 goto write_log_to_file;
933 }946 }
@@ -952,7 +965,7 @@
952 return OK;965 return OK;
953 }966 }
954 /* Not flushed, but what about written? */967 /* Not flushed, but what about written? */
955 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) {968 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) {
956 /* The write position is after or equal to the required flush969 /* The write position is after or equal to the required flush
957 * position. This means that all we have to do is flush970 * position. This means that all we have to do is flush
958 * to satisfy the writers condition.971 * to satisfy the writers condition.
@@ -960,7 +973,7 @@
960 xtBool ok = TRUE;973 xtBool ok = TRUE;
961974
962 if (xl_log_id != xl_write_log_id)975 if (xl_log_id != xl_write_log_id)
963 ok = xlog_open_log(xl_write_log_id, xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : 0), thread);976 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);
964977
965 if (ok) {978 if (ok) {
966 if (xl_db->db_co_busy) {979 if (xl_db->db_co_busy) {
@@ -979,7 +992,7 @@
979992
980 xt_lock_mutex_ns(&xl_db->db_wr_lock);993 xt_lock_mutex_ns(&xl_db->db_wr_lock);
981 xl_flush_log_id = xl_write_log_id;994 xl_flush_log_id = xl_write_log_id;
982 xl_flush_log_offset = xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : 0);995 xl_flush_log_offset = xl_write_log_offset + (xl_write_done ? xl_write_buf_pos : xl_write_buf_pos_start);
983 /*996 /*
984 * We have written data to the log, wake the writer to commit997 * We have written data to the log, wake the writer to commit
985 * the data to the database.998 * the data to the database.
@@ -1000,8 +1013,11 @@
1000 return ok;1013 return ok;
1001 }1014 }
1002 }1015 }
1003 else {1016 else if (size1) {
1004 /* If there is space in the buffer, then we can go on1017 /* If the amounf of data to be written is 0, then we are just required
1018 * to write the transaction buffer.
1019 *
1020 * If there is space in the buffer, then we can go on
1005 * to copy our data into the buffer:1021 * to copy our data into the buffer:
1006 */1022 */
1007 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers) {1023 if (xl_append_buf_pos + size1 + size2 <= xl_size_of_buffers) {
@@ -1016,6 +1032,21 @@
1016 goto copy_to_log_buffer;1032 goto copy_to_log_buffer;
1017 }1033 }
1018 }1034 }
1035 else {
1036 /* We are just writing the buffer! */
1037 ASSERT_NS(write_reason == WR_NO_SPACE);
1038 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) {
1039#ifdef XT_XLOG_WAIT_SPINS
1040 xt_writing = 0;
1041 if (xt_waiting)
1042 xt_cond_wakeall(&xl_write_cond);
1043#else
1044 xt_writing = FALSE;
1045 xt_cond_wakeall(&xl_write_cond);
1046#endif
1047 return OK;
1048 }
1049 }
10191050
1020 rewrite:1051 rewrite:
1021 /* If the current write buffer has been written, then1052 /* If the current write buffer has been written, then
@@ -1109,7 +1140,8 @@
1109 part_size = 512 - part_size;1140 part_size = 512 - part_size;
1110 xl_write_buffer[xl_write_buf_pos] = XT_LOG_ENT_END_OF_LOG;1141 xl_write_buffer[xl_write_buf_pos] = XT_LOG_ENT_END_OF_LOG;
1111#ifdef HAVE_valgrind1142#ifdef HAVE_valgrind
1112 memset(xl_write_buffer + xl_write_buf_pos + 1, 0x66, part_size);1143 if (part_size > 1)
1144 memset(xl_write_buffer + xl_write_buf_pos + 1, 0x66, part_size - 1);
1113#endif1145#endif
1114 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))1146 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))
1115 goto write_failed; 1147 goto write_failed;
@@ -1197,9 +1229,13 @@
1197 xt_writing = FALSE;1229 xt_writing = FALSE;
1198 xt_cond_wakeall(&xl_write_cond);1230 xt_cond_wakeall(&xl_write_cond);
1199#endif1231#endif
1232
1233 if (size1 == 0)
1234 return OK;
1200 }1235 }
12011236
1202 copy_to_log_buffer:1237 copy_to_log_buffer:
1238 ASSERT_NS(size1);
1203 xt_spinlock_lock(&xl_buffer_lock);1239 xt_spinlock_lock(&xl_buffer_lock);
1204 /* Now we have to check again. The check above was a dirty read!1240 /* Now we have to check again. The check above was a dirty read!
1205 */1241 */
@@ -1291,11 +1327,14 @@
1291 if (log_offset)1327 if (log_offset)
1292 *log_offset = xl_append_log_offset + xl_append_buf_pos;1328 *log_offset = xl_append_log_offset + xl_append_buf_pos;
1293 xl_append_buf_pos += size1 + size2;1329 xl_append_buf_pos += size1 + size2;
1294 if (commit) {1330 if (flush_log_at_trx_commit != XT_XLOG_NO_WRITE_NO_FLUSH) {
1295 write_reason = WR_FLUSH;1331 write_reason = flush_log_at_trx_commit == XT_XLOG_WRITE_AND_FLUSH ? WR_FLUSH : WR_NO_SPACE;
1296 req_flush_log_id = xl_append_log_id;1332 req_flush_log_id = xl_append_log_id;
1297 req_flush_log_offset = xl_append_log_offset + xl_append_buf_pos;1333 req_flush_log_offset = xl_append_log_offset + xl_append_buf_pos;
1298 xt_spinlock_unlock(&xl_buffer_lock);1334 xt_spinlock_unlock(&xl_buffer_lock);
1335 /* We have written the data already! */
1336 size1 = 0;
1337 size2 = 0;
1299 goto write_log_to_file;1338 goto write_log_to_file;
1300 }1339 }
13011340
@@ -1485,9 +1524,9 @@
1485 return db->db_xlog.xlog_flush(thread);1524 return db->db_xlog.xlog_flush(thread);
1486}1525}
14871526
1488xtPublic xtBool xt_xlog_log_data(XTThreadPtr thread, size_t size, XTXactLogBufferDPtr log_entry, xtBool commit)1527xtPublic xtBool xt_xlog_log_data(XTThreadPtr thread, size_t size, XTXactLogBufferDPtr log_entry, int flush_log_at_trx_commit)
1489{1528{
1490 return thread->st_database->db_xlog.xlog_append(thread, size, (xtWord1 *) log_entry, 0, NULL, commit, NULL, NULL);1529 return thread->st_database->db_xlog.xlog_append(thread, size, (xtWord1 *) log_entry, 0, NULL, flush_log_at_trx_commit, NULL, NULL);
1491}1530}
14921531
1493/* Allocate a record from the free list. */1532/* Allocate a record from the free list. */
@@ -1498,7 +1537,7 @@
1498 xtWord4 sum = 0;1537 xtWord4 sum = 0;
1499 int check_size = 1;1538 int check_size = 1;
1500 XTXactDataPtr xact = NULL;1539 XTXactDataPtr xact = NULL;
1501 xtBool commit = FALSE;1540 int flush_log_at_trx_commit = XT_XLOG_NO_WRITE_NO_FLUSH;
15021541
1503 switch (status) {1542 switch (status) {
1504 case XT_LOG_ENT_REC_MODIFIED:1543 case XT_LOG_ENT_REC_MODIFIED:
@@ -1613,7 +1652,7 @@
1613 XT_SET_DISK_4(log_entry.xp.xp_xact_id_4, op_seq);1652 XT_SET_DISK_4(log_entry.xp.xp_xact_id_4, op_seq);
1614 log_entry.xp.xp_xa_len_1 = (xtWord1) size;1653 log_entry.xp.xp_xa_len_1 = (xtWord1) size;
1615 len = offsetof(XTXactPrepareEntryDRec, xp_xa_data);1654 len = offsetof(XTXactPrepareEntryDRec, xp_xa_data);
1616 commit = TRUE;1655 flush_log_at_trx_commit = xt_db_flush_log_at_trx_commit;
1617 break;1656 break;
1618 default:1657 default:
1619 ASSERT_NS(FALSE);1658 ASSERT_NS(FALSE);
@@ -1652,9 +1691,9 @@
1652 xt_print_log_record(0, 0, &log_entry);1691 xt_print_log_record(0, 0, &log_entry);
1653#endif1692#endif
1654 if (xact)1693 if (xact)
1655 return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, commit, &xact->xd_begin_log, &xact->xd_begin_offset);1694 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);
16561695
1657 return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, commit, NULL, NULL);1696 return thread->st_database->db_xlog.xlog_append(thread, len, (xtWord1 *) &log_entry, size, data, flush_log_at_trx_commit, NULL, NULL);
1658}1697}
16591698
1660/*1699/*
16611700
=== modified file 'storage/pbxt/src/xactlog_xt.h'
--- storage/pbxt/src/xactlog_xt.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/xactlog_xt.h 2010-05-07 08:52:27 +0000
@@ -75,6 +75,10 @@
75#define XT_DELETE_LOGS 175#define XT_DELETE_LOGS 1
76#define XT_KEEP_LOGS 276#define XT_KEEP_LOGS 2
7777
78#define XT_XLOG_NO_WRITE_NO_FLUSH 0
79#define XT_XLOG_WRITE_AND_FLUSH 1
80#define XT_XLOG_WRITE_AND_NO_FLUSH 2
81
78/* LOG CACHE ---------------------------------------------------- */82/* LOG CACHE ---------------------------------------------------- */
7983
80typedef struct XTXLogBlock {84typedef struct XTXLogBlock {
@@ -443,7 +447,7 @@
443 void xlog_name(size_t size, char *path, xtLogID log_id);447 void xlog_name(size_t size, char *path, xtLogID log_id);
444 int xlog_delete_log(xtLogID del_log_id, struct XTThread *thread);448 int xlog_delete_log(xtLogID del_log_id, struct XTThread *thread);
445449
446 xtBool xlog_append(struct XTThread *thread, size_t size1, xtWord1 *data1, size_t size2, xtWord1 *data2, xtBool commit, xtLogID *log_id, xtLogOffset *log_offset);450 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);
447 xtBool xlog_flush(struct XTThread *thread);451 xtBool xlog_flush(struct XTThread *thread);
448 xtBool xlog_flush_pending();452 xtBool xlog_flush_pending();
449453
@@ -464,7 +468,7 @@
464} XTDatabaseLogRec, *XTDatabaseLogPtr;468} XTDatabaseLogRec, *XTDatabaseLogPtr;
465469
466xtBool xt_xlog_flush_log(struct XTDatabase *db, struct XTThread *thread);470xtBool xt_xlog_flush_log(struct XTDatabase *db, struct XTThread *thread);
467xtBool xt_xlog_log_data(struct XTThread *thread, size_t len, XTXactLogBufferDPtr log_entry, xtBool commit);471xtBool xt_xlog_log_data(struct XTThread *thread, size_t len, XTXactLogBufferDPtr log_entry, int flush_log_at_trx_commit);
468xtBool 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);472xtBool 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);
469473
470void xt_xlog_init(struct XTThread *self, size_t cache_size);474void xt_xlog_init(struct XTThread *self, size_t cache_size);
471475
=== modified file 'storage/pbxt/src/xt_defs.h'
--- storage/pbxt/src/xt_defs.h 2009-11-24 10:55:06 +0000
+++ storage/pbxt/src/xt_defs.h 2010-05-07 08:52:27 +0000
@@ -221,7 +221,7 @@
221 */221 */
222222
223#ifdef DEBUG223#ifdef DEBUG
224//#define XT_USE_GLOBAL_DEBUG_SIZES224#define XT_USE_GLOBAL_DEBUG_SIZES
225#endif225#endif
226226
227/*227/*
@@ -392,6 +392,11 @@
392//#define XT_NO_ATOMICS392//#define XT_NO_ATOMICS
393#endif393#endif
394394
395/* When pbxt_flush_log_at_trx_commit != 1, the transaction log is flushed
396 * at regular intervals. Set the interval here.
397 */
398#define XT_XLOG_FLUSH_FREQ 1000
399
395/* ----------------------------------------------------------------------400/* ----------------------------------------------------------------------
396 * GLOBAL CONSTANTS401 * GLOBAL CONSTANTS
397 */402 */
@@ -457,21 +462,24 @@
457#ifdef XT_USE_GLOBAL_DEBUG_SIZES462#ifdef XT_USE_GLOBAL_DEBUG_SIZES
458463
459//#undef XT_ROW_RWLOCKS464//#undef XT_ROW_RWLOCKS
460//#define XT_ROW_RWLOCKS 2465//#define XT_ROW_RWLOCKS 2
461466
462//#undef XT_TAB_MIN_VAR_REC_LENGTH467//#undef XT_TAB_MIN_VAR_REC_LENGTH
463//#define XT_TAB_MIN_VAR_REC_LENGTH 20468//#define XT_TAB_MIN_VAR_REC_LENGTH 20
464469
465//#undef XT_ROW_LOCK_COUNT470//#undef XT_ROW_LOCK_COUNT
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches