Merge lp:~paul-mccullagh/maria/pbxt-1.0.11-7 into lp:maria/5.3

Proposed by Paul McCullagh
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
Reviewer Review Type Date Requested Status
Maria-captains Pending
Review via email: mp+35794@code.launchpad.net

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/pbxt/ChangeLog).

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.

To post a comment you must log in.
Revision history for this message
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/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

Revision history for this message
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/pbxt/ChangeLog).

<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

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches