Merge lp:~paul-mccullagh/maria/pbxt-1.0.11-7 into lp:maria/5.3
- pbxt-1.0.11-7
- Merge into 5.3
Status: | Rejected |
---|---|
Rejected by: | Sergei Golubchik |
Proposed branch: | lp:~paul-mccullagh/maria/pbxt-1.0.11-7 |
Merge into: | lp:maria/5.3 |
Diff against target: |
1570 lines (+652/-100) 21 files modified
mysql-test/suite/pbxt/r/negation_elimination.result (+1/-1) mysql-test/suite/pbxt/r/select.result (+19/-19) storage/pbxt/ChangeLog (+43/-1) storage/pbxt/src/cache_xt.cc (+20/-1) storage/pbxt/src/cache_xt.h (+8/-0) storage/pbxt/src/database_xt.h (+1/-0) storage/pbxt/src/datadic_xt.cc (+2/-7) storage/pbxt/src/datalog_xt.cc (+4/-4) storage/pbxt/src/discover_xt.cc (+14/-2) storage/pbxt/src/ha_pbxt.cc (+99/-6) storage/pbxt/src/index_xt.cc (+94/-32) storage/pbxt/src/index_xt.h (+1/-1) storage/pbxt/src/myxt_xt.cc (+6/-2) storage/pbxt/src/myxt_xt.h (+6/-6) storage/pbxt/src/restart_xt.cc (+58/-0) storage/pbxt/src/strutil_xt.cc (+1/-1) storage/pbxt/src/table_xt.cc (+239/-12) storage/pbxt/src/table_xt.h (+2/-0) storage/pbxt/src/thread_xt.cc (+7/-2) storage/pbxt/src/xaction_xt.cc (+3/-1) storage/pbxt/src/xt_defs.h (+24/-2) |
To merge this branch: | bzr merge lp:~paul-mccullagh/maria/pbxt-1.0.11-7 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Maria-captains | Pending | ||
Review via email: mp+35794@code.launchpad.net |
Commit message
Description of the change
This is the latest version of the PBXT Pre-GA, version 1.0.11-7. Details of changes are in the release notes (storage/
I have updated the 2 test results as required. In this version, PBXT once again estimates the number of rows in the table correctly. This changes the output of some EXPLAIN commands.
Michael Widenius (monty) wrote : | # |
Michael Widenius (monty) wrote : | # |
Hi!
>>>>> "Paul" == Paul McCullagh <email address hidden> writes:
Paul> Paul McCullagh has proposed merging lp:~paul-mccullagh/maria/pbxt-1.0.11-7 into lp:maria.
Paul> Requested reviews:
Paul> Maria-captains (maria-captains)
Paul> This is the latest version of the PBXT Pre-GA, version 1.0.11-7. Details of changes are in the release notes (storage/
<cut>
I have now merged this into MariaDB 5.1; I changed a couple of ifdefs to
make the code work both for MariaDB 5.1 and MariaDB 5.2.
Will push shortly into 5.1. Next merge pass will take this to MariaDB
5.2 and 5.3.
Regards,
Monty
Sergei Golubchik (sergii) wrote : | # |
done as a patch. as far as I understand.
Unmerged revisions
- 2820. By Paul McCullagh
-
Added release notes
- 2819. By Paul McCullagh
-
Updated PBXT test suite results
- 2818. By Paul McCullagh
-
Merged with 1.0 trunk
Preview Diff
1 | === modified file 'mysql-test/suite/pbxt/r/negation_elimination.result' |
2 | --- mysql-test/suite/pbxt/r/negation_elimination.result 2010-06-26 10:05:41 +0000 |
3 | +++ mysql-test/suite/pbxt/r/negation_elimination.result 2010-09-17 10:32:54 +0000 |
4 | @@ -388,7 +388,7 @@ |
5 | test.t1 analyze status OK |
6 | 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)); |
7 | id select_type table type possible_keys key key_len ref rows filtered Extra |
8 | -1 SIMPLE t1 index NULL a 5 NULL 21 100.00 Using where; Using index |
9 | +1 SIMPLE t1 index NULL a 5 NULL 5 100.00 Using where; Using index |
10 | Warnings: |
11 | 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` |
12 | drop table t1; |
13 | |
14 | === modified file 'mysql-test/suite/pbxt/r/select.result' |
15 | --- mysql-test/suite/pbxt/r/select.result 2010-06-26 19:33:16 +0000 |
16 | +++ mysql-test/suite/pbxt/r/select.result 2010-09-17 10:32:54 +0000 |
17 | @@ -1384,52 +1384,52 @@ |
18 | test.t2 analyze status OK |
19 | explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; |
20 | id select_type table type possible_keys key key_len ref rows Extra |
21 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
22 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
23 | 1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 |
24 | explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; |
25 | id select_type table type possible_keys key key_len ref rows Extra |
26 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
27 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
28 | 1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 |
29 | explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; |
30 | id select_type table type possible_keys key key_len ref rows Extra |
31 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
32 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
33 | 1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 |
34 | explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; |
35 | id select_type table type possible_keys key key_len ref rows Extra |
36 | 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where |
37 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
38 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
39 | explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0; |
40 | id select_type table type possible_keys key key_len ref rows Extra |
41 | 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where |
42 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
43 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
44 | explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0; |
45 | id select_type table type possible_keys key key_len ref rows Extra |
46 | 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where |
47 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
48 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
49 | explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; |
50 | id select_type table type possible_keys key key_len ref rows Extra |
51 | 1 SIMPLE t4 ALL NULL NULL NULL NULL 12 |
52 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
53 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
54 | explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; |
55 | id select_type table type possible_keys key key_len ref rows Extra |
56 | 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 |
57 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
58 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
59 | explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; |
60 | id select_type table type possible_keys key key_len ref rows Extra |
61 | 1 SIMPLE t4 ALL NULL NULL NULL NULL 12 |
62 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
63 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
64 | explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; |
65 | id select_type table type possible_keys key key_len ref rows Extra |
66 | 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where |
67 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
68 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
69 | explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0; |
70 | id select_type table type possible_keys key key_len ref rows Extra |
71 | 1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where |
72 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
73 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
74 | explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0; |
75 | id select_type table type possible_keys key key_len ref rows Extra |
76 | 1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where |
77 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where |
78 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where |
79 | select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; |
80 | companynr companynr |
81 | 37 36 |
82 | @@ -1437,7 +1437,7 @@ |
83 | explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; |
84 | id select_type table type possible_keys key key_len ref rows Extra |
85 | 1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary |
86 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Using join buffer |
87 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer |
88 | 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; |
89 | fld1 companynr fld3 period |
90 | 038008 37 reporters 1008 |
91 | @@ -1511,7 +1511,7 @@ |
92 | 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 |
93 | explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; |
94 | id select_type table type possible_keys key key_len ref rows filtered Extra |
95 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 100.00 Using where |
96 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 100.00 Using where |
97 | Warnings: |
98 | 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` <> '')) |
99 | select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3; |
100 | @@ -1955,7 +1955,7 @@ |
101 | 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE |
102 | explain select fld3 from t2 where fld1=fld1; |
103 | id select_type table type possible_keys key key_len ref rows Extra |
104 | -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 |
105 | +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 |
106 | select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502; |
107 | companynr fld1 |
108 | 34 250501 |
109 | @@ -2007,7 +2007,7 @@ |
110 | 4181 |
111 | explain select min(fld1),max(fld1),count(*) from t2; |
112 | id select_type table type possible_keys key key_len ref rows Extra |
113 | -1 SIMPLE t2 index NULL fld1 4 NULL 1200 Using index |
114 | +1 SIMPLE t2 index NULL fld1 4 NULL 1199 Using index |
115 | select min(fld1),max(fld1),count(*) from t2; |
116 | min(fld1) max(fld1) count(*) |
117 | 0 1232609 1199 |
118 | @@ -2093,9 +2093,9 @@ |
119 | Field Type Collation Null Key Default Extra Privileges Comment |
120 | show keys from t2; |
121 | Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment |
122 | -t2 0 PRIMARY 1 auto A 1200 NULL NULL BTREE |
123 | -t2 0 fld1 1 fld1 A 1200 NULL NULL BTREE |
124 | -t2 1 fld3 1 fld3 A 1200 NULL NULL BTREE |
125 | +t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE |
126 | +t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE |
127 | +t2 1 fld3 1 fld3 A 1199 NULL NULL BTREE |
128 | drop table t4, t3, t2, t1; |
129 | DO 1; |
130 | DO benchmark(100,1+1),1,1; |
131 | |
132 | === modified file 'storage/pbxt/ChangeLog' |
133 | --- storage/pbxt/ChangeLog 2010-05-06 16:33:54 +0000 |
134 | +++ storage/pbxt/ChangeLog 2010-09-17 10:32:54 +0000 |
135 | @@ -1,7 +1,49 @@ |
136 | PBXT Release Notes |
137 | ================== |
138 | |
139 | -+------- 1.0.11 Pre-GA - 2010-05-11 |
140 | +------- 1.0.11-7 Pre-GA - 2010-09-09 |
141 | + |
142 | +RN336: Compiled and tested with MySQL 5.1.50. |
143 | + |
144 | +RN335: Fixed bug #523994: Deleting all records does not update table statistics. |
145 | + |
146 | +RN334: Made a change to reduce the time that only temporary tables exist during the ALTER TABLE and REPAIR TABLE statements. This increases the chance of recovery if a crash occurs during these operations. |
147 | + |
148 | +RN333: Log name of table when PBXT recovers an index on startup. If an error occurs during index recovery, the index is set to "repair pending". |
149 | + |
150 | +RN332: Fixed an inifinite loop when a record in a row is corrupt. Added logging and set the table to "repair pending" in this case. |
151 | + |
152 | +RN331: Fixed bug #626890: Crash on truncate table operation. |
153 | + |
154 | +RN330: Added additional checks for corruption of the index free list. |
155 | + |
156 | +------- 1.0.11-6 Pre-GA - 2010-07-08 |
157 | + |
158 | +RN329: Fixed bug #601245: make fails. PBXT did not compile if the partition engine was disabled in the MySQL build. |
159 | + |
160 | +------- 1.0.11-5 Pre-GA - 2010-06-18 |
161 | + |
162 | +RN328: Fixed bug #595478: Compile fails (1.0.11-4). |
163 | + |
164 | +------- 1.0.11-4 Pre-GA - 2010-06-15 |
165 | + |
166 | +RN327: Fixed a bug that caused a crash during delete on the index. The crash occurred due to memory overwrite when a long key is promoted after a shorter key is deleted, and the difference causes a node size overflow. |
167 | + |
168 | +------- 1.0.11-3 Pre-GA - 2010-06-11 |
169 | + |
170 | +RN326: Fixed bug #587740: pbxt-1.0.11-pre2-ga first time create partition table error. This was not a new bug. The problem was the PBXT system table's .frm files are corrupted when the first PBXT table created is a partition table. |
171 | + |
172 | +RN325: Fixed the "to-sweep" column output in xtstat. |
173 | + |
174 | +------- 1.0.11-2 Pre-GA - 2010-05-26 |
175 | + |
176 | +RN324: Fixed bug #584070:pbxt-1.0.11-pre-ga does not work with mysql 5.1.47. This bug fix removes a hack which was done to avoid running into the LOCK_plugin lock. |
177 | + |
178 | +------- 1.0.11-1 Pre-GA - 2010-05-19 |
179 | + |
180 | +RN323: Detect corruption of a key length in an index page. This bug fix avoids a possible crash due to index page corruption. |
181 | + |
182 | +------- 1.0.11 Pre-GA - 2010-05-11 |
183 | |
184 | 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. |
185 | |
186 | |
187 | === modified file 'storage/pbxt/src/cache_xt.cc' |
188 | --- storage/pbxt/src/cache_xt.cc 2010-05-05 10:59:57 +0000 |
189 | +++ storage/pbxt/src/cache_xt.cc 2010-09-17 10:32:54 +0000 |
190 | @@ -668,6 +668,9 @@ |
191 | block->cb_data = buffer; |
192 | buffer += XT_INDEX_PAGE_SIZE; |
193 | #endif |
194 | +#ifdef CHECK_BLOCK_TRAILERS |
195 | + XT_SET_DISK_4(block->cp_check, 0xDEADBEEF); |
196 | +#endif |
197 | ind_cac_globals.cg_free_list = block; |
198 | block++; |
199 | } |
200 | @@ -684,6 +687,19 @@ |
201 | cont_(a); |
202 | } |
203 | |
204 | +#ifdef CHECK_BLOCK_TRAILERS |
205 | +xtPublic void check_block_trailers() |
206 | +{ |
207 | + XTIndBlockPtr block; |
208 | + |
209 | + block = ind_cac_globals.cg_blocks; |
210 | + for (u_int i=0; i<ind_cac_globals.cg_block_count; i++) { |
211 | + ASSERT_NS(XT_GET_DISK_4(block->cp_check) == 0xDEADBEEF); |
212 | + block++; |
213 | + } |
214 | +} |
215 | +#endif |
216 | + |
217 | xtPublic void xt_ind_exit(XTThreadPtr self) |
218 | { |
219 | #ifdef XT_USE_MYSYS |
220 | @@ -1283,7 +1299,7 @@ |
221 | * Conditionally count the number of deleted entries in the index: |
222 | * We do this before other threads can read the block. |
223 | */ |
224 | - if (ind->mi_lazy_delete && read_data) |
225 | + if (ind && ind->mi_lazy_delete && read_data) |
226 | xt_ind_count_deleted_items(ot->ot_table, ind, block); |
227 | |
228 | /* Add to the hash table: */ |
229 | @@ -1358,6 +1374,9 @@ |
230 | #ifdef XT_TRACK_INDEX_UPDATES |
231 | ot->ot_ind_changed++; |
232 | #endif |
233 | +#ifdef CHECK_BLOCK_TRAILERS |
234 | + check_block_trailers(); |
235 | +#endif |
236 | return OK; |
237 | } |
238 | |
239 | |
240 | === modified file 'storage/pbxt/src/cache_xt.h' |
241 | --- storage/pbxt/src/cache_xt.h 2010-05-05 10:59:57 +0000 |
242 | +++ storage/pbxt/src/cache_xt.h 2010-09-17 10:32:54 +0000 |
243 | @@ -33,6 +33,7 @@ |
244 | |
245 | #ifdef DEBUG |
246 | //#define XT_USE_CACHE_DEBUG_SIZES |
247 | +//#define CHECK_BLOCK_TRAILERS |
248 | #endif |
249 | |
250 | #ifdef XT_USE_CACHE_DEBUG_SIZES |
251 | @@ -116,6 +117,9 @@ |
252 | #else |
253 | xtWord1 cb_data[XT_INDEX_PAGE_SIZE]; |
254 | #endif |
255 | +#ifdef CHECK_BLOCK_TRAILERS |
256 | + xtWord1 cp_check[4]; |
257 | +#endif |
258 | } XTIndBlockRec, *XTIndBlockPtr; |
259 | |
260 | typedef struct XTIndReference { |
261 | @@ -177,6 +181,10 @@ |
262 | XTIndHandlePtr xt_ind_get_handle(struct XTOpenTable *ot, XTIndexPtr ind, XTIndReferencePtr iref); |
263 | void xt_ind_release_handle(XTIndHandlePtr handle, xtBool have_lock, XTThreadPtr thread); |
264 | |
265 | +#ifdef CHECK_BLOCK_TRAILERS |
266 | +extern void check_block_trailers(); |
267 | +#endif |
268 | + |
269 | #ifdef DEBUG |
270 | //#define DEBUG_CHECK_IND_CACHE |
271 | #endif |
272 | |
273 | === modified file 'storage/pbxt/src/database_xt.h' |
274 | --- storage/pbxt/src/database_xt.h 2010-05-05 10:59:57 +0000 |
275 | +++ storage/pbxt/src/database_xt.h 2010-09-17 10:32:54 +0000 |
276 | @@ -117,6 +117,7 @@ |
277 | XTSortedListPtr db_table_by_id; |
278 | XTSortedListPtr db_table_paths; /* A list of table paths used by this database. */ |
279 | xtBool db_multi_path; |
280 | + XTSortedListPtr db_error_list; /* A list of errors already reported. */ |
281 | |
282 | /* The open table pool: */ |
283 | XTAllTablePoolsRec db_ot_pool; |
284 | |
285 | === modified file 'storage/pbxt/src/datadic_xt.cc' |
286 | --- storage/pbxt/src/datadic_xt.cc 2010-06-01 19:52:20 +0000 |
287 | +++ storage/pbxt/src/datadic_xt.cc 2010-09-17 10:32:54 +0000 |
288 | @@ -396,7 +396,7 @@ |
289 | struct charset_info_st; |
290 | |
291 | class XTTokenizer { |
292 | - const struct charset_info_st *tkn_charset; |
293 | + MX_CONST_CHARSET_INFO *tkn_charset; |
294 | char *tkn_cstring; |
295 | char *tkn_curr_pos; |
296 | XTToken *tkn_current; |
297 | @@ -1324,7 +1324,7 @@ |
298 | class XTCreateTable : public XTParseTable { |
299 | public: |
300 | bool ct_convert; |
301 | - const struct charset_info_st *ct_charset; |
302 | + MX_CONST_CHARSET_INFO *ct_charset; |
303 | XTPathStrPtr ct_tab_path; |
304 | u_int ct_contraint_no; |
305 | XTDDTable *ct_curr_table; |
306 | @@ -2039,11 +2039,6 @@ |
307 | if (!(ot = xt_db_open_table_using_tab(tr_fkey->co_table->dt_table, self))) |
308 | xt_throw(self); |
309 | |
310 | - /* {FREE-ROWS-BAD} */ |
311 | - /* |
312 | - row_count = ((xtInt8) ot->ot_table->tab_row_eof_id) - 1; |
313 | - row_count -= (xtInt8) ot->ot_table->tab_row_fnum; |
314 | - */ |
315 | /* Check if there are any rows in the referencing table: */ |
316 | if (!xt_tab_seq_init(ot)) |
317 | goto failed; |
318 | |
319 | === modified file 'storage/pbxt/src/datalog_xt.cc' |
320 | --- storage/pbxt/src/datalog_xt.cc 2010-05-14 11:56:14 +0000 |
321 | +++ storage/pbxt/src/datalog_xt.cc 2010-09-17 10:32:54 +0000 |
322 | @@ -1249,7 +1249,7 @@ |
323 | */ |
324 | dlb_data_log->dlf_log_eof += size; |
325 | #ifdef DEBUG |
326 | - if ((ulonglong) (log_offset + size) > (ulonglong) dlb_max_write_offset) |
327 | + if (log_offset + (xtLogOffset) size > (xtLogOffset) dlb_max_write_offset) |
328 | dlb_max_write_offset = log_offset + size; |
329 | #endif |
330 | dlb_flush_required = TRUE; |
331 | @@ -1291,7 +1291,7 @@ |
332 | if (!xt_pwrite_file(dlb_data_log->dlf_log_file, log_offset, size, data, &thread->st_statistics.st_data, thread)) |
333 | return FAILED; |
334 | #ifdef DEBUG |
335 | - if ((ulonglong) (log_offset + size) > (ulonglong) dlb_max_write_offset) |
336 | + if (log_offset + (xtLogOffset) size > (xtLogOffset) dlb_max_write_offset) |
337 | dlb_max_write_offset = log_offset + size; |
338 | #endif |
339 | dlb_flush_required = TRUE; |
340 | @@ -1734,8 +1734,8 @@ |
341 | xtLogOffset src_log_offset; |
342 | xtLogID curr_log_id; |
343 | xtLogOffset curr_log_offset; |
344 | - xtLogID dest_log_id= 0; |
345 | - xtLogOffset dest_log_offset= 0; |
346 | + xtLogID dest_log_id = 0; |
347 | + xtLogOffset dest_log_offset = 0; |
348 | off_t garbage_count = 0; |
349 | |
350 | memset(&cs, 0, sizeof(XTCompactorStateRec)); |
351 | |
352 | === modified file 'storage/pbxt/src/discover_xt.cc' |
353 | --- storage/pbxt/src/discover_xt.cc 2010-04-08 12:10:05 +0000 |
354 | +++ storage/pbxt/src/discover_xt.cc 2010-09-17 10:32:54 +0000 |
355 | @@ -1622,8 +1622,11 @@ |
356 | COLUMN_FORMAT_TYPE_FIXED, |
357 | #endif |
358 | NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/, |
359 | - NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/, |
360 | - NULL /*vcol_info*/, NULL /* create options */)) |
361 | + NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/ |
362 | +#ifdef MARIADB_BASE_VERSION |
363 | + , NULL /*vcol_info*/, NULL /* create options */ |
364 | +#endif |
365 | + )) |
366 | #endif |
367 | goto error; |
368 | |
369 | @@ -1655,8 +1658,17 @@ |
370 | if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0)) |
371 | goto error; |
372 | #else |
373 | +#ifdef WITH_PARTITION_STORAGE_ENGINE |
374 | + partition_info *part_info; |
375 | + |
376 | + part_info = thd->work_part_info; |
377 | + thd->work_part_info = NULL; |
378 | +#endif |
379 | if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0)) |
380 | goto error; |
381 | +#ifdef WITH_PARTITION_STORAGE_ENGINE |
382 | + thd->work_part_info = part_info; |
383 | +#endif |
384 | #endif |
385 | |
386 | noerror: |
387 | |
388 | === modified file 'storage/pbxt/src/ha_pbxt.cc' |
389 | --- storage/pbxt/src/ha_pbxt.cc 2010-06-01 19:52:20 +0000 |
390 | +++ storage/pbxt/src/ha_pbxt.cc 2010-09-17 10:32:54 +0000 |
391 | @@ -1232,6 +1232,11 @@ |
392 | THD *thd = NULL; |
393 | |
394 | #ifndef DRIZZLED |
395 | +#if MYSQL_VERSION_ID < 50147 |
396 | + /* A hack which is no longer required after 5.1.46 */ |
397 | + extern myxt_mutex_t LOCK_plugin; |
398 | +#endif |
399 | + |
400 | /* {MYSQL QUIRK} |
401 | * I have to release this lock for PBXT recovery to |
402 | * work, because it needs to open .frm files. |
403 | @@ -1248,6 +1253,9 @@ |
404 | * Only real problem, 2 threads try to load the same |
405 | * plugin at the same time. |
406 | */ |
407 | +#if MYSQL_VERSION_ID < 50147 |
408 | + myxt_mutex_unlock(&LOCK_plugin); |
409 | +#endif |
410 | #endif |
411 | |
412 | /* Can't do this here yet, because I need a THD! */ |
413 | @@ -1281,6 +1289,11 @@ |
414 | |
415 | if (thd) |
416 | myxt_destroy_thread(thd, FALSE); |
417 | +#ifndef DRIZZLED |
418 | +#if MYSQL_VERSION_ID < 50147 |
419 | + myxt_mutex_lock(&LOCK_plugin); |
420 | +#endif |
421 | +#endif |
422 | } |
423 | #endif |
424 | } |
425 | @@ -1941,8 +1954,13 @@ |
426 | * selectity of the indices, as soon as the number of rows |
427 | * exceeds 200 (see [**]) |
428 | */ |
429 | +#ifdef XT_ROW_COUNT_CORRECTED |
430 | + /* {CORRECTED-ROW-COUNT} */ |
431 | + pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150; |
432 | +#else |
433 | /* {FREE-ROWS-BAD} */ |
434 | pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150; |
435 | +#endif |
436 | } |
437 | |
438 | /* I am not doing this anymore because it was only required |
439 | @@ -2289,6 +2307,36 @@ |
440 | */ |
441 | if (!thd || thd_sql_command(thd) == SQLCOM_FLUSH) // FLUSH TABLES |
442 | xt_sync_flush_table(self, ot); |
443 | + else { |
444 | + /* This change is a result of a problem mentioned by Arjen. |
445 | + * REPAIR and ALTER lead to the following sequence: |
446 | + * 1. tab -- copy --> tmp1 |
447 | + * 2. tab -- rename --> tmp2 |
448 | + * 3. tmp1 -- rename --> tab |
449 | + * 4. delete tmp2 |
450 | + * |
451 | + * PBXT flushes a table before rename. |
452 | + * In the sequence above results in a table flush in step 3 which can |
453 | + * take a very long time. |
454 | + * |
455 | + * The problem is, during this time frame we have only temp tables. |
456 | + * A crash in this state leaves the database in a bad state. |
457 | + * |
458 | + * To reduce the time in this state, the flush needs to be done |
459 | + * elsewhere. The code below causes the flish to occur after |
460 | + * step 1: |
461 | + */ |
462 | + switch (thd_sql_command(thd)) { |
463 | + case SQLCOM_REPAIR: |
464 | + case SQLCOM_RENAME_TABLE: |
465 | + case SQLCOM_OPTIMIZE: |
466 | + case SQLCOM_ANALYZE: |
467 | + case SQLCOM_ALTER_TABLE: |
468 | + case SQLCOM_CREATE_INDEX: |
469 | + xt_sync_flush_table(self, ot); |
470 | + break; |
471 | + } |
472 | + } |
473 | } |
474 | freer_(); // xt_db_return_table_to_pool(ot); |
475 | } |
476 | @@ -2349,9 +2397,15 @@ |
477 | #else |
478 | xt_tab_load_row_pointers(self, pb_open_tab); |
479 | #endif |
480 | + |
481 | xt_ind_set_index_selectivity(pb_open_tab, self); |
482 | +#ifdef XT_ROW_COUNT_CORRECTED |
483 | + /* {CORRECTED-ROW-COUNT} */ |
484 | + pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150; |
485 | +#else |
486 | /* {FREE-ROWS-BAD} */ |
487 | pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150; |
488 | +#endif |
489 | } |
490 | |
491 | init_auto_increment(0); |
492 | @@ -3922,6 +3976,8 @@ |
493 | |
494 | if ((ot = pb_open_tab)) { |
495 | if (flag & HA_STATUS_VARIABLE) { |
496 | + register XTTableHPtr tab = ot->ot_table; |
497 | + |
498 | /* {FREE-ROWS-BAD} |
499 | * Free row count is not reliable, so ignore it. |
500 | * The problem is if tab_row_fnum > tab_row_eof_id - 1 then |
501 | @@ -3948,11 +4004,26 @@ |
502 | * the actual number of vectors. But it must assume that it has at |
503 | * least EXTRA_RECORDS vectors. |
504 | */ |
505 | - stats.deleted = /* ot->ot_table->tab_row_fnum */ 0; |
506 | - stats.records = (ha_rows) (ot->ot_table->tab_row_eof_id - 1 /* - stats.deleted */); |
507 | - stats.data_file_length = xt_rec_id_to_rec_offset(ot->ot_table, ot->ot_table->tab_rec_eof_id); |
508 | - stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof); |
509 | - stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size; |
510 | +#ifdef XT_ROW_COUNT_CORRECTED |
511 | + if (tab->tab_row_eof_id <= tab->tab_row_fnum || |
512 | + (!tab->tab_row_free_id && tab->tab_row_fnum)) |
513 | + xt_tab_check_free_lists(NULL, ot, false, true); |
514 | + stats.records = (ha_rows) tab->tab_row_eof_id - 1; |
515 | + if (stats.records >= tab->tab_row_fnum) { |
516 | + stats.deleted = tab->tab_row_fnum; |
517 | + stats.records -= stats.deleted; |
518 | + } |
519 | + else { |
520 | + stats.deleted = 0; |
521 | + stats.records = 2; |
522 | + } |
523 | +#else |
524 | + stats.deleted = /* tab->tab_row_fnum */ 0; |
525 | + stats.records = (ha_rows) (tab->tab_row_eof_id - 1 /* - stats.deleted */); |
526 | +#endif |
527 | + stats.data_file_length = xt_rec_id_to_rec_offset(tab, tab->tab_rec_eof_id); |
528 | + stats.index_file_length = xt_ind_node_to_offset(tab, tab->tab_ind_eof); |
529 | + stats.delete_length = tab->tab_rec_fnum * ot->ot_rec_size; |
530 | //check_time = info.check_time; |
531 | stats.mean_rec_length = (ulong) ot->ot_rec_size; |
532 | } |
533 | @@ -4577,13 +4648,24 @@ |
534 | } |
535 | |
536 | if (pb_share->sh_recalc_selectivity) { |
537 | +#ifdef XT_ROW_COUNT_CORRECTED |
538 | + /* {CORRECTED-ROW-COUNT} */ |
539 | + if ((pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) >= 200) |
540 | +#else |
541 | /* {FREE-ROWS-BAD} */ |
542 | - if ((pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) >= 200) { |
543 | + if ((pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) >= 200) |
544 | +#endif |
545 | + { |
546 | /* [**] */ |
547 | pb_share->sh_recalc_selectivity = FALSE; |
548 | xt_ind_set_index_selectivity(pb_open_tab, self); |
549 | +#ifdef XT_ROW_COUNT_CORRECTED |
550 | + /* {CORRECTED-ROW-COUNT} */ |
551 | + pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 - pb_share->sh_table->tab_row_fnum) < 150; |
552 | +#else |
553 | /* {FREE-ROWS-BAD} */ |
554 | pb_share->sh_recalc_selectivity = (pb_share->sh_table->tab_row_eof_id - 1 /* - pb_share->sh_table->tab_row_fnum */) < 150; |
555 | +#endif |
556 | } |
557 | } |
558 | } |
559 | @@ -4631,6 +4713,17 @@ |
560 | goto complete; |
561 | } |
562 | cont_(a); |
563 | + |
564 | + /* Occurs if you do: |
565 | + * truncate table t1; |
566 | + * truncate table t1; |
567 | + */ |
568 | + if (!pb_open_tab) { |
569 | + if ((err = reopen())) { |
570 | + pb_ex_in_use = 0; |
571 | + goto complete; |
572 | + } |
573 | + } |
574 | } |
575 | else { |
576 | pb_ex_in_use = 1; |
577 | |
578 | === modified file 'storage/pbxt/src/index_xt.cc' |
579 | --- storage/pbxt/src/index_xt.cc 2010-05-05 10:59:57 +0000 |
580 | +++ storage/pbxt/src/index_xt.cc 2010-09-17 10:32:54 +0000 |
581 | @@ -272,10 +272,17 @@ |
582 | } |
583 | |
584 | if ((XT_NODE_ID(wrote_pos) = XT_NODE_ID(tab->tab_ind_free))) { |
585 | + xtIndexNodeID next_node; |
586 | + |
587 | /* Use the block on the free list: */ |
588 | - if (!xt_ind_read_bytes(ot, ind, wrote_pos, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) |
589 | - goto failed; |
590 | - XT_NODE_ID(tab->tab_ind_free) = (xtIndexNodeID) XT_GET_DISK_8(free_block.if_next_block_8); |
591 | + if (!xt_ind_read_bytes(ot, NULL, wrote_pos, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) |
592 | + goto failed; |
593 | + XT_NODE_ID(next_node) = (xtIndexNodeID) XT_GET_DISK_8(free_block.if_next_block_8); |
594 | + if (XT_NODE_ID(next_node) >= XT_NODE_ID(tab->tab_ind_eof)) { |
595 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, tab->tab_name); |
596 | + goto failed; |
597 | + } |
598 | + XT_NODE_ID(tab->tab_ind_free) = XT_NODE_ID(next_node); |
599 | xt_unlock_mutex_ns(&tab->tab_ind_lock); |
600 | *address = wrote_pos; |
601 | TRACK_BLOCK_ALLOC(wrote_pos); |
602 | @@ -1415,30 +1422,45 @@ |
603 | if (idx_is_item_deleted(iref.ir_branch, &item->i_pos)) |
604 | iref.ir_block->cp_del_count--; |
605 | } |
606 | - memmove(&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item_size], |
607 | - &iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size], |
608 | - item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size); |
609 | - memcpy(&iref.ir_branch->tb_data[item->i_pos.i_item_offset], |
610 | - item_buf, item_size); |
611 | - if (ind->mi_lazy_delete) { |
612 | - if (idx_is_item_deleted(iref.ir_branch, &item->i_pos)) |
613 | - iref.ir_block->cp_del_count++; |
614 | - } |
615 | - item->i_pos.i_total_size = item->i_pos.i_total_size + item_size - item->i_pos.i_item_size; |
616 | - XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(item->i_pos.i_total_size)); |
617 | - IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2)); |
618 | - iref.ir_updated = TRUE; |
619 | + |
620 | + if (item->i_pos.i_total_size + item_size - item->i_pos.i_item_size <= XT_INDEX_PAGE_DATA_SIZE) { |
621 | + /* The new item is larger than the old, this can result |
622 | + * in overflow of the node! |
623 | + */ |
624 | + memmove(&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item_size], |
625 | + &iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size], |
626 | + item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size); |
627 | + memcpy(&iref.ir_branch->tb_data[item->i_pos.i_item_offset], |
628 | + item_buf, item_size); |
629 | + if (ind->mi_lazy_delete) { |
630 | + if (idx_is_item_deleted(iref.ir_branch, &item->i_pos)) |
631 | + iref.ir_block->cp_del_count++; |
632 | + } |
633 | + item->i_pos.i_total_size = item->i_pos.i_total_size + item_size - item->i_pos.i_item_size; |
634 | + XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(item->i_pos.i_total_size)); |
635 | + IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2)); |
636 | + iref.ir_updated = TRUE; |
637 | |
638 | #ifdef DEBUG |
639 | - if (ind->mi_lazy_delete) |
640 | ASSERT_NS(item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE); |
641 | #endif |
642 | - if (item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE) |
643 | return xt_ind_release(ot, ind, XT_UNLOCK_W_UPDATE, &iref); |
644 | + } |
645 | |
646 | /* The node has overflowed!! */ |
647 | result.sr_item = item->i_pos; |
648 | |
649 | + memcpy(ot->ot_ind_wbuf.tb_data, iref.ir_branch->tb_data, item->i_pos.i_item_offset); // First part of the buffer |
650 | + memcpy(&ot->ot_ind_wbuf.tb_data[item->i_pos.i_item_offset], item_buf, item_size); // The new item |
651 | + memcpy(&ot->ot_ind_wbuf.tb_data[item->i_pos.i_item_offset + item_size], |
652 | + &iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size], |
653 | + item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size); |
654 | + item->i_pos.i_total_size += item_size - item->i_pos.i_item_size; |
655 | + item->i_pos.i_item_size = item_size; |
656 | + XT_SET_DISK_2(ot->ot_ind_wbuf.tb_size_2, XT_MAKE_LEAF_SIZE(item->i_pos.i_total_size)); |
657 | + IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2)); |
658 | + ASSERT_NS(item->i_pos.i_total_size > XT_INDEX_PAGE_DATA_SIZE && item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE*2); |
659 | + |
660 | /* Adjust the stack (we want the parents of the delete node): */ |
661 | for (;;) { |
662 | if (idx_pop(stack) == item) |
663 | @@ -1448,7 +1470,7 @@ |
664 | /* We assume that value can be overwritten (which is the case) */ |
665 | key_value.sv_flags = XT_SEARCH_WHOLE_KEY; |
666 | key_value.sv_key = key_buf; |
667 | - if (!idx_get_middle_branch_item(ot, ind, iref.ir_branch, &key_value, &result)) |
668 | + if (!idx_get_middle_branch_item(ot, ind, &ot->ot_ind_wbuf, &key_value, &result)) |
669 | goto failed_1; |
670 | |
671 | if (!idx_new_branch(ot, ind, &new_branch)) |
672 | @@ -1456,7 +1478,6 @@ |
673 | |
674 | /* Split the node: */ |
675 | new_size = result.sr_item.i_total_size - result.sr_item.i_item_offset - result.sr_item.i_item_size; |
676 | - // TODO: Are 2 buffers now required? |
677 | new_branch_ptr = (XTIdxBranchDPtr) &ot->ot_ind_wbuf.tb_data[XT_INDEX_PAGE_DATA_SIZE]; |
678 | memmove(new_branch_ptr->tb_data, &iref.ir_branch->tb_data[result.sr_item.i_item_offset + result.sr_item.i_item_size], new_size); |
679 | |
680 | @@ -1466,10 +1487,10 @@ |
681 | goto failed_2; |
682 | |
683 | /* Change the size of the old branch: */ |
684 | - XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(result.sr_item.i_item_offset)); |
685 | - IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2)); |
686 | + XT_SET_DISK_2(ot->ot_ind_wbuf.tb_size_2, XT_MAKE_NODE_SIZE(result.sr_item.i_item_offset)); |
687 | + IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2)); |
688 | + memcpy(iref.ir_branch, &ot->ot_ind_wbuf, offsetof(XTIdxBranchDRec, tb_data) + result.sr_item.i_item_offset); |
689 | iref.ir_updated = TRUE; |
690 | - |
691 | xt_ind_release(ot, ind, XT_UNLOCK_W_UPDATE, &iref); |
692 | |
693 | /* Insert the new branch into the parent node, using the new middle key value: */ |
694 | @@ -2071,6 +2092,11 @@ |
695 | if (!idx_new_branch(ot, ind, &new_branch)) |
696 | goto failed_1; |
697 | |
698 | + if (XT_NODE_ID(current) == XT_NODE_ID(new_branch)) { |
699 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
700 | + goto failed_1; |
701 | + } |
702 | + |
703 | /* Copy and write the rest of the data to the new node: */ |
704 | new_size = result.sr_item.i_total_size - result.sr_item.i_item_offset - result.sr_item.i_item_size; |
705 | new_branch_ptr = (XTIdxBranchDPtr) &ot->ot_ind_wbuf.tb_data[XT_INDEX_PAGE_DATA_SIZE]; |
706 | @@ -2723,6 +2749,10 @@ |
707 | #endif |
708 | ASSERT_NS(iref.ir_xlock == 2); |
709 | ASSERT_NS(iref.ir_updated == 2); |
710 | + if (ind->mi_key_corrupted) { |
711 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
712 | + return FAILED; |
713 | + } |
714 | return OK; |
715 | |
716 | failed: |
717 | @@ -2874,6 +2904,10 @@ |
718 | //idx_check_index(ot, ind, TRUE); |
719 | //idx_check_on_key(ot); |
720 | #endif |
721 | + if (ind->mi_key_corrupted) { |
722 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
723 | + return FAILED; |
724 | + } |
725 | return OK; |
726 | |
727 | failed: |
728 | @@ -2964,6 +2998,10 @@ |
729 | |
730 | if (!(XT_NODE_ID(current) = XT_NODE_ID(ind->mi_root))) { |
731 | XT_INDEX_UNLOCK(ind, ot); |
732 | + if (ind->mi_key_corrupted) { |
733 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
734 | + return FAILED; |
735 | + } |
736 | return OK; |
737 | } |
738 | |
739 | @@ -3071,6 +3109,10 @@ |
740 | ot->ot_curr_rec_id = 0; |
741 | ot->ot_curr_row_id = 0; |
742 | XT_INDEX_UNLOCK(ind, ot); |
743 | + if (ind->mi_key_corrupted) { |
744 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
745 | + return FAILED; |
746 | + } |
747 | return OK; |
748 | } |
749 | |
750 | @@ -3112,6 +3154,10 @@ |
751 | ot->ot_curr_row_id = result.sr_row_id; |
752 | ot->ot_ind_state = result.sr_item; |
753 | |
754 | + if (ind->mi_key_corrupted) { |
755 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
756 | + return FAILED; |
757 | + } |
758 | return OK; |
759 | |
760 | failed: |
761 | @@ -3178,6 +3224,10 @@ |
762 | |
763 | if (!(XT_NODE_ID(current) = XT_NODE_ID(ind->mi_root))) { |
764 | XT_INDEX_UNLOCK(ind, ot); |
765 | + if (ind->mi_key_corrupted) { |
766 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
767 | + return FAILED; |
768 | + } |
769 | return OK; |
770 | } |
771 | |
772 | @@ -3274,6 +3324,10 @@ |
773 | ot->ot_curr_row_id = 0; |
774 | |
775 | XT_INDEX_UNLOCK(ind, ot); |
776 | + if (ind->mi_key_corrupted) { |
777 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
778 | + return FAILED; |
779 | + } |
780 | return OK; |
781 | |
782 | unlock_check_on_key: |
783 | @@ -3302,6 +3356,10 @@ |
784 | ot->ot_curr_rec_id = result.sr_rec_id; |
785 | ot->ot_curr_row_id = result.sr_row_id; |
786 | ot->ot_ind_state = result.sr_item; |
787 | + if (ind->mi_key_corrupted) { |
788 | + xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name); |
789 | + return FAILED; |
790 | + } |
791 | return OK; |
792 | |
793 | failed: |
794 | @@ -3648,7 +3706,7 @@ |
795 | track_block_exists(current); |
796 | #endif |
797 | printf("%d ", (int) XT_NODE_ID(current)); |
798 | - if (!xt_ind_read_bytes(ot, *ind, current, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) { |
799 | + if (!xt_ind_read_bytes(ot, NULL, current, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) { |
800 | xt_log_and_clear_exception_ns(); |
801 | break; |
802 | } |
803 | @@ -4141,11 +4199,18 @@ |
804 | if (!ilp_open_log(&il, log_id, FALSE, self)) |
805 | goto failed; |
806 | if (il->il_tab_id && il->il_log_eof) { |
807 | + char table_name[XT_IDENTIFIER_NAME_SIZE*3+3]; |
808 | + |
809 | if (!il->il_open_table(&ot)) |
810 | goto failed; |
811 | if (ot) { |
812 | - if (!il->il_apply_log(ot)) |
813 | - goto failed; |
814 | + xt_tab_make_table_name(ot->ot_table, table_name, sizeof(table_name)); |
815 | + xt_logf(XT_NT_INFO, "PBXT: Recovering index, table: %s, bytes to read: %llu\n", table_name, (u_llong) il->il_log_eof); |
816 | + if (!il->il_apply_log(ot)) { |
817 | + /* If recovery of an index fails, then it is corrupt! */ |
818 | + xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED); |
819 | + xt_log_and_clear_exception_ns(); |
820 | + } |
821 | ot->ot_thread = self; |
822 | il->il_close_table(ot); |
823 | } |
824 | @@ -4468,8 +4533,7 @@ |
825 | /* Corrupt log?! */ |
826 | if (il_buffer_len < req_size) { |
827 | xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of)); |
828 | - xt_log_and_clear_exception_ns(); |
829 | - return OK; |
830 | + return FAILED; |
831 | } |
832 | if (!xt_pread_file(il_of, offset, il_buffer_len, il_buffer_len, il_buffer, NULL, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread)) |
833 | return FAILED; |
834 | @@ -4548,8 +4612,7 @@ |
835 | /* Corrupt log?! */ |
836 | if (il_buffer_len < req_size) { |
837 | xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of)); |
838 | - xt_log_and_clear_exception_ns(); |
839 | - return OK; |
840 | + return FAILED; |
841 | } |
842 | if (!xt_pread_file(il_of, offset, il_buffer_len, il_buffer_len, il_buffer, NULL, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread)) |
843 | return FAILED; |
844 | @@ -4597,8 +4660,7 @@ |
845 | break; |
846 | default: |
847 | xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of)); |
848 | - xt_log_and_clear_exception_ns(); |
849 | - return OK; |
850 | + return FAILED; |
851 | } |
852 | } |
853 | |
854 | |
855 | === modified file 'storage/pbxt/src/index_xt.h' |
856 | --- storage/pbxt/src/index_xt.h 2010-05-05 10:59:57 +0000 |
857 | +++ storage/pbxt/src/index_xt.h 2010-09-17 10:32:54 +0000 |
858 | @@ -312,7 +312,7 @@ |
859 | u_int mi_flags; |
860 | u_int mi_key_size; |
861 | u_int mi_max_items; /* The maximum number of items that can fit in a leaf node. */ |
862 | - xtBool mi_low_byte_first; |
863 | + xtBool mi_key_corrupted; /* Set to TRUE if a currupted index key is detected. */ |
864 | xtBool mi_fix_key; |
865 | xtBool mi_lazy_delete; /* TRUE if index entries are "lazy deleted". */ |
866 | u_int mi_single_type; /* Used when the index contains a single field. */ |
867 | |
868 | === modified file 'storage/pbxt/src/myxt_xt.cc' |
869 | --- storage/pbxt/src/myxt_xt.cc 2010-05-12 14:27:18 +0000 |
870 | +++ storage/pbxt/src/myxt_xt.cc 2010-09-17 10:32:54 +0000 |
871 | @@ -1088,7 +1088,10 @@ |
872 | } |
873 | |
874 | end: |
875 | - return (xtWord1 *) key_data - key_buf; |
876 | + u_int ilen = (xtWord1 *) key_data - key_buf; |
877 | + if (ilen > XT_INDEX_MAX_KEY_SIZE) |
878 | + ind->mi_key_corrupted = TRUE; |
879 | + return ilen; |
880 | } |
881 | |
882 | /* Derived from ha_key_cmp */ |
883 | @@ -2183,7 +2186,8 @@ |
884 | xt_spinlock_init_with_autoname(self, &ind->mi_dirty_lock); |
885 | ind->mi_index_no = idx; |
886 | ind->mi_flags = (index->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL | HA_UNIQUE_CHECK)); |
887 | - ind->mi_low_byte_first = TS(table_arg)->db_low_byte_first; |
888 | + //ind->mi_low_byte_first = TS(table_arg)->db_low_byte_first; |
889 | + ind->mi_key_corrupted = FALSE; |
890 | ind->mi_fix_key = TRUE; |
891 | ind->mi_select_total = 0; |
892 | ind->mi_subset_of = 0; |
893 | |
894 | === modified file 'storage/pbxt/src/myxt_xt.h' |
895 | --- storage/pbxt/src/myxt_xt.h 2010-01-06 19:20:16 +0000 |
896 | +++ storage/pbxt/src/myxt_xt.h 2010-09-17 10:32:54 +0000 |
897 | @@ -69,17 +69,17 @@ |
898 | void myxt_move_dictionary(XTDictionaryPtr dic, XTDictionaryPtr source_dic); |
899 | XTDDTable *myxt_create_table_from_table(XTThreadPtr self, STRUCT_TABLE *my_tab); |
900 | |
901 | -void myxt_static_convert_identifier(XTThreadPtr self, const struct charset_info_st *cs, char *from, char *to, size_t to_len); |
902 | -char *myxt_convert_identifier(XTThreadPtr self, const struct charset_info_st *cs, char *from); |
903 | +void myxt_static_convert_identifier(XTThreadPtr self, MX_CONST_CHARSET_INFO *cs, char *from, char *to, size_t to_len); |
904 | +char *myxt_convert_identifier(XTThreadPtr self, MX_CONST_CHARSET_INFO *cs, char *from); |
905 | void myxt_static_convert_table_name(XTThreadPtr self, char *from, char *to, size_t to_len); |
906 | void myxt_static_convert_file_name(char *from, char *to, size_t to_len); |
907 | char *myxt_convert_table_name(XTThreadPtr self, char *from); |
908 | int myxt_strcasecmp(char * a, char *b); |
909 | -int myxt_isspace(const struct charset_info_st *cs, char a); |
910 | -int myxt_ispunct(const struct charset_info_st *cs, char a); |
911 | -int myxt_isdigit(const struct charset_info_st *cs, char a); |
912 | +int myxt_isspace(MX_CONST_CHARSET_INFO *cs, char a); |
913 | +int myxt_ispunct(MX_CONST_CHARSET_INFO *cs, char a); |
914 | +int myxt_isdigit(MX_CONST_CHARSET_INFO *cs, char a); |
915 | |
916 | -const struct charset_info_st *myxt_getcharset(bool convert); |
917 | +MX_CONST_CHARSET_INFO *myxt_getcharset(bool convert); |
918 | |
919 | void *myxt_create_thread(); |
920 | void myxt_destroy_thread(void *thread, xtBool end_threads); |
921 | |
922 | === modified file 'storage/pbxt/src/restart_xt.cc' |
923 | --- storage/pbxt/src/restart_xt.cc 2010-05-05 10:59:57 +0000 |
924 | +++ storage/pbxt/src/restart_xt.cc 2010-09-17 10:32:54 +0000 |
925 | @@ -1359,6 +1359,57 @@ |
926 | return op_synced; |
927 | } |
928 | |
929 | +#ifdef XT_CORRECT_TABLE_FREE_COUNT |
930 | +#define CORRECT_COUNT TRUE |
931 | +#else |
932 | +#define CORRECT_COUNT FALSE |
933 | +#endif |
934 | +#ifdef XT_CHECK_RECORD_FREE_COUNT |
935 | +#define CHECK_RECS TRUE |
936 | +#else |
937 | +#define CHECK_RECS FALSE |
938 | +#endif |
939 | +#if defined(XT_CHECK_RECORD_FREE_COUNT) || defined(XT_CHECK_ROW_FREE_COUNT) |
940 | +#define RECOVER_FREE_COUNTS |
941 | +#endif |
942 | + |
943 | +#ifdef RECOVER_FREE_COUNTS |
944 | +/* {CORRECTED-ROW-COUNT} |
945 | + * This error can be repeated by crashing the server during |
946 | + * high activitity, after flush table writes the table header |
947 | + * |
948 | + * On recovery, the free count "from the future" is used as |
949 | + * the starting point for subsequent allocation and frees. |
950 | + * The count is wrong after that point. |
951 | + * |
952 | + * The recovery of the count only works correctly if a |
953 | + * checkpoint is complete successfully after that table |
954 | + * header is flushed. Basically the writing of the table |
955 | + * header should be synchronsized with the writing of the |
956 | + * end of the checkpoint. |
957 | + * |
958 | + * Another solution would be to log the count, along with |
959 | + * the allocate and free commannds. |
960 | + * |
961 | + * The 3rd solution is the one used here. The count is corrected |
962 | + * after recovery. |
963 | + */ |
964 | +static void xres_recover_table_free_counts(XTThreadPtr self, XTDatabaseHPtr db, XTWriterStatePtr ws) |
965 | +{ |
966 | + u_int edx; |
967 | + XTTableEntryPtr te_ptr; |
968 | + XTTableHPtr tab; |
969 | + |
970 | + xt_enum_tables_init(&edx); |
971 | + while ((te_ptr = xt_enum_tables_next(self, db, &edx))) { |
972 | + if ((tab = te_ptr->te_table)) { |
973 | + if (xres_open_table(self, ws, te_ptr->te_tab_id)) |
974 | + xt_tab_check_free_lists(self, ws->ws_ot, CHECK_RECS, CORRECT_COUNT); |
975 | + } |
976 | + } |
977 | +} |
978 | +#endif |
979 | + |
980 | /* |
981 | * Operations from the log are applied in sequence order. |
982 | * If the operations are out of sequence, they are buffered |
983 | @@ -2175,6 +2226,13 @@ |
984 | /* This is true because if no transaction was placed in RAM then |
985 | * the next transaction in RAM will have the next ID: */ |
986 | db->db_xn_min_ram_id = db->db_xn_curr_id + 1; |
987 | + |
988 | +#ifdef RECOVER_FREE_COUNTS |
989 | + if (xres_cp_log_id != *log_id || xres_cp_log_offset != *log_offset) { |
990 | + /* Recovery took place, correct the row count! */ |
991 | + xres_recover_table_free_counts(self, db, &ws); |
992 | + } |
993 | +#endif |
994 | } |
995 | |
996 | failed: |
997 | |
998 | === modified file 'storage/pbxt/src/strutil_xt.cc' |
999 | --- storage/pbxt/src/strutil_xt.cc 2010-05-05 10:59:57 +0000 |
1000 | +++ storage/pbxt/src/strutil_xt.cc 2010-09-17 10:32:54 +0000 |
1001 | @@ -380,7 +380,7 @@ |
1002 | /* Version number must also be set in configure.in! */ |
1003 | xtPublic c_char *xt_get_version(void) |
1004 | { |
1005 | - return "1.0.11 Pre-GA"; |
1006 | + return "1.0.11-7 Pre-GA"; |
1007 | } |
1008 | |
1009 | /* Copy and URL decode! */ |
1010 | |
1011 | === modified file 'storage/pbxt/src/table_xt.cc' |
1012 | --- storage/pbxt/src/table_xt.cc 2010-05-14 11:56:14 +0000 |
1013 | +++ storage/pbxt/src/table_xt.cc 2010-09-17 10:32:54 +0000 |
1014 | @@ -80,6 +80,65 @@ |
1015 | |
1016 | /* |
1017 | * ----------------------------------------------------------------------- |
1018 | + * Handle Error Detected in a Table |
1019 | + */ |
1020 | + |
1021 | +struct XTTableError { |
1022 | + xtTableID ter_tab_id; |
1023 | + xtRecordID ter_rec_id; |
1024 | +}; |
1025 | + |
1026 | +static int tab_comp_tab_error(XTThreadPtr XT_UNUSED(self), register const void *XT_UNUSED(thunk), register const void *a, register const void *b) |
1027 | +{ |
1028 | + XTTableError *ter_a = ((XTTableError *) a); |
1029 | + XTTableError *ter_b = (XTTableError *) b; |
1030 | + |
1031 | + if (ter_a->ter_tab_id < ter_b->ter_tab_id) |
1032 | + return -1; |
1033 | + if (ter_a->ter_tab_id == ter_b->ter_tab_id) { |
1034 | + if (ter_a->ter_rec_id < ter_b->ter_rec_id) |
1035 | + return -1; |
1036 | + if (ter_a->ter_rec_id == ter_b->ter_rec_id) |
1037 | + return 0; |
1038 | + return 1; |
1039 | + } |
1040 | + return 1; |
1041 | +} |
1042 | + |
1043 | +static xtBool tab_record_corrupt(XTOpenTablePtr ot, xtRowID row_id, xtRecordID rec_id, bool not_valid, int where) |
1044 | +{ |
1045 | + XTTableHPtr tab = ot->ot_table; |
1046 | + XTDatabaseHPtr db = tab->tab_db; |
1047 | + XTTableError ter; |
1048 | + XTTableError *ter_ptr; |
1049 | + |
1050 | + ter.ter_tab_id = tab->tab_id; |
1051 | + ter.ter_rec_id = rec_id; |
1052 | + |
1053 | + xt_sl_lock_ns(db->db_error_list, ot->ot_thread); |
1054 | + if (!(ter_ptr = (XTTableError *) xt_sl_find(NULL, db->db_error_list, &ter))) { |
1055 | + xtBool ok; |
1056 | + char table_name[XT_IDENTIFIER_NAME_SIZE*3+3]; |
1057 | + |
1058 | + ok = xt_sl_insert(NULL, db->db_error_list, &ter, &ter); |
1059 | + xt_sl_unlock_ns(db->db_error_list); |
1060 | + if (!ok) |
1061 | + return FAILED; |
1062 | + xt_tab_set_table_repair_pending(tab); |
1063 | + xt_tab_make_table_name(tab, table_name, sizeof(table_name)); |
1064 | + xt_logf(XT_NT_ERROR, "#%d Table %s: row %llu, record %llu, is %s, REPAIR TABLE required.\n", where, |
1065 | + table_name, |
1066 | + (u_llong) row_id, |
1067 | + (u_llong) rec_id, |
1068 | + not_valid ? "not valid" : "free"); |
1069 | + } |
1070 | + else |
1071 | + xt_sl_unlock_ns(db->db_error_list); |
1072 | + return OK; |
1073 | +} |
1074 | + |
1075 | +/* |
1076 | + * ----------------------------------------------------------------------- |
1077 | * Compare paths: |
1078 | */ |
1079 | |
1080 | @@ -425,6 +484,7 @@ |
1081 | db->db_tables = xt_new_hashtable(self, tab_list_comp, tab_list_hash, tab_list_free, TRUE, TRUE); |
1082 | db->db_table_by_id = xt_new_sortedlist(self, sizeof(XTTableEntryRec), 20, 20, tab_comp_by_id, db, tab_free_by_id, FALSE, FALSE); |
1083 | db->db_table_paths = xt_new_sortedlist(self, sizeof(XTTablePathPtr), 20, 20, tab_comp_path, db, tab_free_path, FALSE, FALSE); |
1084 | + db->db_error_list = xt_new_sortedlist(self, sizeof(XTTableError), 20, 20, tab_comp_tab_error, db, NULL, TRUE, FALSE); |
1085 | |
1086 | if (db->db_multi_path) { |
1087 | XTOpenFilePtr of; |
1088 | @@ -649,6 +709,10 @@ |
1089 | xt_free_sortedlist(self, db->db_table_paths); |
1090 | db->db_table_paths = NULL; |
1091 | } |
1092 | + if (db->db_error_list) { |
1093 | + xt_free_sortedlist(self, db->db_error_list); |
1094 | + db->db_error_list = NULL; |
1095 | + } |
1096 | } |
1097 | |
1098 | static void tab_check_table(XTThreadPtr self, XTTableHPtr XT_UNUSED(tab)) |
1099 | @@ -1713,6 +1777,116 @@ |
1100 | exit_(); |
1101 | } |
1102 | |
1103 | +xtPublic void xt_tab_check_free_lists(XTThreadPtr self, XTOpenTablePtr ot, bool check_recs, bool correct_count) |
1104 | +{ |
1105 | + char table_name[XT_IDENTIFIER_NAME_SIZE*3+3]; |
1106 | + register XTTableHPtr tab = ot->ot_table; |
1107 | + xtRowID prev_row_id; |
1108 | + xtRowID row_id; |
1109 | + xtRefID next_row_id; |
1110 | + u_llong free_count; |
1111 | + |
1112 | + xt_tab_make_table_name(tab, table_name, sizeof(table_name)); |
1113 | + if (check_recs) { |
1114 | + xtRecordID prev_rec_id; |
1115 | + xtRecordID rec_id; |
1116 | + XTTabRecExtDRec rec_buf; |
1117 | + |
1118 | + xt_lock_mutex_ns(&tab->tab_rec_lock); |
1119 | + /* Checking the free list: */ |
1120 | + prev_rec_id = 0; |
1121 | + free_count = 0; |
1122 | + rec_id = tab->tab_rec_free_id; |
1123 | + while (rec_id) { |
1124 | + if (rec_id >= tab->tab_rec_eof_id) { |
1125 | + xt_logf(XT_NT_ERROR, "Table %s: invalid reference on free list: %llu, ", table_name, (u_llong) rec_id); |
1126 | + if (prev_rec_id) |
1127 | + xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_rec_id); |
1128 | + else |
1129 | + xt_logf(XT_NT_ERROR, "reference by list head pointer\n"); |
1130 | + xt_tab_set_table_repair_pending(tab); |
1131 | + break; |
1132 | + } |
1133 | + if (!xt_tab_get_rec_data(ot, rec_id, XT_REC_FIX_HEADER_SIZE, (xtWord1 *) &rec_buf)) { |
1134 | + if (self) |
1135 | + xt_throw(self); |
1136 | + else |
1137 | + xt_log_and_clear_warning(ot->ot_thread); |
1138 | + break; |
1139 | + } |
1140 | + if ((rec_buf.tr_rec_type_1 & XT_TAB_STATUS_MASK) != XT_TAB_STATUS_FREED) |
1141 | + xt_logf(XT_NT_INFO, "Table %s: record, %llu, on free list is not free\n", table_name, (u_llong) rec_id); |
1142 | + free_count++; |
1143 | + prev_rec_id = rec_id; |
1144 | + rec_id = XT_GET_DISK_4(rec_buf.tr_prev_rec_id_4); |
1145 | + } |
1146 | + if (free_count != tab->tab_rec_fnum) { |
1147 | + if (correct_count) { |
1148 | + tab->tab_rec_fnum = free_count; |
1149 | + tab->tab_head_rec_fnum = free_count; |
1150 | + tab->tab_flush_pending = TRUE; |
1151 | + xt_logf(XT_NT_INFO, "Table %s: free record count (%llu) has been set to the number of records on the list: %llu\n", table_name, (u_llong) tab->tab_rec_fnum, (u_llong) free_count); |
1152 | + } |
1153 | + else |
1154 | + xt_logf(XT_NT_INFO, "Table %s: free record count (%llu) differs from the number of records on the list: %llu\n", table_name, (u_llong) tab->tab_rec_fnum, (u_llong) free_count); |
1155 | + } |
1156 | + xt_unlock_mutex_ns(&tab->tab_rec_lock); |
1157 | + } |
1158 | + |
1159 | + /* Check the row free list: */ |
1160 | + xt_lock_mutex_ns(&tab->tab_row_lock); |
1161 | + |
1162 | + prev_row_id = 0; |
1163 | + free_count = 0; |
1164 | + row_id = tab->tab_row_free_id; |
1165 | + while (row_id) { |
1166 | + if (row_id >= tab->tab_row_eof_id) { |
1167 | + xt_logf(XT_NT_ERROR, "Table %s: invalid reference on free row: %llu, ", table_name, (u_llong) row_id); |
1168 | + if (prev_row_id) |
1169 | + xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_row_id); |
1170 | + else |
1171 | + xt_logf(XT_NT_ERROR, "reference by list head pointer\n"); |
1172 | + xt_tab_set_table_repair_pending(tab); |
1173 | + break; |
1174 | + } |
1175 | + if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, row_id, &next_row_id, ot->ot_thread)) { |
1176 | + if (self) |
1177 | + xt_throw(self); |
1178 | + else |
1179 | + xt_log_and_clear_warning(ot->ot_thread); |
1180 | + break; |
1181 | + } |
1182 | + free_count++; |
1183 | + prev_row_id = row_id; |
1184 | + row_id = next_row_id; |
1185 | + } |
1186 | + if (free_count != tab->tab_row_fnum) { |
1187 | + if (correct_count) { |
1188 | + /* tab_row_fnum is the current value, and tab_head_row_fnum is the value on |
1189 | + * disk. tab_head_row_fnum is set by the writer as the changes are applied |
1190 | + * to the database. |
1191 | + * |
1192 | + * This is the value then stored in the header of the file. This value |
1193 | + * is in sync with other changes to the file. |
1194 | + * |
1195 | + * So the fact that I am setting both value means this will not work at |
1196 | + * runtime, unless all changes have been applied by the writer. |
1197 | + * |
1198 | + * The correct way to do this at run time would be to add the change to the |
1199 | + * transaction log, so that it is applied by the writer. |
1200 | + */ |
1201 | + tab->tab_row_fnum = free_count; |
1202 | + tab->tab_head_row_fnum = free_count; |
1203 | + tab->tab_flush_pending = TRUE; |
1204 | + xt_logf(XT_NT_INFO, "Table %s: free row count (%llu) has been set to the number of rows on the list: %llu\n", table_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count); |
1205 | + } |
1206 | + else |
1207 | + xt_logf(XT_NT_INFO, "Table %s: free row count (%llu) differs from the number of rows on the list: %llu\n", table_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count); |
1208 | + } |
1209 | + |
1210 | + xt_unlock_mutex_ns(&tab->tab_row_lock); |
1211 | +} |
1212 | + |
1213 | /* |
1214 | * Record buffer size: |
1215 | * ------------------- |
1216 | @@ -2010,7 +2184,7 @@ |
1217 | prec_id = rec_id; |
1218 | rec_id = XT_GET_DISK_4(rec_buf->tr_prev_rec_id_4); |
1219 | } |
1220 | - if (free_count2 < free_rec_count) |
1221 | + if (free_count2 != free_rec_count) |
1222 | xt_logf(XT_INFO, "Table %s: not all free blocks (%llu) on free list: %llu\n", tab->tab_name, (u_llong) free_rec_count, (u_llong) free_count2); |
1223 | |
1224 | freer_(); // xt_unlock_mutex_ns(&tab->tab_rec_lock); |
1225 | @@ -2042,6 +2216,29 @@ |
1226 | rec_id++; |
1227 | } |
1228 | |
1229 | + prec_id = 0; |
1230 | + free_count2 = 0; |
1231 | + row_id = tab->tab_row_free_id; |
1232 | + while (row_id) { |
1233 | + if (row_id >= tab->tab_row_eof_id) { |
1234 | + xt_logf(XT_INFO, "Table %s: invalid reference on free row: %llu, ", tab->tab_name, (u_llong) row_id); |
1235 | + if (prec_id) |
1236 | + xt_logf(XT_INFO, "reference by: %llu\n", (u_llong) prec_id); |
1237 | + else |
1238 | + xt_logf(XT_INFO, "reference by list head pointer\n"); |
1239 | + break; |
1240 | + } |
1241 | + if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, row_id, &ref_id, self)) { |
1242 | + xt_log_and_clear_exception(self); |
1243 | + break; |
1244 | + } |
1245 | + free_count2++; |
1246 | + prec_id = row_id; |
1247 | + row_id = ref_id; |
1248 | + } |
1249 | + if (free_count2 != tab->tab_row_fnum) |
1250 | + xt_logf(XT_INFO, "Table %s: free row count (%llu) differs from the number of row on the list: %llu\n", tab->tab_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count2); |
1251 | + |
1252 | freer_(); // xt_unlock_mutex(&tab->tab_row_lock); |
1253 | |
1254 | #ifdef CHECK_INDEX_ON_CHECK_TABLE |
1255 | @@ -3117,10 +3314,18 @@ |
1256 | #endif |
1257 | break; |
1258 | case XT_XN_REREAD: |
1259 | + /* {RETRY-READ} |
1260 | + * TODO: This is not as "correct" as it could be. |
1261 | + * Such records should be considered to be aborted, |
1262 | + * and removed from the list. |
1263 | + */ |
1264 | if (invalid_rec != var_rec_id) { |
1265 | invalid_rec = var_rec_id; |
1266 | goto retry_3; |
1267 | } |
1268 | + if (!tab_record_corrupt(ot, row_id, var_rec_id, true, 1)) |
1269 | + goto failed; |
1270 | + |
1271 | /* Assume end of list. */ |
1272 | #ifdef XT_CRASH_DEBUG |
1273 | /* Should not happen! */ |
1274 | @@ -3308,6 +3513,8 @@ |
1275 | /* Avoid infinite loop: */ |
1276 | if (read_again) { |
1277 | /* Should not happen! */ |
1278 | + if (!tab_record_corrupt(ot, row_id, ot->ot_curr_rec_id, true, 2)) |
1279 | + return XT_ERR; |
1280 | #ifdef XT_CRASH_DEBUG |
1281 | /* Generate a core dump! */ |
1282 | xt_crash_me(); |
1283 | @@ -3364,6 +3571,8 @@ |
1284 | /* Avoid infinite loop: */ |
1285 | if (read_again) { |
1286 | /* Should not happen! */ |
1287 | + if (!tab_record_corrupt(ot, XT_GET_DISK_4(((XTTabRecHeadDPtr) ot->ot_row_rbuffer)->tr_row_id_4), ot->ot_curr_rec_id, true, 3)) |
1288 | + return XT_ERR; |
1289 | #ifdef XT_CRASH_DEBUG |
1290 | /* Generate a core dump! */ |
1291 | xt_crash_me(); |
1292 | @@ -3580,6 +3789,7 @@ |
1293 | } |
1294 | tab->tab_row_free_id = row_id; |
1295 | tab->tab_row_fnum++; |
1296 | + ASSERT_NS(tab->tab_row_fnum < tab->tab_row_eof_id); |
1297 | xt_unlock_mutex_ns(&tab->tab_row_lock); |
1298 | |
1299 | if (!xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_ROW_FREED, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &free_row, ot->ot_thread)) |
1300 | @@ -3776,7 +3986,7 @@ |
1301 | xt_lock_mutex_ns(&tab->tab_db->db_co_ext_lock); |
1302 | if (!xt_tab_get_rec_data(ot, rec_id, XT_REC_EXT_HEADER_SIZE, ot->ot_row_rbuffer)) { |
1303 | xt_unlock_mutex_ns(&tab->tab_db->db_co_ext_lock); |
1304 | - return FAILED; |
1305 | + return XT_ERR; |
1306 | } |
1307 | xt_unlock_mutex_ns(&tab->tab_db->db_co_ext_lock); |
1308 | |
1309 | @@ -3824,7 +4034,7 @@ |
1310 | XT_SET_DISK_4(free_rec->rf_next_rec_id_4, prev_rec_id); |
1311 | if (!xt_tab_put_rec_data(ot, rec_id, sizeof(XTTabRecFreeDRec), ot->ot_row_rbuffer, &op_seq)) { |
1312 | xt_unlock_mutex_ns(&tab->tab_rec_lock); |
1313 | - return FAILED; |
1314 | + return XT_ERR; |
1315 | } |
1316 | tab->tab_rec_free_id = rec_id; |
1317 | ASSERT_NS(tab->tab_rec_free_id < tab->tab_rec_eof_id); |
1318 | @@ -3832,7 +4042,9 @@ |
1319 | xt_unlock_mutex_ns(&tab->tab_rec_lock); |
1320 | |
1321 | free_rec->rf_rec_type_1 = old_rec_type; |
1322 | - return xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_REC_REMOVED_BI, op_seq, (xtRecordID) new_rec_type, rec_id, rec_size, ot->ot_row_rbuffer, ot->ot_thread); |
1323 | + if (!xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_REC_REMOVED_BI, op_seq, (xtRecordID) new_rec_type, rec_id, rec_size, ot->ot_row_rbuffer, ot->ot_thread)) |
1324 | + return XT_ERR; |
1325 | + return OK; |
1326 | } |
1327 | |
1328 | static xtRowID tab_new_row(XTOpenTablePtr ot, XTTableHPtr tab) |
1329 | @@ -3851,6 +4063,7 @@ |
1330 | return 0; |
1331 | } |
1332 | tab->tab_row_free_id = next_row_id; |
1333 | + ASSERT_NS(tab->tab_row_fnum > 0); |
1334 | tab->tab_row_fnum--; |
1335 | } |
1336 | else { |
1337 | @@ -4170,9 +4383,12 @@ |
1338 | return FAILED; |
1339 | if (XT_REC_IS_CLEAN(var_head.tr_rec_type_1)) |
1340 | goto locked; |
1341 | - if (XT_REC_IS_FREE(var_head.tr_rec_type_1)) |
1342 | + if (XT_REC_IS_FREE(var_head.tr_rec_type_1)) { |
1343 | /* Should not happen: */ |
1344 | + if (!tab_record_corrupt(ot, row_id, var_rec_id, false, 4)) |
1345 | + return FAILED; |
1346 | goto record_invalid; |
1347 | + } |
1348 | xn_id = XT_GET_DISK_4(var_head.tr_xact_id_4); |
1349 | switch (xt_xn_status(ot, xn_id, var_rec_id)) { |
1350 | case XT_XN_VISIBLE: |
1351 | @@ -4195,6 +4411,8 @@ |
1352 | XT_TAB_ROW_WRITE_LOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread); |
1353 | goto retry; |
1354 | case XT_XN_REREAD: |
1355 | + if (!tab_record_corrupt(ot, row_id, var_rec_id, true, 5)) |
1356 | + return FAILED; |
1357 | goto record_invalid; |
1358 | } |
1359 | var_rec_id = XT_GET_DISK_4(var_head.tr_prev_rec_id_4); |
1360 | @@ -4206,9 +4424,10 @@ |
1361 | return FAILED; |
1362 | |
1363 | record_invalid: |
1364 | + /* {RETRY-READ} */ |
1365 | /* Prevent an infinite loop due to a bad record: */ |
1366 | if (invalid_rec != var_rec_id) { |
1367 | - var_rec_id = invalid_rec; |
1368 | + invalid_rec = var_rec_id; |
1369 | goto retry; |
1370 | } |
1371 | /* The record is invalid, it will be "overwritten"... */ |
1372 | @@ -4280,9 +4499,12 @@ |
1373 | #ifdef TRACE_VARIATIONS_IN_DUP_CHECK |
1374 | t_type="Re-read"; |
1375 | #endif |
1376 | + /* {RETRY-READ} */ |
1377 | /* Avoid infinite loop: */ |
1378 | if (invalid_rec == rec_id) { |
1379 | /* Should not happen! */ |
1380 | + if (!tab_record_corrupt(ot, XT_GET_DISK_4(rec_head.tr_row_id_4), rec_id, true, 6)) |
1381 | + goto failed; |
1382 | #ifdef XT_CRASH_DEBUG |
1383 | /* Generate a core dump! */ |
1384 | xt_crash_me(); |
1385 | @@ -4327,7 +4549,7 @@ |
1386 | if (XT_REC_IS_FREE(rec_head.tr_rec_type_1)) { |
1387 | /* Should not happen: */ |
1388 | if (invalid_rec != var_rec_id) { |
1389 | - var_rec_id = invalid_rec; |
1390 | + invalid_rec = var_rec_id; |
1391 | goto retry; |
1392 | } |
1393 | /* Assume end of list. */ |
1394 | @@ -4364,11 +4586,14 @@ |
1395 | } |
1396 | break; |
1397 | case XT_XN_REREAD: |
1398 | + /* {RETRY-READ} */ |
1399 | if (invalid_rec != var_rec_id) { |
1400 | - var_rec_id = invalid_rec; |
1401 | + invalid_rec = var_rec_id; |
1402 | goto retry; |
1403 | } |
1404 | /* Assume end of list. */ |
1405 | + if (!tab_record_corrupt(ot, row_id, invalid_rec, true, 7)) |
1406 | + goto failed; |
1407 | #ifdef XT_CRASH_DEBUG |
1408 | /* Should not happen! */ |
1409 | xt_crash_me(); |
1410 | @@ -5068,6 +5293,8 @@ |
1411 | ot->ot_on_page = FALSE; |
1412 | goto next_page; |
1413 | } |
1414 | + if (!tab_record_corrupt(ot, XT_GET_DISK_4(((XTTabRecHeadDPtr) buff_ptr)->tr_row_id_4), invalid_rec, true, 8)) |
1415 | + return XT_ERR; |
1416 | #ifdef XT_CRASH_DEBUG |
1417 | /* Should not happen! */ |
1418 | xt_crash_me(); |
1419 | @@ -5240,7 +5467,7 @@ |
1420 | return FALSE; |
1421 | } |
1422 | |
1423 | -static void tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size) |
1424 | +xtPublic void xt_tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size) |
1425 | { |
1426 | char *nptr; |
1427 | |
1428 | @@ -5316,7 +5543,7 @@ |
1429 | { |
1430 | char table_name[XT_IDENTIFIER_NAME_SIZE*3+3]; |
1431 | |
1432 | - tab_make_table_name(tab, table_name, sizeof(table_name)); |
1433 | + xt_tab_make_table_name(tab, table_name, sizeof(table_name)); |
1434 | return tab_exec_repair_pending(tab->tab_db, REP_FIND, table_name); |
1435 | } |
1436 | |
1437 | @@ -5326,7 +5553,7 @@ |
1438 | char table_name[XT_IDENTIFIER_NAME_SIZE*3+3]; |
1439 | |
1440 | tab->tab_repair_pending = FALSE; |
1441 | - tab_make_table_name(tab, table_name, sizeof(table_name)); |
1442 | + xt_tab_make_table_name(tab, table_name, sizeof(table_name)); |
1443 | tab_exec_repair_pending(tab->tab_db, REP_DEL, table_name); |
1444 | } |
1445 | } |
1446 | @@ -5337,7 +5564,7 @@ |
1447 | char table_name[XT_IDENTIFIER_NAME_SIZE*3+3]; |
1448 | |
1449 | tab->tab_repair_pending = TRUE; |
1450 | - tab_make_table_name(tab, table_name, sizeof(table_name)); |
1451 | + xt_tab_make_table_name(tab, table_name, sizeof(table_name)); |
1452 | tab_exec_repair_pending(tab->tab_db, REP_ADD, table_name); |
1453 | } |
1454 | } |
1455 | |
1456 | === modified file 'storage/pbxt/src/table_xt.h' |
1457 | --- storage/pbxt/src/table_xt.h 2010-05-05 10:59:57 +0000 |
1458 | +++ storage/pbxt/src/table_xt.h 2010-09-17 10:32:54 +0000 |
1459 | @@ -507,6 +507,7 @@ |
1460 | int xt_tab_compare_paths(char *n1, char *n2); |
1461 | void xt_tab_init_db(struct XTThread *self, struct XTDatabase *db); |
1462 | void xt_tab_exit_db(struct XTThread *self, struct XTDatabase *db); |
1463 | +void xt_tab_check_free_lists(struct XTThread *self, XTOpenTablePtr ot, bool check_recs, bool correct_count); |
1464 | void xt_check_tables(struct XTThread *self); |
1465 | |
1466 | char *xt_tab_file_to_name(size_t size, char *tab_name, char *file_name); |
1467 | @@ -572,6 +573,7 @@ |
1468 | void xt_tab_disable_index(XTTableHPtr tab, u_int ind_error); |
1469 | void xt_tab_set_index_error(XTTableHPtr tab); |
1470 | |
1471 | +void xt_tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size); |
1472 | xtBool xt_tab_is_table_repair_pending(XTTableHPtr tab); |
1473 | void xt_tab_table_repaired(XTTableHPtr tab); |
1474 | void xt_tab_set_table_repair_pending(XTTableHPtr tab); |
1475 | |
1476 | === modified file 'storage/pbxt/src/thread_xt.cc' |
1477 | --- storage/pbxt/src/thread_xt.cc 2010-05-06 12:42:28 +0000 |
1478 | +++ storage/pbxt/src/thread_xt.cc 2010-09-17 10:32:54 +0000 |
1479 | @@ -224,11 +224,16 @@ |
1480 | #else |
1481 | /* Use the buffer, unless it is too small */ |
1482 | va_list ap2; |
1483 | + int bufsize; |
1484 | |
1485 | va_copy(ap2, ap); |
1486 | - if (vsnprintf(buffer, DEFAULT_LOG_BUFFER_SIZE, fmt, ap) >= DEFAULT_LOG_BUFFER_SIZE) { |
1487 | - if (vasprintf(&log_string, fmt, ap2) == -1) |
1488 | + bufsize = vsnprintf(buffer, DEFAULT_LOG_BUFFER_SIZE, fmt, ap); |
1489 | + if (bufsize >= DEFAULT_LOG_BUFFER_SIZE) { |
1490 | + log_string = (char *) malloc(bufsize + 1); |
1491 | + if (vsnprintf(log_string, bufsize + 1, fmt, ap2) > bufsize) { |
1492 | + free(log_string); |
1493 | log_string = NULL; |
1494 | + } |
1495 | } |
1496 | else |
1497 | log_string = buffer; |
1498 | |
1499 | === modified file 'storage/pbxt/src/xaction_xt.cc' |
1500 | --- storage/pbxt/src/xaction_xt.cc 2010-05-05 10:59:57 +0000 |
1501 | +++ storage/pbxt/src/xaction_xt.cc 2010-09-17 10:32:54 +0000 |
1502 | @@ -1558,6 +1558,8 @@ |
1503 | * Because we are only here because the record was valid but not |
1504 | * clean (you can confirm this by looking at the code that |
1505 | * calls this function). |
1506 | + * |
1507 | + * See {RETRY-READ} |
1508 | */ |
1509 | return XT_XN_REREAD; |
1510 | } |
1511 | @@ -1743,7 +1745,7 @@ |
1512 | } |
1513 | else { |
1514 | xn_log_id = x_log_id; |
1515 | - x_log_offset = x_log_offset; |
1516 | + xn_log_offset = x_log_offset; |
1517 | } |
1518 | } |
1519 | xn_id++; |
1520 | |
1521 | === modified file 'storage/pbxt/src/xt_defs.h' |
1522 | --- storage/pbxt/src/xt_defs.h 2010-06-01 19:52:20 +0000 |
1523 | +++ storage/pbxt/src/xt_defs.h 2010-09-17 10:32:54 +0000 |
1524 | @@ -397,6 +397,24 @@ |
1525 | */ |
1526 | #define XT_XLOG_FLUSH_FREQ 1000 |
1527 | |
1528 | +/* |
1529 | + * Define here if you want to check (and correct) the table free list |
1530 | + * counts. The free list counts are not durable, because they are not |
1531 | + * written to the log. |
1532 | + * |
1533 | + * The row free count is most critical because it can be used to |
1534 | + * estimate the the of rows in the record. |
1535 | + */ |
1536 | +#define XT_CHECK_ROW_FREE_COUNT |
1537 | +#ifdef DEBUG |
1538 | +#define XT_CHECK_RECORD_FREE_COUNT |
1539 | +#endif |
1540 | +#define XT_CORRECT_TABLE_FREE_COUNT |
1541 | + |
1542 | +#if defined(XT_CHECK_ROW_FREE_COUNT) && defined(XT_CORRECT_TABLE_FREE_COUNT) |
1543 | +#define XT_ROW_COUNT_CORRECTED |
1544 | +#endif |
1545 | + |
1546 | /* ---------------------------------------------------------------------- |
1547 | * GLOBAL CONSTANTS |
1548 | */ |
1549 | @@ -782,7 +800,7 @@ |
1550 | #define MX_ULONG_T uint32_t |
1551 | #define MX_ULONGLONG_T uint64_t |
1552 | #define MX_LONGLONG_T uint64_t |
1553 | -#define MX_CHARSET_INFO const struct charset_info_st |
1554 | +#define MX_CHARSET_INFO struct charset_info_st |
1555 | #define MX_CONST_CHARSET_INFO const struct charset_info_st |
1556 | #define MX_CONST const |
1557 | #define MX_BITMAP MyBitmap |
1558 | @@ -873,7 +891,11 @@ |
1559 | #define MX_ULONGLONG_T ulonglong |
1560 | #define MX_LONGLONG_T longlong |
1561 | #define MX_CHARSET_INFO CHARSET_INFO |
1562 | -#define MX_CONST_CHARSET_INFO const struct charset_info_st |
1563 | +#ifdef MARIADB_BASE_VERSION |
1564 | +#define MX_CONST_CHARSET_INFO const struct charset_info_st |
1565 | +#else |
1566 | +#define MX_CONST_CHARSET_INFO struct charset_info_st |
1567 | +#endif |
1568 | #define MX_CONST |
1569 | #define MX_BITMAP MY_BITMAP |
1570 | #define MX_BIT_SIZE() n_bits |
Hi!
>>>>> "Paul" == Paul McCullagh <email address hidden> writes:
Paul> Paul McCullagh has proposed merging lp:~paul-mccullagh/maria/pbxt-1.0.11-7 into lp:maria.
Paul> Requested reviews:
Paul> Maria-captains (maria-captains)
Paul> This is the latest version of the PBXT Pre-GA, version 1.0.11-7. Details of changes are in the release notes (storage/ pbxt/ChangeLog) .
Paul> I have updated the 2 test results as required. In this version, PBXT once again estimates the number of rows in the table correctly. This changes the output of some EXPLAIN commands.
I will start the merge today. Thanks!
By the way, I don't know if you noticed but I have fixed some compiler
warnings in the pbxt code in MariaDB; Feel free to backport those that
makes sence for you :)
Regards,
Monty