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