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

Proposed by Paul McCullagh
Status: Superseded
Proposed branch: lp:~paul-mccullagh/maria/maria-pbxt-rc3
Merge into: lp:~maria-captains/maria/5.1-converting
Diff against target: 5759 lines (+2595/-366)
47 files modified
sql/handler.cc (+9/-1)
storage/pbxt/ChangeLog (+52/-0)
storage/pbxt/src/Makefile.am (+2/-2)
storage/pbxt/src/backup_xt.cc (+802/-0)
storage/pbxt/src/backup_xt.h (+34/-0)
storage/pbxt/src/cache_xt.cc (+7/-3)
storage/pbxt/src/cache_xt.h (+1/-1)
storage/pbxt/src/database_xt.cc (+14/-0)
storage/pbxt/src/database_xt.h (+8/-0)
storage/pbxt/src/datadic_xt.cc (+1/-6)
storage/pbxt/src/datalog_xt.cc (+4/-4)
storage/pbxt/src/discover_xt.cc (+301/-15)
storage/pbxt/src/filesys_xt.cc (+3/-5)
storage/pbxt/src/filesys_xt.h (+1/-1)
storage/pbxt/src/ha_pbxt.cc (+526/-119)
storage/pbxt/src/ha_pbxt.h (+26/-9)
storage/pbxt/src/ha_xtsys.h (+2/-1)
storage/pbxt/src/heap_xt.cc (+1/-1)
storage/pbxt/src/index_xt.cc (+18/-7)
storage/pbxt/src/lock_xt.cc (+1/-1)
storage/pbxt/src/locklist_xt.h (+7/-2)
storage/pbxt/src/memory_xt.cc (+2/-3)
storage/pbxt/src/myxt_xt.cc (+164/-29)
storage/pbxt/src/myxt_xt.h (+4/-0)
storage/pbxt/src/pbms.h (+12/-12)
storage/pbxt/src/pbms_enabled.cc (+11/-12)
storage/pbxt/src/pbms_enabled.h (+0/-7)
storage/pbxt/src/pthread_xt.cc (+2/-2)
storage/pbxt/src/restart_xt.cc (+119/-49)
storage/pbxt/src/restart_xt.h (+13/-1)
storage/pbxt/src/strutil_xt.cc (+10/-4)
storage/pbxt/src/systab_xt.cc (+2/-2)
storage/pbxt/src/tabcache_xt.cc (+3/-1)
storage/pbxt/src/tabcache_xt.h (+1/-1)
storage/pbxt/src/table_xt.cc (+85/-20)
storage/pbxt/src/table_xt.h (+3/-2)
storage/pbxt/src/thread_xt.cc (+16/-1)
storage/pbxt/src/thread_xt.h (+4/-1)
storage/pbxt/src/util_xt.cc (+17/-0)
storage/pbxt/src/util_xt.h (+1/-0)
storage/pbxt/src/xaction_xt.cc (+169/-6)
storage/pbxt/src/xaction_xt.h (+29/-1)
storage/pbxt/src/xactlog_xt.cc (+48/-23)
storage/pbxt/src/xactlog_xt.h (+12/-2)
storage/pbxt/src/xt_config.h (+15/-2)
storage/pbxt/src/xt_defs.h (+30/-7)
storage/pbxt/src/xt_errno.h (+3/-0)
To merge this branch: bzr merge lp:~paul-mccullagh/maria/maria-pbxt-rc3
Reviewer Review Type Date Requested Status
Paul McCullagh Needs Resubmitting
Review via email: mp+15480@code.launchpad.net

This proposal has been superseded by a proposal from 2009-12-10.

To post a comment you must log in.
Revision history for this message
Paul McCullagh (paul-mccullagh) wrote :
Download full text (3.5 KiB)

This is the 3rd RC release of PBXT. It includes a number of bug fixes (some specifically for MariaDB), and 2 features:

- XA/2-Phase commit support
- Online backup native driver for PBXT

The backup uses the MySQL backup API (MySQL 6.0/5.4), and is not yet available in MariaDB.

Release notes since the RC2 version already in MariaDB are as follows:

------- 1.0.09f RC3 - 2009-11-30

RN291: Fixed bug #489088: On shutdown MySQL reports: [Warning] Plugin 'PBXT' will be forced to shutdown.

RN290: Fixed bug #345524: pbxt does not compile on 64 bit windows. Currently atomic operations are not supported on this platform.

RN286: Fixed a bug introduced in RN281, which could cause an index scan to hang. The original change was to prevent a warning in Valgrind.

RN285: Merged changes required to compile with Drizzle.

RN284: Fixed bug that cause the error "[ERROR] Invalid (old?) table or database name 'mysqld.1'", when running temp_table.test under MariaDB (thanks to Monty for his initial bug fix). Added a fix for partition table names as well.

RN283: Added win_inttypes.h to the distribution. This file is only required for the Windows build.

RN282: Fixed bug #451101: jump or move depends on uninitialised value in myxt_get_key_length

RN281: Fixed bug #451080: Uninitialised memory write in XTDatabaseLog::xlog_append

RN280: Fixed bug #451085: jump or move depends on uninitialised value in my_type_to_string

RN279: Fixed bug #441000: xtstat crashes with segmentation fault on startup if max_pbxt_threads exceeded.

------- 1.0.09e RC3 - 2009-11-20

RN278: Fixed compile error with MySQL 5.1.41.

------- 1.0.09d RC3 - 2009-09-30

RN277: Added r/o flag to pbxt_max_threads server variable (this fix is related to bug #430637)

RN276: Added test case for replication on tables w/o PKs (see bug #430716)

RN275: Fixed bug #430600: 'Failed to read auto-increment value from storage engine' error.

RN274: Fixed bug #431240: This report is public edit xtstat fails if no PBXT table has been created. xtstat now accepts --database=information_schema or --database=pbxt. Depending on this setting PBXT will either use the information_schema.pbxt_statistics or the pbxt.statistics table. If information_schema is used, then the statistics are displayed even when no PBXT table exists. Recovery activity is also displayed, unless pbxt_support_xa=1, in which case MySQL will wait for PBXT recovery to complete before allowing connections.

RN273: Fixed bug #430633: XA_RBDEADLOCK is not returned on XA END after the transacting ended with a deadlock.

RN272: Fixed bug #430596: Backup/restore does not work well even on a basic PBXT table with auto-increment.

------- 1.0.09c RC3 - 2009-09-16

RN271: Windows build update: now you can simply put the pbxt directory under <mysql-root>/storage and build the PBXT engine as a part of the source tree. The engine will be linked statically. Be sure to specify the WITH_PBXT_STORAGE_ENGINE option when running win\configure.js

RN270: Correctly disabled PBMS so that this version now compiles under Windows. If PBMS_ENABLED is defined, PBXT will not compile under Windows becaause of a getpid() call in pbms.h.

------- 1.0.09 RC3 - 2009-09-09

RN26...

Read more...

Revision history for this message
Paul McCullagh (paul-mccullagh) wrote :

This patch changes MariaDB code in one case:

File handler.cc, Line 1591

DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog

This line has been commented out, because the assertions fails now that PBXT supports XA.

Although this assertion implies that not everything will work, I have not found any problem with the stability of MySQL due to the addition of PBXT XA.

PBXT XA can be disabled by setting pbxt_support_xa=0, it is enabled by default.

Revision history for this message
Paul McCullagh (paul-mccullagh) wrote :

I have made 2 changes:

1. I have improved the bug fix in RN291 (bug #489088). The problem was: [Warning] Plugin 'PBXT' will be forced to shutdown. The bug fix caused a crash under certain circumstances. This has been fixed.

2. I have def'd out the following code (changed ifndef to ifdef):

#ifndef WILL_BE_DELETED_LATER
  /*
    for now, only InnoDB supports 2pc. It means we can always safely
    rollback all pending transactions, without risking inconsistent data
  */
  DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
  info.dry_run=FALSE;
#endif

review: Needs Resubmitting

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'sql/handler.cc'
2--- sql/handler.cc 2009-12-03 11:19:05 +0000
3+++ sql/handler.cc 2009-12-10 11:48:17 +0000
4@@ -1584,7 +1584,15 @@
5 if (info.commit_list)
6 sql_print_information("Starting crash recovery...");
7
8-#ifndef WILL_BE_DELETED_LATER
9+/* With PBXT 1.0.09 2 engines now support XA. According to Sergei, this
10+ code below should therefore be removed. The code below
11+ handles the case when the engines report prepared transactions,
12+ but the binlogs are missing or have no recovery information.
13+ In this case the tc_heuristic_recover variable determines whether
14+ prepared transcations should be committed or rolled back.
15+ If there is only one engine, then rollback is safe.
16+ */
17+#ifdef WILL_BE_DELETED_LATER
18 /*
19 for now, only InnoDB supports 2pc. It means we can always safely
20 rollback all pending transactions, without risking inconsistent data
21
22=== modified file 'storage/pbxt/ChangeLog'
23--- storage/pbxt/ChangeLog 2009-09-03 06:15:03 +0000
24+++ storage/pbxt/ChangeLog 2009-12-10 11:48:17 +0000
25@@ -1,6 +1,58 @@
26 PBXT Release Notes
27 ==================
28
29+------- 1.0.09f RC3 - 2009-11-30
30+
31+RN291: Fixed bug #489088: On shutdown MySQL reports: [Warning] Plugin 'PBXT' will be forced to shutdown.
32+
33+RN290: Fixed bug #345524: pbxt does not compile on 64 bit windows. Currently atomic operations are not supported on this platform.
34+
35+RN286: Fixed a bug introduced in RN281, which could cause an index scan to hang. The original change was to prevent a warning in Valgrind.
36+
37+RN285: Merged changes required to compile with Drizzle.
38+
39+RN284: Fixed bug that cause the error "[ERROR] Invalid (old?) table or database name 'mysqld.1'", when running temp_table.test under MariaDB (thanks to Monty for his initial bug fix). Added a fix for partition table names as well.
40+
41+RN283: Added win_inttypes.h to the distribution. This file is only required for the Windows build.
42+
43+RN282: Fixed bug #451101: jump or move depends on uninitialised value in myxt_get_key_length
44+
45+RN281: Fixed bug #451080: Uninitialised memory write in XTDatabaseLog::xlog_append
46+
47+RN280: Fixed bug #451085: jump or move depends on uninitialised value in my_type_to_string
48+
49+RN279: Fixed bug #441000: xtstat crashes with segmentation fault on startup if max_pbxt_threads exceeded.
50+
51+------- 1.0.09e RC3 - 2009-11-20
52+
53+RN278: Fixed compile error with MySQL 5.1.41.
54+
55+------- 1.0.09d RC3 - 2009-09-30
56+
57+RN277: Added r/o flag to pbxt_max_threads server variable (this fix is related to bug #430637)
58+
59+RN276: Added test case for replication on tables w/o PKs (see bug #430716)
60+
61+RN275: Fixed bug #430600: 'Failed to read auto-increment value from storage engine' error.
62+
63+RN274: Fixed bug #431240: This report is public edit xtstat fails if no PBXT table has been created. xtstat now accepts --database=information_schema or --database=pbxt. Depending on this setting PBXT will either use the information_schema.pbxt_statistics or the pbxt.statistics table. If information_schema is used, then the statistics are displayed even when no PBXT table exists. Recovery activity is also displayed, unless pbxt_support_xa=1, in which case MySQL will wait for PBXT recovery to complete before allowing connections.
64+
65+RN273: Fixed bug #430633: XA_RBDEADLOCK is not returned on XA END after the transacting ended with a deadlock.
66+
67+RN272: Fixed bug #430596: Backup/restore does not work well even on a basic PBXT table with auto-increment.
68+
69+------- 1.0.09c RC3 - 2009-09-16
70+
71+RN271: Windows build update: now you can simply put the pbxt directory under <mysql-root>/storage and build the PBXT engine as a part of the source tree. The engine will be linked statically. Be sure to specify the WITH_PBXT_STORAGE_ENGINE option when running win\configure.js
72+
73+RN270: Correctly disabled PBMS so that this version now compiles under Windows. If PBMS_ENABLED is defined, PBXT will not compile under Windows becaause of a getpid() call in pbms.h.
74+
75+------- 1.0.09 RC3 - 2009-09-09
76+
77+RN269: Implemented online backup. A native online backup driver now performs BACKUP and RESTORE DATABASE operations for PBXT. NOTE: This feature is only supported by MySQL 6.0.9 or later.
78+
79+RN268: Implemented XA support. PBXT now supports all XA related MySQL statements. The variable pbxt_support_xa determines if XA support is enabled. Note: due to MySQL bug #47134, enabling XA support could lead to a crash.
80+
81 ------- 1.0.08d RC2 - 2009-09-02
82
83 RN267: Fixed a bug that caused MySQL to crash on shutdown, after an incorrect command line parameter was given. The crash occurred because the background recovery task was not cleaned up before the PBXT engine was de-initialized.
84
85=== modified file 'storage/pbxt/src/Makefile.am'
86--- storage/pbxt/src/Makefile.am 2009-10-07 07:40:56 +0000
87+++ storage/pbxt/src/Makefile.am 2009-12-10 11:48:17 +0000
88@@ -22,7 +22,7 @@
89 pbms_enabled.h sortedlist_xt.h strutil_xt.h \
90 tabcache_xt.h table_xt.h trace_xt.h thread_xt.h \
91 util_xt.h xaction_xt.h xactlog_xt.h lock_xt.h \
92- systab_xt.h ha_xtsys.h discover_xt.h \
93+ systab_xt.h ha_xtsys.h discover_xt.h backup_xt.h \
94 pbms.h xt_config.h xt_defs.h xt_errno.h locklist_xt.h
95 EXTRA_LTLIBRARIES = libpbxt.la
96
97@@ -32,7 +32,7 @@
98 memory_xt.cc myxt_xt.cc pthread_xt.cc restart_xt.cc \
99 sortedlist_xt.cc strutil_xt.cc \
100 tabcache_xt.cc table_xt.cc trace_xt.cc thread_xt.cc \
101- systab_xt.cc ha_xtsys.cc discover_xt.cc \
102+ systab_xt.cc ha_xtsys.cc discover_xt.cc backup_xt.cc \
103 util_xt.cc xaction_xt.cc xactlog_xt.cc lock_xt.cc locklist_xt.cc
104
105 libpbxt_la_LDFLAGS = -module
106
107=== added file 'storage/pbxt/src/backup_xt.cc'
108--- storage/pbxt/src/backup_xt.cc 1970-01-01 00:00:00 +0000
109+++ storage/pbxt/src/backup_xt.cc 2009-12-10 11:48:17 +0000
110@@ -0,0 +1,802 @@
111+/* Copyright (c) 2009 PrimeBase Technologies GmbH
112+ *
113+ * PrimeBase XT
114+ *
115+ * This program is free software; you can redistribute it and/or modify
116+ * it under the terms of the GNU General Public License as published by
117+ * the Free Software Foundation; either version 2 of the License, or
118+ * (at your option) any later version.
119+ *
120+ * This program is distributed in the hope that it will be useful,
121+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
122+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
123+ * GNU General Public License for more details.
124+ *
125+ * You should have received a copy of the GNU General Public License
126+ * along with this program; if not, write to the Free Software
127+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
128+ *
129+ * 2009-09-07 Paul McCullagh
130+ *
131+ * H&G2JCtL
132+ */
133+
134+#include "xt_config.h"
135+
136+#ifdef MYSQL_SUPPORTS_BACKUP
137+
138+#include <string.h>
139+#include <stdio.h>
140+#include <stdlib.h>
141+#include <time.h>
142+#include <ctype.h>
143+
144+#include "mysql_priv.h"
145+#include <backup/api_types.h>
146+#include <backup/backup_engine.h>
147+#include <backup/backup_aux.h> // for build_table_list()
148+#include <hash.h>
149+
150+#include "ha_pbxt.h"
151+
152+#include "backup_xt.h"
153+#include "pthread_xt.h"
154+#include "filesys_xt.h"
155+#include "database_xt.h"
156+#include "strutil_xt.h"
157+#include "memory_xt.h"
158+#include "trace_xt.h"
159+#include "myxt_xt.h"
160+
161+#ifdef OK
162+#undef OK
163+#endif
164+
165+#ifdef byte
166+#undef byte
167+#endif
168+
169+#ifdef DEBUG
170+//#define TRACE_BACKUP_CALLS
171+//#define TEST_SMALL_BLOCK 100000
172+#endif
173+
174+using backup::byte;
175+using backup::result_t;
176+using backup::version_t;
177+using backup::Table_list;
178+using backup::Table_ref;
179+using backup::Buffer;
180+
181+#ifdef TRACE_BACKUP_CALLS
182+#define XT_TRACE_CALL() ha_trace_function(__FUNC__, NULL)
183+#else
184+#define XT_TRACE_CALL()
185+#endif
186+
187+#define XT_RESTORE_BATCH_SIZE 10000
188+
189+#define BUP_STATE_BEFORE_LOCK 0
190+#define BUP_STATE_AFTER_LOCK 1
191+
192+#define BUP_STANDARD_VAR_RECORD 1
193+#define BUP_RECORD_BLOCK_4_START 2 // Part of a record, with a 4 byte total length, and 4 byte data length
194+#define BUP_RECORD_BLOCK_4 3 // Part of a record, with a 4 byte length
195+#define BUP_RECORD_BLOCK_4_END 4 // Last part of a record with a 4 byte length
196+
197+/*
198+ * -----------------------------------------------------------------------
199+ * UTILITIES
200+ */
201+
202+#ifdef TRACE_BACKUP_CALLS
203+static void ha_trace_function(const char *function, char *table)
204+{
205+ char func_buf[50], *ptr;
206+ XTThreadPtr thread = xt_get_self();
207+
208+ if ((ptr = strchr(function, '('))) {
209+ ptr--;
210+ while (ptr > function) {
211+ if (!(isalnum(*ptr) || *ptr == '_'))
212+ break;
213+ ptr--;
214+ }
215+ ptr++;
216+ xt_strcpy(50, func_buf, ptr);
217+ if ((ptr = strchr(func_buf, '(')))
218+ *ptr = 0;
219+ }
220+ else
221+ xt_strcpy(50, func_buf, function);
222+ if (table)
223+ printf("%s %s (%s)\n", thread ? thread->t_name : "-unknown-", func_buf, table);
224+ else
225+ printf("%s %s\n", thread ? thread->t_name : "-unknown-", func_buf);
226+}
227+#endif
228+
229+/*
230+ * -----------------------------------------------------------------------
231+ * BACKUP DRIVER
232+ */
233+
234+class PBXTBackupDriver: public Backup_driver
235+{
236+ public:
237+ PBXTBackupDriver(const Table_list &);
238+ virtual ~PBXTBackupDriver();
239+
240+ virtual size_t size();
241+ virtual size_t init_size();
242+ virtual result_t begin(const size_t);
243+ virtual result_t end();
244+ virtual result_t get_data(Buffer &);
245+ virtual result_t prelock();
246+ virtual result_t lock();
247+ virtual result_t unlock();
248+ virtual result_t cancel();
249+ virtual void free();
250+ void lock_tables_TL_READ_NO_INSERT();
251+
252+ private:
253+ XTThreadPtr bd_thread;
254+ int bd_state;
255+ u_int bd_table_no;
256+ XTOpenTablePtr bd_ot;
257+ xtWord1 *bd_row_buf;
258+
259+ /* Non-zero if we last returned only part of
260+ * a row.
261+ */
262+ xtWord1 *db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *size, xtWord4 row_len);
263+ xtWord1 *db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *size, xtWord4 total_len, xtWord4 row_len);
264+
265+ xtWord4 bd_row_offset;
266+ xtWord4 bd_row_size;
267+};
268+
269+
270+PBXTBackupDriver::PBXTBackupDriver(const Table_list &tables):
271+Backup_driver(tables),
272+bd_state(BUP_STATE_BEFORE_LOCK),
273+bd_table_no(0),
274+bd_ot(NULL),
275+bd_row_buf(NULL),
276+bd_row_offset(0),
277+bd_row_size(0)
278+{
279+}
280+
281+PBXTBackupDriver::~PBXTBackupDriver()
282+{
283+}
284+
285+/** Estimates total size of backup. @todo improve it */
286+size_t PBXTBackupDriver::size()
287+{
288+ XT_TRACE_CALL();
289+ return UNKNOWN_SIZE;
290+}
291+
292+/** Estimates size of backup before lock. @todo improve it */
293+size_t PBXTBackupDriver::init_size()
294+{
295+ XT_TRACE_CALL();
296+ return 0;
297+}
298+
299+result_t PBXTBackupDriver::begin(const size_t)
300+{
301+ THD *thd = current_thd;
302+ XTExceptionRec e;
303+
304+ XT_TRACE_CALL();
305+
306+ if (!(bd_thread = xt_ha_set_current_thread(thd, &e))) {
307+ xt_log_exception(NULL, &e, XT_LOG_DEFAULT);
308+ return backup::ERROR;
309+ }
310+
311+ return backup::OK;
312+}
313+
314+result_t PBXTBackupDriver::end()
315+{
316+ XT_TRACE_CALL();
317+ if (bd_ot) {
318+ xt_tab_seq_exit(bd_ot);
319+ xt_db_return_table_to_pool_ns(bd_ot);
320+ bd_ot = NULL;
321+ }
322+ if (bd_thread->st_xact_data) {
323+ if (!xt_xn_commit(bd_thread))
324+ return backup::ERROR;
325+ }
326+ return backup::OK;
327+}
328+
329+xtWord1 *PBXTBackupDriver::db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *ret_size, xtWord4 row_len)
330+{
331+ register size_t size = *ret_size;
332+
333+ *buffer = bup_type; // Record type identifier.
334+ buffer++;
335+ size--;
336+ memcpy(buffer, bd_ot->ot_row_wbuffer, row_len);
337+ buffer += row_len;
338+ size -= row_len;
339+ *ret_size = size;
340+ return buffer;
341+}
342+
343+xtWord1 *PBXTBackupDriver::db_write_block(xtWord1 *buffer, xtWord1 bup_type, size_t *ret_size, xtWord4 total_len, xtWord4 row_len)
344+{
345+ register size_t size = *ret_size;
346+
347+ *buffer = bup_type; // Record type identifier.
348+ buffer++;
349+ size--;
350+ if (bup_type == BUP_RECORD_BLOCK_4_START) {
351+ XT_SET_DISK_4(buffer, total_len);
352+ buffer += 4;
353+ size -= 4;
354+ }
355+ XT_SET_DISK_4(buffer, row_len);
356+ buffer += 4;
357+ size -= 4;
358+ memcpy(buffer, bd_ot->ot_row_wbuffer+bd_row_offset, row_len);
359+ buffer += row_len;
360+ size -= row_len;
361+ bd_row_size -= row_len;
362+ bd_row_offset += row_len;
363+ *ret_size = size;
364+ return buffer;
365+}
366+
367+result_t PBXTBackupDriver::get_data(Buffer &buf)
368+{
369+ xtBool eof = FALSE;
370+ size_t size;
371+ xtWord4 row_len;
372+ xtWord1 *buffer;
373+
374+ XT_TRACE_CALL();
375+
376+ if (bd_state == BUP_STATE_BEFORE_LOCK) {
377+ buf.table_num = 0;
378+ buf.size = 0;
379+ buf.last = FALSE;
380+ return backup::READY;
381+ }
382+
383+ /* Open the backup table: */
384+ if (!bd_ot) {
385+ XTThreadPtr self = bd_thread;
386+ XTTableHPtr tab;
387+ char path[PATH_MAX];
388+
389+ if (bd_table_no == m_tables.count()) {
390+ buf.size = 0;
391+ buf.table_num = 0;
392+ buf.last = TRUE;
393+ return backup::DONE;
394+ }
395+
396+ m_tables[bd_table_no].internal_name(path, sizeof(path));
397+ bd_table_no++;
398+ try_(a) {
399+ xt_ha_open_database_of_table(self, (XTPathStrPtr) path);
400+ tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);
401+ pushr_(xt_heap_release, tab);
402+ if (!(bd_ot = xt_db_open_table_using_tab(tab, bd_thread)))
403+ xt_throw(self);
404+ freer_(); // xt_heap_release(tab)
405+
406+ /* Prepare the seqential scan: */
407+ xt_tab_seq_exit(bd_ot);
408+ if (!xt_tab_seq_init(bd_ot))
409+ xt_throw(self);
410+
411+ if (bd_row_buf) {
412+ xt_free(self, bd_row_buf);
413+ bd_row_buf = NULL;
414+ }
415+ bd_row_buf = (xtWord1 *) xt_malloc(self, bd_ot->ot_table->tab_dic.dic_mysql_buf_size);
416+ bd_ot->ot_cols_req = bd_ot->ot_table->tab_dic.dic_no_of_cols;
417+ }
418+ catch_(a) {
419+ ;
420+ }
421+ cont_(a);
422+
423+ if (!bd_ot)
424+ goto failed;
425+ }
426+
427+ buf.table_num = bd_table_no;
428+#ifdef TEST_SMALL_BLOCK
429+ buf.size = TEST_SMALL_BLOCK;
430+#endif
431+ size = buf.size;
432+ buffer = (xtWord1 *) buf.data;
433+ ASSERT_NS(size > 9);
434+
435+ /* First check of a record was partically written
436+ * last time.
437+ */
438+ write_row:
439+ if (bd_row_size > 0) {
440+ row_len = bd_row_size;
441+ if (bd_row_offset == 0) {
442+ if (row_len+1 > size) {
443+ ASSERT_NS(size > 9);
444+ row_len = size - 9;
445+ buffer = db_write_block(buffer, BUP_RECORD_BLOCK_4_START, &size, bd_row_size, row_len);
446+ goto done;
447+ }
448+ buffer = db_write_block(buffer, BUP_STANDARD_VAR_RECORD, &size, row_len);
449+ bd_row_size = 0;
450+ }
451+ else {
452+ if (row_len+5 > size) {
453+ row_len = size - 5;
454+ buffer = db_write_block(buffer, BUP_RECORD_BLOCK_4, &size, 0, row_len);
455+ goto done;
456+ }
457+ buffer = db_write_block(buffer, BUP_RECORD_BLOCK_4_END, &size, 0, row_len);
458+ }
459+ }
460+
461+ /* Now continue with the sequential scan. */
462+ while (size > 1) {
463+ if (!xt_tab_seq_next(bd_ot, bd_row_buf, &eof))
464+ goto failed;
465+ if (eof) {
466+ /* We will go the next table, on the next call. */
467+ xt_tab_seq_exit(bd_ot);
468+ xt_db_return_table_to_pool_ns(bd_ot);
469+ bd_ot = NULL;
470+ break;
471+ }
472+ if (!(row_len = myxt_store_row_data(bd_ot, 0, (char *) bd_row_buf)))
473+ goto failed;
474+ if (row_len+1 > size) {
475+ /* Does not fit: */
476+ bd_row_offset = 0;
477+ bd_row_size = row_len;
478+ /* Only add part of the row, if there is still
479+ * quite a bit of space left:
480+ */
481+ if (size >= (32 * 1024))
482+ goto write_row;
483+ break;
484+ }
485+ buffer = db_write_block(buffer, BUP_STANDARD_VAR_RECORD, &size, row_len);
486+ }
487+
488+ done:
489+ buf.size = buf.size - size;
490+ /* This indicates wnd of data for a table! */
491+ buf.last = eof;
492+
493+ return backup::OK;
494+
495+ failed:
496+ xt_log_and_clear_exception(bd_thread);
497+ return backup::ERROR;
498+}
499+
500+result_t PBXTBackupDriver::prelock()
501+{
502+ XT_TRACE_CALL();
503+ return backup::READY;
504+}
505+
506+result_t PBXTBackupDriver::lock()
507+{
508+ XT_TRACE_CALL();
509+ bd_thread->st_xact_mode = XT_XACT_COMMITTED_READ;
510+ bd_thread->st_ignore_fkeys = FALSE;
511+ bd_thread->st_auto_commit = FALSE;
512+ bd_thread->st_table_trans = FALSE;
513+ bd_thread->st_abort_trans = FALSE;
514+ bd_thread->st_stat_ended = FALSE;
515+ bd_thread->st_stat_trans = FALSE;
516+ bd_thread->st_is_update = FALSE;
517+ if (!xt_xn_begin(bd_thread))
518+ return backup::ERROR;
519+ bd_state = BUP_STATE_AFTER_LOCK;
520+ return backup::OK;
521+}
522+
523+result_t PBXTBackupDriver::unlock()
524+{
525+ XT_TRACE_CALL();
526+ return backup::OK;
527+}
528+
529+result_t PBXTBackupDriver::cancel()
530+{
531+ XT_TRACE_CALL();
532+ return backup::OK; // free() will be called and suffice
533+}
534+
535+void PBXTBackupDriver::free()
536+{
537+ XT_TRACE_CALL();
538+ if (bd_ot) {
539+ xt_tab_seq_exit(bd_ot);
540+ xt_db_return_table_to_pool_ns(bd_ot);
541+ bd_ot = NULL;
542+ }
543+ if (bd_row_buf) {
544+ xt_free_ns(bd_row_buf);
545+ bd_row_buf = NULL;
546+ }
547+ if (bd_thread->st_xact_data)
548+ xt_xn_rollback(bd_thread);
549+ delete this;
550+}
551+
552+void PBXTBackupDriver::lock_tables_TL_READ_NO_INSERT()
553+{
554+ XT_TRACE_CALL();
555+}
556+
557+/*
558+ * -----------------------------------------------------------------------
559+ * BACKUP DRIVER
560+ */
561+
562+class PBXTRestoreDriver: public Restore_driver
563+{
564+ public:
565+ PBXTRestoreDriver(const Table_list &tables);
566+ virtual ~PBXTRestoreDriver();
567+
568+ virtual result_t begin(const size_t);
569+ virtual result_t end();
570+ virtual result_t send_data(Buffer &buf);
571+ virtual result_t cancel();
572+ virtual void free();
573+
574+ private:
575+ XTThreadPtr rd_thread;
576+ u_int rd_table_no;
577+ XTOpenTablePtr rd_ot;
578+ STRUCT_TABLE *rd_my_table;
579+ xtWord1 *rb_row_buf;
580+ u_int rb_col_cnt;
581+ u_int rb_insert_count;
582+
583+ /* Long rows are accumulated here: */
584+ xtWord4 rb_row_len;
585+ xtWord4 rb_data_size;
586+ xtWord1 *rb_row_data;
587+};
588+
589+PBXTRestoreDriver::PBXTRestoreDriver(const Table_list &tables):
590+Restore_driver(tables),
591+rd_thread(NULL),
592+rd_table_no(0),
593+rd_ot(NULL),
594+rb_row_buf(NULL),
595+rb_row_len(0),
596+rb_data_size(0),
597+rb_row_data(NULL)
598+{
599+}
600+
601+PBXTRestoreDriver::~PBXTRestoreDriver()
602+{
603+}
604+
605+result_t PBXTRestoreDriver::begin(const size_t)
606+{
607+ THD *thd = current_thd;
608+ XTExceptionRec e;
609+
610+ XT_TRACE_CALL();
611+
612+ if (!(rd_thread = xt_ha_set_current_thread(thd, &e))) {
613+ xt_log_exception(NULL, &e, XT_LOG_DEFAULT);
614+ return backup::ERROR;
615+ }
616+
617+ return backup::OK;
618+}
619+
620+result_t PBXTRestoreDriver::end()
621+{
622+ XT_TRACE_CALL();
623+ if (rd_ot) {
624+ xt_db_return_table_to_pool_ns(rd_ot);
625+ rd_ot = NULL;
626+ }
627+ //if (rb_row_buf) {
628+ // xt_free_ns(rb_row_buf);
629+ // rb_row_buf = NULL;
630+ //}
631+ if (rb_row_data) {
632+ xt_free_ns(rb_row_data);
633+ rb_row_data = NULL;
634+ }
635+ if (rd_thread->st_xact_data) {
636+ if (!xt_xn_commit(rd_thread))
637+ return backup::ERROR;
638+ }
639+ return backup::OK;
640+}
641+
642+
643+result_t PBXTRestoreDriver::send_data(Buffer &buf)
644+{
645+ size_t size;
646+ xtWord1 type;
647+ xtWord1 *buffer;
648+ xtWord4 row_len;
649+ xtWord1 *rec_data;
650+
651+ XT_TRACE_CALL();
652+
653+ if (buf.table_num != rd_table_no) {
654+ XTThreadPtr self = rd_thread;
655+ XTTableHPtr tab;
656+ char path[PATH_MAX];
657+
658+ if (rd_ot) {
659+ xt_db_return_table_to_pool_ns(rd_ot);
660+ rd_ot = NULL;
661+ }
662+
663+ if (rd_thread->st_xact_data) {
664+ if (!xt_xn_commit(rd_thread))
665+ goto failed;
666+ }
667+ if (!xt_xn_begin(rd_thread))
668+ goto failed;
669+ rb_insert_count = 0;
670+
671+ rd_table_no = buf.table_num;
672+ m_tables[rd_table_no-1].internal_name(path, sizeof(path));
673+ try_(a) {
674+ xt_ha_open_database_of_table(self, (XTPathStrPtr) path);
675+ tab = xt_use_table(self, (XTPathStrPtr) path, FALSE, FALSE, NULL);
676+ pushr_(xt_heap_release, tab);
677+ if (!(rd_ot = xt_db_open_table_using_tab(tab, rd_thread)))
678+ xt_throw(self);
679+ freer_(); // xt_heap_release(tab)
680+
681+ rd_my_table = rd_ot->ot_table->tab_dic.dic_my_table;
682+ if (rd_my_table->found_next_number_field) {
683+ rd_my_table->in_use = current_thd;
684+ rd_my_table->next_number_field = rd_my_table->found_next_number_field;
685+ rd_my_table->mark_columns_used_by_index_no_reset(rd_my_table->s->next_number_index, rd_my_table->read_set);
686+ }
687+
688+ /* This is safe because only one thread can restore a table at
689+ * a time!
690+ */
691+ rb_row_buf = (xtWord1 *) rd_my_table->record[0];
692+ //if (rb_row_buf) {
693+ // xt_free(self, rb_row_buf);
694+ // rb_row_buf = NULL;
695+ //}
696+ //rb_row_buf = (xtWord1 *) xt_malloc(self, rd_ot->ot_table->tab_dic.dic_mysql_buf_size);
697+
698+ rb_col_cnt = rd_ot->ot_table->tab_dic.dic_no_of_cols;
699+
700+ }
701+ catch_(a) {
702+ ;
703+ }
704+ cont_(a);
705+
706+ if (!rd_ot)
707+ goto failed;
708+ }
709+
710+ buffer = (xtWord1 *) buf.data;
711+ size = buf.size;
712+
713+ while (size > 0) {
714+ type = *buffer;
715+ switch (type) {
716+ case BUP_STANDARD_VAR_RECORD:
717+ rec_data = buffer + 1;
718+ break;
719+ case BUP_RECORD_BLOCK_4_START:
720+ buffer++;
721+ row_len = XT_GET_DISK_4(buffer);
722+ buffer += 4;
723+ if (rb_data_size < row_len) {
724+ if (!xt_realloc_ns((void **) &rb_row_data, row_len))
725+ goto failed;
726+ rb_data_size = row_len;
727+ }
728+ row_len = XT_GET_DISK_4(buffer);
729+ buffer += 4;
730+ ASSERT_NS(row_len <= rb_data_size);
731+ if (row_len > rb_data_size) {
732+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
733+ goto failed;
734+ }
735+ memcpy(rb_row_data, buffer, row_len);
736+ rb_row_len = row_len;
737+ buffer += row_len;
738+ if (row_len + 9 > size) {
739+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
740+ goto failed;
741+ }
742+ size -= row_len + 9;
743+ continue;
744+ case BUP_RECORD_BLOCK_4:
745+ buffer++;
746+ row_len = XT_GET_DISK_4(buffer);
747+ buffer += 4;
748+ ASSERT_NS(rb_row_len + row_len <= rb_data_size);
749+ if (rb_row_len + row_len > rb_data_size) {
750+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
751+ goto failed;
752+ }
753+ memcpy(rb_row_data + rb_row_len, buffer, row_len);
754+ rb_row_len += row_len;
755+ buffer += row_len;
756+ if (row_len + 5 > size) {
757+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
758+ goto failed;
759+ }
760+ size -= row_len + 5;
761+ continue;
762+ case BUP_RECORD_BLOCK_4_END:
763+ buffer++;
764+ row_len = XT_GET_DISK_4(buffer);
765+ buffer += 4;
766+ ASSERT_NS(rb_row_len + row_len <= rb_data_size);
767+ if (rb_row_len + row_len > rb_data_size) {
768+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
769+ goto failed;
770+ }
771+ memcpy(rb_row_data + rb_row_len, buffer, row_len);
772+ buffer += row_len;
773+ if (row_len + 5 > size) {
774+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
775+ goto failed;
776+ }
777+ size -= row_len + 5;
778+ rec_data = rb_row_data;
779+ break;
780+ default:
781+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
782+ goto failed;
783+ }
784+
785+ if (!(row_len = myxt_load_row_data(rd_ot, rec_data, rb_row_buf, rb_col_cnt)))
786+ goto failed;
787+
788+ if (rd_ot->ot_table->tab_dic.dic_my_table->found_next_number_field)
789+ ha_set_auto_increment(rd_ot, rd_ot->ot_table->tab_dic.dic_my_table->found_next_number_field);
790+
791+ if (!xt_tab_new_record(rd_ot, rb_row_buf))
792+ goto failed;
793+
794+ if (type == BUP_STANDARD_VAR_RECORD) {
795+ buffer += row_len+1;
796+ if (row_len + 1 > size) {
797+ xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_BACKUP_FORMAT);
798+ goto failed;
799+ }
800+ size -= row_len + 1;
801+ }
802+
803+ rb_insert_count++;
804+ if (rb_insert_count == XT_RESTORE_BATCH_SIZE) {
805+ if (!xt_xn_commit(rd_thread))
806+ goto failed;
807+ if (!xt_xn_begin(rd_thread))
808+ goto failed;
809+ rb_insert_count = 0;
810+ }
811+ }
812+
813+ return backup::OK;
814+
815+ failed:
816+ xt_log_and_clear_exception(rd_thread);
817+ return backup::ERROR;
818+}
819+
820+
821+result_t PBXTRestoreDriver::cancel()
822+{
823+ XT_TRACE_CALL();
824+ /* Nothing to do in cancel(); free() will suffice */
825+ return backup::OK;
826+}
827+
828+void PBXTRestoreDriver::free()
829+{
830+ XT_TRACE_CALL();
831+ if (rd_ot) {
832+ xt_db_return_table_to_pool_ns(rd_ot);
833+ rd_ot = NULL;
834+ }
835+ //if (rb_row_buf) {
836+ // xt_free_ns(rb_row_buf);
837+ // rb_row_buf = NULL;
838+ //}
839+ if (rb_row_data) {
840+ xt_free_ns(rb_row_data);
841+ rb_row_data = NULL;
842+ }
843+ if (rd_thread->st_xact_data)
844+ xt_xn_rollback(rd_thread);
845+ delete this;
846+}
847+
848+/*
849+ * -----------------------------------------------------------------------
850+ * BACKUP ENGINE FACTORY
851+ */
852+
853+#define PBXT_BACKUP_VERSION 1
854+
855+
856+class PBXTBackupEngine: public Backup_engine
857+{
858+ public:
859+ PBXTBackupEngine() { };
860+
861+ virtual version_t version() const {
862+ return PBXT_BACKUP_VERSION;
863+ };
864+
865+ virtual result_t get_backup(const uint32, const Table_list &, Backup_driver* &);
866+
867+ virtual result_t get_restore(const version_t, const uint32, const Table_list &,Restore_driver* &);
868+
869+ virtual void free()
870+ {
871+ delete this;
872+ }
873+};
874+
875+result_t PBXTBackupEngine::get_backup(const u_int count, const Table_list &tables, Backup_driver* &drv)
876+{
877+ PBXTBackupDriver *ptr = new PBXTBackupDriver(tables);
878+
879+ if (!ptr)
880+ return backup::ERROR;
881+ drv = ptr;
882+ return backup::OK;
883+}
884+
885+result_t PBXTBackupEngine::get_restore(const version_t ver, const uint32,
886+ const Table_list &tables, Restore_driver* &drv)
887+{
888+ if (ver > PBXT_BACKUP_VERSION)
889+ {
890+ return backup::ERROR;
891+ }
892+
893+ PBXTRestoreDriver *ptr = new PBXTRestoreDriver(tables);
894+
895+ if (!ptr)
896+ return backup::ERROR;
897+ drv = (Restore_driver *) ptr;
898+ return backup::OK;
899+}
900+
901+
902+Backup_result_t pbxt_backup_engine(handlerton *self, Backup_engine* &be)
903+{
904+ be = new PBXTBackupEngine();
905+
906+ if (!be)
907+ return backup::ERROR;
908+
909+ return backup::OK;
910+}
911+
912+#endif
913
914=== added file 'storage/pbxt/src/backup_xt.h'
915--- storage/pbxt/src/backup_xt.h 1970-01-01 00:00:00 +0000
916+++ storage/pbxt/src/backup_xt.h 2009-12-10 11:48:17 +0000
917@@ -0,0 +1,34 @@
918+/* Copyright (c) 2009 PrimeBase Technologies GmbH
919+ *
920+ * PrimeBase XT
921+ *
922+ * This program is free software; you can redistribute it and/or modify
923+ * it under the terms of the GNU General Public License as published by
924+ * the Free Software Foundation; either version 2 of the License, or
925+ * (at your option) any later version.
926+ *
927+ * This program is distributed in the hope that it will be useful,
928+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
930+ * GNU General Public License for more details.
931+ *
932+ * You should have received a copy of the GNU General Public License
933+ * along with this program; if not, write to the Free Software
934+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
935+ *
936+ * 2009-09-07 Paul McCullagh
937+ *
938+ * H&G2JCtL
939+ */
940+
941+#ifndef __backup_xt_h__
942+#define __backup_xt_h__
943+
944+#include "xt_defs.h"
945+
946+#ifdef MYSQL_SUPPORTS_BACKUP
947+
948+Backup_result_t pbxt_backup_engine(handlerton *self, Backup_engine* &be);
949+
950+#endif
951+#endif
952
953=== modified file 'storage/pbxt/src/cache_xt.cc'
954--- storage/pbxt/src/cache_xt.cc 2009-10-30 18:50:56 +0000
955+++ storage/pbxt/src/cache_xt.cc 2009-12-10 11:48:17 +0000
956@@ -73,7 +73,7 @@
957 #define IDX_CAC_UNLOCK(i, o) xt_xsmutex_unlock(&(i)->cs_lock, (o)->t_id)
958 #elif defined(IDX_CAC_USE_PTHREAD_RW)
959 #define IDX_CAC_LOCK_TYPE xt_rwlock_type
960-#define IDX_CAC_INIT_LOCK(s, i) xt_init_rwlock(s, &(i)->cs_lock)
961+#define IDX_CAC_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, &(i)->cs_lock)
962 #define IDX_CAC_FREE_LOCK(s, i) xt_free_rwlock(&(i)->cs_lock)
963 #define IDX_CAC_READ_LOCK(i, o) xt_slock_rwlock_ns(&(i)->cs_lock)
964 #define IDX_CAC_WRITE_LOCK(i, o) xt_xlock_rwlock_ns(&(i)->cs_lock)
965@@ -94,8 +94,12 @@
966 #define IDX_CAC_UNLOCK(i, s) xt_spinxslock_unlock(&(i)->cs_lock, (s)->t_id)
967 #endif
968
969+#ifdef XT_NO_ATOMICS
970+#define ID_HANDLE_USE_PTHREAD_RW
971+#else
972 #define ID_HANDLE_USE_SPINLOCK
973 //#define ID_HANDLE_USE_PTHREAD_RW
974+#endif
975
976 #if defined(ID_HANDLE_USE_PTHREAD_RW)
977 #define ID_HANDLE_LOCK_TYPE xt_mutex_type
978@@ -374,7 +378,7 @@
979 {
980 DcHandleSlotPtr hs;
981 XTIndBlockPtr block = NULL;
982- u_int hash_idx = 0;
983+ u_int hash_idx = 0;
984 DcSegmentPtr seg = NULL;
985 XTIndBlockPtr xblock;
986
987@@ -1379,7 +1383,7 @@
988 ASSERT_NS(iref->ir_xlock == 2);
989 #endif
990 if (!(block = ind_cac_fetch(ot, ind, address, &seg, TRUE)))
991- return 0;
992+ return FAILED;
993
994 branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2);
995 if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) {
996
997=== modified file 'storage/pbxt/src/cache_xt.h'
998--- storage/pbxt/src/cache_xt.h 2009-08-17 11:12:36 +0000
999+++ storage/pbxt/src/cache_xt.h 2009-12-10 11:48:17 +0000
1000@@ -62,7 +62,7 @@
1001 #define XT_IPAGE_UNLOCK(i, x) xt_atomicrwlock_unlock(i, x)
1002 #elif defined(XT_IPAGE_USE_PTHREAD_RW)
1003 #define XT_IPAGE_LOCK_TYPE xt_rwlock_type
1004-#define XT_IPAGE_INIT_LOCK(s, i) xt_init_rwlock(s, i)
1005+#define XT_IPAGE_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i)
1006 #define XT_IPAGE_FREE_LOCK(s, i) xt_free_rwlock(i)
1007 #define XT_IPAGE_READ_LOCK(i) xt_slock_rwlock_ns(i)
1008 #define XT_IPAGE_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i)
1009
1010=== modified file 'storage/pbxt/src/database_xt.cc'
1011--- storage/pbxt/src/database_xt.cc 2009-08-17 11:12:36 +0000
1012+++ storage/pbxt/src/database_xt.cc 2009-12-10 11:48:17 +0000
1013@@ -54,6 +54,8 @@
1014 * GLOBALS
1015 */
1016
1017+xtPublic XTDatabaseHPtr pbxt_database = NULL; // The global open database
1018+
1019 xtPublic xtLogOffset xt_db_log_file_threshold;
1020 xtPublic size_t xt_db_log_buffer_size;
1021 xtPublic size_t xt_db_transaction_buffer_size;
1022@@ -505,6 +507,15 @@
1023 * all index entries that are not visible have
1024 * been removed.
1025 *
1026+ * REASON WHY WE SET ROWID ON RECOVERY:
1027+ * The row ID is set on recovery because the
1028+ * change to the index may be lost after a crash.
1029+ * The change to the index is done by the sweeper, and
1030+ * there is no record of this change in the log.
1031+ * The sweeper will not "re-sweep" all transations
1032+ * that are recovered. As a result, this upadte
1033+ * of the index by the sweeper may be lost.
1034+ *
1035 * {OPEN-DB-SWEEPER-WAIT}
1036 * This has been moved to after the release of the open
1037 * database lock because:
1038@@ -518,9 +529,12 @@
1039 * - To open the database it needs the open database
1040 * lock.
1041 */
1042+ /*
1043+ * This has been moved, see: {WAIT-FOR-SW-AFTER-RECOV}
1044 pushr_(xt_heap_release, db);
1045 xt_wait_for_sweeper(self, db, 0);
1046 popr_();
1047+ */
1048
1049 return db;
1050 }
1051
1052=== modified file 'storage/pbxt/src/database_xt.h'
1053--- storage/pbxt/src/database_xt.h 2009-04-02 10:03:14 +0000
1054+++ storage/pbxt/src/database_xt.h 2009-12-10 11:48:17 +0000
1055@@ -105,6 +105,8 @@
1056 #define XT_THREAD_IDLE 1
1057 #define XT_THREAD_INERR 2
1058
1059+#define XT_XA_HASH_TAB_SIZE 223
1060+
1061 typedef struct XTDatabase : public XTHeap {
1062 char *db_name; /* The name of the database, last component of the path! */
1063 char *db_main_path;
1064@@ -131,6 +133,9 @@
1065 u_int db_stat_sweep_waits; /* STATISTICS: count the sweeper waits. */
1066 XTDatabaseLogRec db_xlog; /* The transaction log for this database. */
1067 XTXactRestartRec db_restart; /* Database recovery stuff. */
1068+ xt_mutex_type db_xn_xa_lock;
1069+ XTXactPreparePtr db_xn_xa_table[XT_XA_HASH_TAB_SIZE];
1070+ XTSortedListPtr db_xn_xa_list; /* The "wait-for" list, of transactions waiting for other transactions. */
1071
1072 XTSortedListPtr db_xn_wait_for; /* The "wait-for" list, of transactions waiting for other transactions. */
1073 u_int db_xn_call_start; /* Start of the post wait calls. */
1074@@ -198,6 +203,7 @@
1075
1076 void xt_add_pbxt_file(size_t size, char *path, const char *file);
1077 void xt_add_location_file(size_t size, char *path);
1078+void xt_add_pbxt_dir(size_t size, char *path);
1079 void xt_add_system_dir(size_t size, char *path);
1080 void xt_add_data_dir(size_t size, char *path);
1081
1082@@ -244,4 +250,6 @@
1083 }
1084 }
1085
1086+extern XTDatabaseHPtr pbxt_database; // The global open database
1087+
1088 #endif
1089
1090=== modified file 'storage/pbxt/src/datadic_xt.cc'
1091--- storage/pbxt/src/datadic_xt.cc 2009-08-18 07:46:53 +0000
1092+++ storage/pbxt/src/datadic_xt.cc 2009-12-10 11:48:17 +0000
1093@@ -35,7 +35,7 @@
1094
1095 #ifdef DEBUG
1096 #ifdef DRIZZLED
1097-#include <drizzled/common_includes.h>
1098+//#include <drizzled/common_includes.h>
1099 #else
1100 #include "mysql_priv.h"
1101 #endif
1102@@ -437,11 +437,6 @@
1103 XTToken *nextToken(XTThreadPtr self, c_char *keyword, XTToken *tk);
1104 };
1105
1106-void ri_free_token(XTThreadPtr XT_UNUSED(self), XTToken *tk)
1107-{
1108- delete tk;
1109-}
1110-
1111 XTToken *XTTokenizer::newToken(XTThreadPtr self, u_int type, char *start, char *end)
1112 {
1113 if (!tkn_current) {
1114
1115=== modified file 'storage/pbxt/src/datalog_xt.cc'
1116--- storage/pbxt/src/datalog_xt.cc 2009-09-04 07:29:34 +0000
1117+++ storage/pbxt/src/datalog_xt.cc 2009-12-10 11:48:17 +0000
1118@@ -410,7 +410,7 @@
1119 ASSERT_NS(seq_read.sl_log_eof == seq_read.sl_rec_log_offset);
1120 data_log->dlf_log_eof = seq_read.sl_rec_log_offset;
1121
1122- if ((size_t) data_log->dlf_log_eof < sizeof(XTXactLogHeaderDRec)) {
1123+ if (data_log->dlf_log_eof < (off_t) sizeof(XTXactLogHeaderDRec)) {
1124 data_log->dlf_log_eof = sizeof(XTXactLogHeaderDRec);
1125 if (!dl_create_log_header(data_log, seq_read.sl_log_file, self))
1126 xt_throw(self);
1127@@ -1162,7 +1162,7 @@
1128 /* When I use 'thread' instead of 'self', this means
1129 * that I will not throw an error.
1130 */
1131-xtBool XTDataLogBuffer::dlb_get_log_offset(xtLogID *log_id, xtLogOffset *out_offset, size_t req_size, struct XTThread *thread)
1132+xtBool XTDataLogBuffer::dlb_get_log_offset(xtLogID *log_id, xtLogOffset *out_offset, size_t XT_UNUSED(req_size), struct XTThread *thread)
1133 {
1134 /* Note, I am allowing a log to grow beyond the threshold.
1135 * The amount depends on the maximum extended record size.
1136@@ -1757,7 +1757,7 @@
1137 freer_(); // xt_unlock_mutex(&db->db_co_dlog_lock)
1138
1139 /* Flush the transaction log. */
1140- if (!xt_xlog_flush_log(self))
1141+ if (!xt_xlog_flush_log(db, self))
1142 xt_throw(self);
1143
1144 xt_lock_mutex_ns(&db->db_datalogs.dlc_head_lock);
1145@@ -1891,7 +1891,7 @@
1146 freer_(); // xt_unlock_mutex(&db->db_co_dlog_lock)
1147
1148 /* Flush the transaction log. */
1149- if (!xt_xlog_flush_log(self))
1150+ if (!xt_xlog_flush_log(db, self))
1151 xt_throw(self);
1152
1153 /* Save state in source log header. */
1154
1155=== modified file 'storage/pbxt/src/discover_xt.cc'
1156--- storage/pbxt/src/discover_xt.cc 2009-12-03 11:19:05 +0000
1157+++ storage/pbxt/src/discover_xt.cc 2009-12-10 11:48:17 +0000
1158@@ -31,6 +31,9 @@
1159 #include <drizzled/session.h>
1160 #include <drizzled/server_includes.h>
1161 #include <drizzled/sql_base.h>
1162+#include <drizzled/statement/alter_table.h>
1163+#include <algorithm>
1164+#include <sstream>
1165 #endif
1166
1167 #include "strutil_xt.h"
1168@@ -39,18 +42,273 @@
1169 #include "ha_xtsys.h"
1170
1171 #ifndef DRIZZLED
1172-#if MYSQL_VERSION_ID > 60005
1173+#if MYSQL_VERSION_ID >= 50404
1174 #define DOT_STR(x) x.str
1175 #else
1176 #define DOT_STR(x) x
1177 #endif
1178 #endif
1179
1180-#ifndef DRIZZLED
1181+//#ifndef DRIZZLED
1182 #define LOCK_OPEN_HACK_REQUIRED
1183-#endif // DRIZZLED
1184+//#endif // DRIZZLED
1185
1186 #ifdef LOCK_OPEN_HACK_REQUIRED
1187+#ifdef DRIZZLED
1188+
1189+using namespace drizzled;
1190+using namespace std;
1191+
1192+#define mysql_create_table_no_lock hacked_mysql_create_table_no_lock
1193+
1194+namespace drizzled {
1195+
1196+int rea_create_table(Session *session, const char *path,
1197+ const char *db, const char *table_name,
1198+ message::Table *table_proto,
1199+ HA_CREATE_INFO *create_info,
1200+ List<CreateField> &create_field,
1201+ uint32_t key_count,KEY *key_info);
1202+}
1203+
1204+static uint32_t build_tmptable_filename(Session* session,
1205+ char *buff, size_t bufflen)
1206+{
1207+ uint32_t length;
1208+ ostringstream path_str, post_tmpdir_str;
1209+ string tmp;
1210+
1211+ path_str << drizzle_tmpdir;
1212+ post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
1213+ post_tmpdir_str << session->thread_id << session->tmp_table++;
1214+ tmp= post_tmpdir_str.str();
1215+
1216+ transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
1217+
1218+ path_str << tmp;
1219+
1220+ if (bufflen < path_str.str().length())
1221+ length= 0;
1222+ else
1223+ length= unpack_filename(buff, path_str.str().c_str());
1224+
1225+ return length;
1226+}
1227+
1228+static bool mysql_create_table_no_lock(Session *session,
1229+ const char *db, const char *table_name,
1230+ HA_CREATE_INFO *create_info,
1231+ message::Table *table_proto,
1232+ AlterInfo *alter_info,
1233+ bool internal_tmp_table,
1234+ uint32_t select_field_count)
1235+{
1236+ char path[FN_REFLEN];
1237+ uint32_t path_length;
1238+ uint db_options, key_count;
1239+ KEY *key_info_buffer;
1240+ Cursor *file;
1241+ bool error= true;
1242+ /* Check for duplicate fields and check type of table to create */
1243+ if (!alter_info->create_list.elements)
1244+ {
1245+ my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1246+ MYF(0));
1247+ return true;
1248+ }
1249+ assert(strcmp(table_name,table_proto->name().c_str())==0);
1250+ if (check_engine(session, table_name, create_info))
1251+ return true;
1252+ db_options= create_info->table_options;
1253+ if (create_info->row_type == ROW_TYPE_DYNAMIC)
1254+ db_options|=HA_OPTION_PACK_RECORD;
1255+
1256+ /*if (!(file= create_info->db_type->getCursor((TableShare*) 0, session->mem_root)))
1257+ {
1258+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
1259+ return true;
1260+ }*/
1261+
1262+ /* PMC - Done to avoid getting the partition handler by mistake! */
1263+ if (!(file= new (session->mem_root) ha_xtsys(pbxt_hton, NULL)))
1264+ {
1265+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
1266+ return true;
1267+ }
1268+
1269+ set_table_default_charset(create_info, (char*) db);
1270+
1271+ if (mysql_prepare_create_table(session,
1272+ create_info,
1273+ table_proto,
1274+ alter_info,
1275+ internal_tmp_table,
1276+ &db_options, file,
1277+ &key_info_buffer, &key_count,
1278+ select_field_count))
1279+ goto err;
1280+
1281+ /* Check if table exists */
1282+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1283+ {
1284+ path_length= build_tmptable_filename(session, path, sizeof(path));
1285+ }
1286+ else
1287+ {
1288+ #ifdef FN_DEVCHAR
1289+ /* check if the table name contains FN_DEVCHAR when defined */
1290+ if (strchr(table_name, FN_DEVCHAR))
1291+ {
1292+ my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
1293+ return true;
1294+ }
1295+#endif
1296+ path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
1297+ }
1298+
1299+ /* Check if table already exists */
1300+ if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1301+ session->find_temporary_table(db, table_name))
1302+ {
1303+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1304+ {
1305+ create_info->table_existed= 1; // Mark that table existed
1306+ push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1307+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1308+ table_name);
1309+ error= 0;
1310+ goto err;
1311+ }
1312+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1313+ goto err;
1314+ }
1315+
1316+ //pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1317+ if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1318+ {
1319+ if (plugin::StorageEngine::getTableDefinition(*session,
1320+ path,
1321+ db,
1322+ table_name,
1323+ internal_tmp_table) == EEXIST)
1324+ {
1325+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1326+ {
1327+ error= false;
1328+ push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1329+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1330+ table_name);
1331+ create_info->table_existed= 1; // Mark that table existed
1332+ }
1333+ else
1334+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1335+
1336+ goto unlock_and_end;
1337+ }
1338+ /*
1339+ * We don't assert here, but check the result, because the table could be
1340+ * in the table definition cache and in the same time the .frm could be
1341+ * missing from the disk, in case of manual intervention which deletes
1342+ * the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1343+ * Then she could create the table. This case is pretty obscure and
1344+ * therefore we don't introduce a new error message only for it.
1345+ * */
1346+ if (TableShare::getShare(db, table_name))
1347+ {
1348+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1349+ goto unlock_and_end;
1350+ }
1351+ }
1352+ /*
1353+ * Check that table with given name does not already
1354+ * exist in any storage engine. In such a case it should
1355+ * be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1356+ * unless user specified CREATE TABLE IF EXISTS
1357+ * The LOCK_open mutex has been locked to make sure no
1358+ * one else is attempting to discover the table. Since
1359+ * it's not on disk as a frm file, no one could be using it!
1360+ * */
1361+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1362+ {
1363+ bool create_if_not_exists =
1364+ create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1365+
1366+ char table_path[FN_REFLEN];
1367+ uint32_t table_path_length;
1368+
1369+ table_path_length= build_table_filename(table_path, sizeof(table_path),
1370+ db, table_name, false);
1371+
1372+ int retcode= plugin::StorageEngine::getTableDefinition(*session,
1373+ table_path,
1374+ db,
1375+ table_name,
1376+ false);
1377+ switch (retcode)
1378+ {
1379+ case ENOENT:
1380+ /* Normal case, no table exists. we can go and create it */
1381+ break;
1382+ case EEXIST:
1383+ if (create_if_not_exists)
1384+ {
1385+ error= false;
1386+ push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1387+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1388+ table_name);
1389+ create_info->table_existed= 1; // Mark that table existed
1390+ goto unlock_and_end;
1391+ }
1392+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1393+ goto unlock_and_end;
1394+ default:
1395+ my_error(retcode, MYF(0),table_name);
1396+ goto unlock_and_end;
1397+ }
1398+ }
1399+
1400+ session->set_proc_info("creating table");
1401+ create_info->table_existed= 0; // Mark that table is created
1402+
1403+ create_info->table_options=db_options;
1404+
1405+ if (rea_create_table(session, path, db, table_name,
1406+ table_proto,
1407+ create_info, alter_info->create_list,
1408+ key_count, key_info_buffer))
1409+ goto unlock_and_end;
1410+
1411+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1412+ {
1413+ /* Open table and put in temporary table list */
1414+ if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
1415+ {
1416+ (void) session->rm_temporary_table(create_info->db_type, path);
1417+ goto unlock_and_end;
1418+ }
1419+ }
1420+
1421+ /*
1422+ * Don't write statement if:
1423+ * - It is an internal temporary table,
1424+ * - Row-based logging is used and it we are creating a temporary table, or
1425+ * - The binary log is not open.
1426+ * Otherwise, the statement shall be binlogged.
1427+ * */
1428+ if (!internal_tmp_table &&
1429+ ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1430+ write_bin_log(session, session->query, session->query_length);
1431+ error= false;
1432+unlock_and_end:
1433+ //pthread_mutex_unlock(&LOCK_open);
1434+
1435+err:
1436+ session->set_proc_info("After create");
1437+ delete file;
1438+ return(error);
1439+}
1440+
1441+#else // MySQL case
1442 ///////////////////////////////
1443 /*
1444 * Unfortunately I cannot use the standard mysql_create_table_no_lock() because it will lock "LOCK_open"
1445@@ -1229,13 +1487,13 @@
1446 if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1447 {
1448 /* Open table and put in temporary table list */
1449-#if MYSQL_VERSION_ID > 60005
1450+#if MYSQL_VERSION_ID >= 50404
1451 if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1452 #else
1453 if (!(open_temporary_table(thd, path, db, table_name, 1)))
1454 #endif
1455 {
1456-#if MYSQL_VERSION_ID > 60005
1457+#if MYSQL_VERSION_ID >= 50404
1458 (void) rm_temporary_table(create_info->db_type, path, false);
1459 #else
1460 (void) rm_temporary_table(create_info->db_type, path);
1461@@ -1252,11 +1510,25 @@
1462 - The binary log is not open.
1463 Otherwise, the statement shall be binlogged.
1464 */
1465+ /* PBXT 1.0.09e
1466+ * Firstly we had a compile problem with MySQL 5.1.42 and
1467+ * the write_bin_log() call below:
1468+ * discover_xt.cc:1259: error: argument of type 'char* (Statement::)()' does not match 'const char*'
1469+ *
1470+ * And secondly, we should no write the BINLOG anyway because this is
1471+ * an internal PBXT system table.
1472+ *
1473+ * So I am just commenting out the code altogether.
1474 if (!internal_tmp_table &&
1475 (!thd->current_stmt_binlog_row_based ||
1476 (thd->current_stmt_binlog_row_based &&
1477 !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1478+<<<<<<< TREE
1479 write_bin_log(thd, TRUE, thd->query(), thd->query_length());
1480+=======
1481+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
1482+ */
1483+>>>>>>> MERGE-SOURCE
1484 error= FALSE;
1485 unlock_and_end:
1486 pthread_mutex_unlock(&LOCK_open);
1487@@ -1279,37 +1551,51 @@
1488 ////// END OF CUT AND PASTES FROM sql_table.cc ////////
1489 ////////////////////////////////////////////////////////
1490
1491+#endif // DRIZZLED
1492 #endif // LOCK_OPEN_HACK_REQUIRED
1493
1494 //------------------------------
1495 int xt_create_table_frm(handlerton *hton, THD* thd, const char *db, const char *name, DT_FIELD_INFO *info, DT_KEY_INFO *XT_UNUSED(keys), xtBool skip_existing)
1496 {
1497 #ifdef DRIZZLED
1498- drizzled::message::Table table_proto;
1499+#define MYLEX_CREATE_INFO create_info
1500+#else
1501+#define MYLEX_CREATE_INFO mylex.create_info
1502+#endif
1503+
1504+#ifdef DRIZZLED
1505+ drizzled::statement::AlterTable *stmt = new drizzled::statement::AlterTable(thd);
1506+ HA_CREATE_INFO create_info;
1507+ //AlterInfo alter_info;
1508+ drizzled::message::Table table_proto;
1509
1510 static const char *ext = ".dfe";
1511 static const int ext_len = 4;
1512+
1513+ table_proto.mutable_engine()->mutable_name()->assign("PBXT");
1514 #else
1515 static const char *ext = ".frm";
1516 static const int ext_len = 4;
1517 #endif
1518 int err = 1;
1519- //HA_CREATE_INFO create_info = {0};
1520- //Alter_info alter_info;
1521 char field_length_buffer[12], *field_length_ptr;
1522 LEX *save_lex= thd->lex, mylex;
1523-
1524- memset(&mylex.create_info, 0, sizeof(HA_CREATE_INFO));
1525+
1526+ memset(&MYLEX_CREATE_INFO, 0, sizeof(HA_CREATE_INFO));
1527
1528 thd->lex = &mylex;
1529- lex_start(thd);
1530+ lex_start(thd);
1531+#ifdef DRIZZLED
1532+ mylex.statement = stmt;
1533+#endif
1534
1535 /* setup the create info */
1536- mylex.create_info.db_type = hton;
1537+ MYLEX_CREATE_INFO.db_type = hton;
1538+
1539 #ifndef DRIZZLED
1540 mylex.create_info.frm_only = 1;
1541 #endif
1542- mylex.create_info.default_table_charset = system_charset_info;
1543+ MYLEX_CREATE_INFO.default_table_charset = system_charset_info;
1544
1545 /* setup the column info. */
1546 while (info->field_name) {
1547@@ -1335,7 +1621,7 @@
1548 #else
1549 if (add_field_to_list(thd, &field_name, info->field_type, field_length_ptr, info->field_decimal_length,
1550 info->field_flags,
1551-#if MYSQL_VERSION_ID > 60005
1552+#if MYSQL_VERSION_ID >= 50404
1553 HA_SM_DISK,
1554 COLUMN_FORMAT_TYPE_FIXED,
1555 #endif
1556@@ -1369,7 +1655,7 @@
1557 table_proto.set_name(name);
1558 table_proto.set_type(drizzled::message::Table::STANDARD);
1559
1560- if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &table_proto, &mylex.alter_info, 1, 0, false))
1561+ if (mysql_create_table_no_lock(thd, db, name, &create_info, &table_proto, &stmt->alter_info, 1, 0))
1562 goto error;
1563 #else
1564 if (mysql_create_table_no_lock(thd, db, name, &mylex.create_info, &mylex.alter_info, 1, 0))
1565
1566=== modified file 'storage/pbxt/src/filesys_xt.cc'
1567--- storage/pbxt/src/filesys_xt.cc 2009-09-03 06:15:03 +0000
1568+++ storage/pbxt/src/filesys_xt.cc 2009-12-10 11:48:17 +0000
1569@@ -56,6 +56,8 @@
1570 //#define DEBUG_TRACE_FILES
1571 //#define INJECT_WRITE_REMAP_ERROR
1572 /* This is required to make testing on the Mac faster: */
1573+/* It turns of full file sync. */
1574+#define DEBUG_FAST_MAC
1575 #endif
1576
1577 #ifdef DEBUG_TRACE_FILES
1578@@ -63,10 +65,6 @@
1579 #define PRINTF xt_trace
1580 #endif
1581
1582-#if defined(XT_MAC) && defined(F_FULLFSYNC)
1583-#undef F_FULLFSYNC
1584-#endif
1585-
1586 #ifdef INJECT_WRITE_REMAP_ERROR
1587 #define INJECT_REMAP_FILE_SIZE 1000000
1588 #define INJECT_REMAP_FILE_TYPE "xtd"
1589@@ -883,7 +881,7 @@
1590 * fsync didn't really flush index pages to disk. fcntl(F_FULLFSYNC) is considered more effective
1591 * in such case.
1592 */
1593-#ifdef F_FULLFSYNC
1594+#if defined(F_FULLFSYNC) && !defined(DEBUG_FAST_MAC)
1595 if (fcntl(of->of_filedes, F_FULLFSYNC, 0) == -1) {
1596 xt_register_ferrno(XT_REG_CONTEXT, errno, xt_file_path(of));
1597 goto failed;
1598
1599=== modified file 'storage/pbxt/src/filesys_xt.h'
1600--- storage/pbxt/src/filesys_xt.h 2009-08-17 11:12:36 +0000
1601+++ storage/pbxt/src/filesys_xt.h 2009-12-10 11:48:17 +0000
1602@@ -102,7 +102,7 @@
1603 #define FILE_MAP_UNLOCK(i, o) xt_xsmutex_unlock(i, o)
1604 #elif defined(FILE_MAP_USE_PTHREAD_RW)
1605 #define FILE_MAP_LOCK_TYPE xt_rwlock_type
1606-#define FILE_MAP_INIT_LOCK(s, i) xt_init_rwlock(s, i)
1607+#define FILE_MAP_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i)
1608 #define FILE_MAP_FREE_LOCK(s, i) xt_free_rwlock(i)
1609 #define FILE_MAP_READ_LOCK(i, o) xt_slock_rwlock_ns(i)
1610 #define FILE_MAP_WRITE_LOCK(i, o) xt_xlock_rwlock_ns(i)
1611
1612=== modified file 'storage/pbxt/src/ha_pbxt.cc'
1613--- storage/pbxt/src/ha_pbxt.cc 2009-09-03 06:15:03 +0000
1614+++ storage/pbxt/src/ha_pbxt.cc 2009-12-10 11:48:17 +0000
1615@@ -35,6 +35,7 @@
1616
1617 #include <stdlib.h>
1618 #include <time.h>
1619+#include <ctype.h>
1620
1621 #ifdef DRIZZLED
1622 #include <drizzled/common.h>
1623@@ -42,14 +43,21 @@
1624 #include <mysys/my_alloc.h>
1625 #include <mysys/hash.h>
1626 #include <drizzled/field.h>
1627-#include <drizzled/current_session.h>
1628+#include <drizzled/session.h>
1629 #include <drizzled/data_home.h>
1630 #include <drizzled/error.h>
1631 #include <drizzled/table.h>
1632 #include <drizzled/field/timestamp.h>
1633 #include <drizzled/server_includes.h>
1634+#include <drizzled/plugin/info_schema_table.h>
1635 extern "C" char **session_query(Session *session);
1636 #define my_strdup(a,b) strdup(a)
1637+
1638+using drizzled::plugin::Registry;
1639+using drizzled::plugin::ColumnInfo;
1640+using drizzled::plugin::InfoSchemaTable;
1641+using drizzled::plugin::InfoSchemaMethods;
1642+
1643 #else
1644 #include "mysql_priv.h"
1645 #include <mysql/plugin.h>
1646@@ -71,7 +79,7 @@
1647 #include "tabcache_xt.h"
1648 #include "systab_xt.h"
1649 #include "xaction_xt.h"
1650-#include "restart_xt.h"
1651+#include "backup_xt.h"
1652
1653 #ifdef DEBUG
1654 //#define XT_USE_SYS_PAR_DEBUG_SIZES
1655@@ -101,6 +109,10 @@
1656 static int pbxt_close_connection(handlerton *hton, THD* thd);
1657 static int pbxt_commit(handlerton *hton, THD *thd, bool all);
1658 static int pbxt_rollback(handlerton *hton, THD *thd, bool all);
1659+static int pbxt_prepare(handlerton *hton, THD *thd, bool all);
1660+static int pbxt_recover(handlerton *hton, XID *xid_list, uint len);
1661+static int pbxt_commit_by_xid(handlerton *hton, XID *xid);
1662+static int pbxt_rollback_by_xid(handlerton *hton, XID *xid);
1663 #endif
1664 static void ha_aquire_exclusive_use(XTThreadPtr self, XTSharePtr share, ha_pbxt *mine);
1665 static void ha_release_exclusive_use(XTThreadPtr self, XTSharePtr share);
1666@@ -123,7 +135,9 @@
1667 #ifdef PBXT_HANDLER_TRACE
1668 #define PBXT_ALLOW_PRINTING
1669
1670-#define XT_TRACE_CALL() do { XTThreadPtr s = xt_get_self(); printf("%s %s\n", s ? s->t_name : "-unknown-", __FUNC__); } while (0)
1671+#define XT_TRACE_CALL() ha_trace_function(__FUNC__, NULL)
1672+#define XT_TRACE_METHOD() ha_trace_function(__FUNC__, pb_share->sh_table_path->ps_path)
1673+
1674 #ifdef PBXT_TRACE_RETURN
1675 #define XT_RETURN(x) do { printf("%d\n", (int) (x)); return (x); } while (0)
1676 #define XT_RETURN_VOID do { printf("out\n"); return; } while (0)
1677@@ -135,6 +149,7 @@
1678 #else
1679
1680 #define XT_TRACE_CALL()
1681+#define XT_TRACE_METHOD()
1682 #define XT_RETURN(x) return (x)
1683 #define XT_RETURN_VOID return
1684
1685@@ -165,10 +180,10 @@
1686 xtBool pbxt_crash_debug = FALSE;
1687 #endif
1688
1689+
1690 /* Variables for pbxt share methods */
1691 static xt_mutex_type pbxt_database_mutex; // Prevent a database from being opened while it is being dropped
1692 static XTHashTabPtr pbxt_share_tables; // Hash used to track open tables
1693-XTDatabaseHPtr pbxt_database = NULL; // The global open database
1694 static char *pbxt_index_cache_size;
1695 static char *pbxt_record_cache_size;
1696 static char *pbxt_log_cache_size;
1697@@ -180,6 +195,12 @@
1698 static char *pbxt_data_file_grow_size;
1699 static char *pbxt_row_file_grow_size;
1700 static int pbxt_max_threads;
1701+static my_bool pbxt_support_xa;
1702+
1703+#ifndef DRIZZLED
1704+// drizzle complains it's not used
1705+static XTXactEnumXARec pbxt_xa_enum;
1706+#endif
1707
1708 #ifdef DEBUG
1709 #define XT_SHARE_LOCK_WAIT 5000
1710@@ -259,6 +280,33 @@
1711 //#define XT_AUTO_INCREMENT_DEF 1
1712 #endif
1713
1714+#ifdef PBXT_HANDLER_TRACE
1715+static void ha_trace_function(const char *function, char *table)
1716+{
1717+ char func_buf[50], *ptr;
1718+ XTThreadPtr thread = xt_get_self();
1719+
1720+ if ((ptr = strchr(function, '('))) {
1721+ ptr--;
1722+ while (ptr > function) {
1723+ if (!(isalnum(*ptr) || *ptr == '_'))
1724+ break;
1725+ ptr--;
1726+ }
1727+ ptr++;
1728+ xt_strcpy(50, func_buf, ptr);
1729+ if ((ptr = strchr(func_buf, '(')))
1730+ *ptr = 0;
1731+ }
1732+ else
1733+ xt_strcpy(50, func_buf, function);
1734+ if (table)
1735+ printf("%s %s (%s)\n", thread ? thread->t_name : "-unknown-", func_buf, table);
1736+ else
1737+ printf("%s %s\n", thread ? thread->t_name : "-unknown-", func_buf);
1738+}
1739+#endif
1740+
1741 /*
1742 * -----------------------------------------------------------------------
1743 * SHARED TABLE DATA
1744@@ -584,6 +632,9 @@
1745 /* The first bit is 1. */
1746 static u_int ha_get_max_bit(MX_BITMAP *map)
1747 {
1748+#ifdef DRIZZLED
1749+ return map->getFirstSet();
1750+#else
1751 my_bitmap_map *data_ptr = map->bitmap;
1752 my_bitmap_map *end_ptr = map->last_word_ptr;
1753 my_bitmap_map b;
1754@@ -612,6 +663,7 @@
1755 cnt -= 32;
1756 }
1757 return 0;
1758+#endif
1759 }
1760
1761 /*
1762@@ -684,9 +736,10 @@
1763 return(-1); // Unknown error
1764 }
1765
1766-xtPublic int xt_ha_pbxt_thread_error_for_mysql(THD *XT_UNUSED(thd), const XTThreadPtr self, int ignore_dup_key)
1767+xtPublic int xt_ha_pbxt_thread_error_for_mysql(THD *thd, const XTThreadPtr self, int ignore_dup_key)
1768 {
1769- int xt_err = self->t_exception.e_xt_err;
1770+ int xt_err = self->t_exception.e_xt_err;
1771+ xtBool dup_key = FALSE;
1772
1773 XT_PRINT2(self, "xt_ha_pbxt_thread_error_for_mysql xt_err=%d auto commit=%d\n", (int) xt_err, (int) self->st_auto_commit);
1774 switch (xt_err) {
1775@@ -725,6 +778,7 @@
1776 /* If we are in auto-commit mode (and we are not ignoring
1777 * duplicate keys) then rollback the transaction automatically.
1778 */
1779+ dup_key = TRUE;
1780 if (!ignore_dup_key && self->st_auto_commit)
1781 goto abort_transaction;
1782 break;
1783@@ -790,26 +844,20 @@
1784 /* Locks are held on tables.
1785 * Only rollback after locks are released.
1786 */
1787- self->st_auto_commit = TRUE;
1788+ /* I do not think this is required, because
1789+ * I tell mysql to rollback below,
1790+ * besides it is a hack!
1791+ self->st_auto_commit = TRUE;
1792+ */
1793 self->st_abort_trans = TRUE;
1794 }
1795-#ifdef xxxx
1796-/* DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
1797- trans == &thd->transaction.stmt); in handler.cc now
1798- * fails, and I don't know if this function can be called anymore! */
1799- /* Cause any other DBs to do a rollback as well... */
1800- if (thd) {
1801- /*
1802- * GOTCHA:
1803- * This is a BUG in MySQL. I cannot rollback a transaction if
1804- * pb_mysql_thd->in_sub_stmt! But I must....?!
1805- */
1806-#ifdef MYSQL_SERVER
1807- if (!thd->in_sub_stmt)
1808- ha_rollback(thd);
1809-#endif
1810+ /* Only tell MySQL to rollback if we automatically rollback.
1811+ * Note: calling this with (thd, FALSE), cause sp.test to fail.
1812+ */
1813+ if (!dup_key) {
1814+ if (thd)
1815+ thd_mark_transaction_to_rollback(thd, TRUE);
1816 }
1817-#endif
1818 }
1819 break;
1820 }
1821@@ -908,7 +956,11 @@
1822 xt_db_data_file_grow_size = (size_t) data_file_grow_size;
1823 xt_db_row_file_grow_size = (size_t) row_file_grow_size;
1824
1825+#ifdef DRIZZLED
1826+ pbxt_ignore_case = TRUE;
1827+#else
1828 pbxt_ignore_case = lower_case_table_names != 0;
1829+#endif
1830 if (pbxt_ignore_case)
1831 pbxt_share_tables = xt_new_hashtable(self, ha_hash_comp_ci, ha_hash_ci, ha_hash_free, TRUE, FALSE);
1832 else
1833@@ -968,7 +1020,7 @@
1834 */
1835 static void ha_exit(XTThreadPtr self)
1836 {
1837- xt_xres_wait_for_recovery(self);
1838+ xt_xres_terminate_recovery(self);
1839
1840 /* Wrap things up... */
1841 xt_unuse_database(self, self); /* Just in case the main thread has a database in use (for testing)? */
1842@@ -1024,7 +1076,7 @@
1843 cont_(a);
1844
1845 if (!not_ok) {
1846- if (stat_print(thd, "PBXT", 4, "", 0, strbuf.sb_cstring, strbuf.sb_len))
1847+ if (stat_print(thd, "PBXT", 4, "", 0, strbuf.sb_cstring, (uint) strbuf.sb_len))
1848 not_ok = TRUE;
1849 }
1850 xt_sb_set_size(self, &strbuf, 0);
1851@@ -1038,14 +1090,14 @@
1852 * return 1 on error, else 0.
1853 */
1854 #ifdef DRIZZLED
1855-static int pbxt_init(PluginRegistry &registry)
1856+static int pbxt_init(Registry &registry)
1857 #else
1858 static int pbxt_init(void *p)
1859 #endif
1860 {
1861 int init_err = 0;
1862
1863- XT_TRACE_CALL();
1864+ XT_PRINT0(NULL, "pbxt_init\n");
1865
1866 if (sizeof(xtWordPS) != sizeof(void *)) {
1867 printf("PBXT: This won't work, I require that sizeof(xtWordPS) == sizeof(void *)!\n");
1868@@ -1076,11 +1128,27 @@
1869 pbxt_hton->close_connection = pbxt_close_connection; /* close_connection, cleanup thread related data. */
1870 pbxt_hton->commit = pbxt_commit; /* commit */
1871 pbxt_hton->rollback = pbxt_rollback; /* rollback */
1872+ if (pbxt_support_xa) {
1873+ pbxt_hton->prepare = pbxt_prepare;
1874+ pbxt_hton->recover = pbxt_recover;
1875+ pbxt_hton->commit_by_xid = pbxt_commit_by_xid;
1876+ pbxt_hton->rollback_by_xid = pbxt_rollback_by_xid;
1877+ }
1878+ else {
1879+ pbxt_hton->prepare = NULL;
1880+ pbxt_hton->recover = NULL;
1881+ pbxt_hton->commit_by_xid = NULL;
1882+ pbxt_hton->rollback_by_xid = NULL;
1883+ }
1884 pbxt_hton->create = pbxt_create_handler; /* Create a new handler */
1885 pbxt_hton->drop_database = pbxt_drop_database; /* Drop a database */
1886 pbxt_hton->panic = pbxt_panic; /* Panic call */
1887 pbxt_hton->show_status = pbxt_show_status;
1888 pbxt_hton->flags = HTON_NO_FLAGS; /* HTON_CAN_RECREATE - Without this flags TRUNCATE uses delete_all_rows() */
1889+ pbxt_hton->slot = (uint)-1; /* assign invald value, so we know when it's inited later */
1890+#if defined(MYSQL_SUPPORTS_BACKUP) && defined(XT_ENABLE_ONLINE_BACKUP)
1891+ pbxt_hton->get_backup_engine = pbxt_backup_engine;
1892+#endif
1893 #endif
1894 if (!xt_init_logging()) /* Initialize logging */
1895 goto error_1;
1896@@ -1160,8 +1228,10 @@
1897 * Only real problem, 2 threads try to load the same
1898 * plugin at the same time.
1899 */
1900+#if MYSQL_VERSION_ID < 60014
1901 myxt_mutex_unlock(&LOCK_plugin);
1902 #endif
1903+#endif
1904
1905 /* Can't do this here yet, because I need a THD! */
1906 try_(b) {
1907@@ -1195,8 +1265,10 @@
1908 if (thd)
1909 myxt_destroy_thread(thd, FALSE);
1910 #ifndef DRIZZLED
1911+#if MYSQL_VERSION_ID < 60014
1912 myxt_mutex_lock(&LOCK_plugin);
1913 #endif
1914+#endif
1915 }
1916 #endif
1917 }
1918@@ -1262,7 +1334,7 @@
1919 }
1920
1921 #ifdef DRIZZLED
1922-static int pbxt_end(PluginRegistry &registry)
1923+static int pbxt_end(Registry &registry)
1924 #else
1925 static int pbxt_end(void *)
1926 #endif
1927@@ -1378,7 +1450,7 @@
1928 * transaction (!all && !self->st_auto_commit).
1929 */
1930 if (all || self->st_auto_commit) {
1931- XT_PRINT0(self, "xt_xn_commit\n");
1932+ XT_PRINT0(self, "xt_xn_commit in pbxt_commit\n");
1933
1934 if (!xt_xn_commit(self))
1935 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
1936@@ -1402,7 +1474,7 @@
1937 XTThreadPtr self;
1938
1939 if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) {
1940- XT_PRINT1(self, "pbxt_rollback all=%d\n", all);
1941+ XT_PRINT1(self, "pbxt_rollback all=%d in pbxt_commit\n", all);
1942
1943 if (self->st_xact_data) {
1944 /* There are no table locks, rollback immediately in all cases
1945@@ -1431,7 +1503,7 @@
1946 }
1947
1948 #ifdef DRIZZLED
1949-handler *PBXTStorageEngine::create(TABLE_SHARE *table, MEM_ROOT *mem_root)
1950+Cursor *PBXTStorageEngine::create(TABLE_SHARE *table, MEM_ROOT *mem_root)
1951 {
1952 PBXTStorageEngine * const hton = this;
1953 #else
1954@@ -1446,6 +1518,182 @@
1955
1956 /*
1957 * -----------------------------------------------------------------------
1958+ * 2-PHASE COMMIT
1959+ *
1960+ */
1961+
1962+#ifndef DRIZZLED
1963+
1964+static int pbxt_prepare(handlerton *hton, THD *thd, bool all)
1965+{
1966+ int err = 0;
1967+ XTThreadPtr self;
1968+
1969+ XT_TRACE_CALL();
1970+ if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) {
1971+ XT_PRINT1(self, "pbxt_commit all=%d\n", all);
1972+
1973+ if (self->st_xact_data) {
1974+ /* There are no table locks, commit immediately in all cases
1975+ * except when this is a statement commit with an explicit
1976+ * transaction (!all && !self->st_auto_commit).
1977+ */
1978+ if (all) {
1979+ XID xid;
1980+
1981+ XT_PRINT0(self, "xt_xn_prepare in pbxt_prepare\n");
1982+ thd_get_xid(thd, (MYSQL_XID*) &xid);
1983+
1984+ if (!xt_xn_prepare(xid.length(), (xtWord1 *) &xid, self))
1985+ err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
1986+ }
1987+ }
1988+ }
1989+ return err;
1990+}
1991+
1992+static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, char *thread_name, int *err)
1993+{
1994+ THD *thd;
1995+ XTThreadPtr self = NULL;
1996+
1997+ *temp_thread = 0;
1998+ if ((thd = current_thd))
1999+ self = (XTThreadPtr) *thd_ha_data(thd, hton);
2000+ else {
2001+ //thd = (THD *) myxt_create_thread();
2002+ //*temp_thread |= 2;
2003+ }
2004+
2005+ if (!self) {
2006+ XTExceptionRec e;
2007+
2008+ if (!(self = xt_create_thread(thread_name, FALSE, TRUE, &e))) {
2009+ *err = xt_ha_pbxt_to_mysql_error(e.e_xt_err);
2010+ xt_log_exception(NULL, &e, XT_LOG_DEFAULT);
2011+ return NULL;
2012+ }
2013+ *temp_thread |= 1;
2014+ }
2015+
2016+ xt_xres_wait_for_recovery(self, XT_RECOVER_DONE);
2017+
2018+ try_(a) {
2019+ xt_open_database(self, mysql_real_data_home, TRUE);
2020+ }
2021+ catch_(a) {
2022+ *err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
2023+ if ((*temp_thread & 1))
2024+ xt_free_thread(self);
2025+ if (*temp_thread & 2)
2026+ myxt_destroy_thread(thd, FALSE);
2027+ self = NULL;
2028+ }
2029+ cont_(a);
2030+
2031+ *ret_thd = thd;
2032+ return self;
2033+}
2034+
2035+static void ha_temp_close_database(XTThreadPtr self, THD *thd, int temp_thread)
2036+{
2037+ xt_unuse_database(self, self);
2038+ if (temp_thread & 1)
2039+ xt_free_thread(self);
2040+ if (temp_thread & 2)
2041+ myxt_destroy_thread(thd, TRUE);
2042+}
2043+
2044+/* Return all prepared transactions, found during recovery.
2045+ * This function returns a count. If len is returned, the
2046+ * function will be called again.
2047+ */
2048+static int pbxt_recover(handlerton *hton, XID *xid_list, uint len)
2049+{
2050+ xtBool temp_thread;
2051+ XTThreadPtr self;
2052+ XTDatabaseHPtr db;
2053+ uint count = 0;
2054+ XTXactPreparePtr xap;
2055+ int err;
2056+ THD *thd;
2057+
2058+ if (!(self = ha_temp_open_global_database(hton, &thd, &temp_thread, "TempForRecover", &err)))
2059+ return 0;
2060+
2061+ db = self->st_database;
2062+
2063+ for (count=0; count<len; count++) {
2064+ xap = xt_xn_enum_xa_data(db, &pbxt_xa_enum);
2065+ if (!xap)
2066+ break;
2067+ memcpy(&xid_list[count], xap->xp_xa_data, xap->xp_data_len);
2068+ }
2069+
2070+ ha_temp_close_database(self, thd, temp_thread);
2071+ return (int) count;
2072+}
2073+
2074+static int pbxt_commit_by_xid(handlerton *hton, XID *xid)
2075+{
2076+ xtBool temp_thread;
2077+ XTThreadPtr self;
2078+ XTDatabaseHPtr db;
2079+ int err = 0;
2080+ XTXactPreparePtr xap;
2081+ THD *thd;
2082+
2083+ XT_TRACE_CALL();
2084+
2085+ if (!(self = ha_temp_open_global_database(hton, &thd, &temp_thread, "TempForCommitXA", &err)))
2086+ return err;
2087+ db = self->st_database;
2088+
2089+ if ((xap = xt_xn_find_xa_data(db, xid->length(), (xtWord1 *) xid, TRUE, self))) {
2090+ if ((self->st_xact_data = xt_xn_get_xact(db, xap->xp_xact_id, self))) {
2091+ self->st_xact_data->xd_flags &= ~XT_XN_XAC_PREPARED; // Prepared transactions cannot be swept!
2092+ if (!xt_xn_commit(self))
2093+ err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
2094+ }
2095+ xt_xn_delete_xa_data(db, xap, TRUE, self);
2096+ }
2097+
2098+ ha_temp_close_database(self, thd, temp_thread);
2099+ return 0;
2100+}
2101+
2102+static int pbxt_rollback_by_xid(handlerton *hton, XID *xid)
2103+{
2104+ int temp_thread;
2105+ XTThreadPtr self;
2106+ XTDatabaseHPtr db;
2107+ int err = 0;
2108+ XTXactPreparePtr xap;
2109+ THD *thd;
2110+
2111+ XT_TRACE_CALL();
2112+
2113+ if (!(self = ha_temp_open_global_database(hton, &thd, &temp_thread, "TempForRollbackXA", &err)))
2114+ return err;
2115+ db = self->st_database;
2116+
2117+ if ((xap = xt_xn_find_xa_data(db, xid->length(), (xtWord1 *) xid, TRUE, self))) {
2118+ if ((self->st_xact_data = xt_xn_get_xact(db, xap->xp_xact_id, self))) {
2119+ self->st_xact_data->xd_flags &= ~XT_XN_XAC_PREPARED; // Prepared transactions cannot be swept!
2120+ if (!xt_xn_rollback(self))
2121+ err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
2122+ }
2123+ xt_xn_delete_xa_data(db, xap, TRUE, self);
2124+ }
2125+
2126+ ha_temp_close_database(self, thd, temp_thread);
2127+ return 0;
2128+}
2129+
2130+#endif
2131+
2132+/*
2133+ * -----------------------------------------------------------------------
2134 * HANDLER LOCKING FUNCTIONS
2135 *
2136 * These functions are used get a lock on all handles of a particular table.
2137@@ -1497,7 +1745,7 @@
2138 ha_pbxt *handler;
2139 time_t end_time = time(NULL) + XT_SHARE_LOCK_TIMEOUT / 1000;
2140
2141- XT_PRINT1(self, "ha_aquire_exclusive_use %s PBXT X lock\n", share->sh_table_path->ps_path);
2142+ XT_PRINT1(self, "ha_aquire_exclusive_use (%s) PBXT X lock\n", share->sh_table_path->ps_path);
2143 /* GOTCHA: It is possible to hang here, if you hold
2144 * onto the sh_ex_mutex lock, before we really
2145 * have the exclusive lock (i.e. before all
2146@@ -1578,7 +1826,7 @@
2147 static void ha_release_exclusive_use(XTThreadPtr XT_UNUSED(self), XTSharePtr share)
2148 #endif
2149 {
2150- XT_PRINT1(self, "ha_release_exclusive_use %s PBXT X UNLOCK\n", share->sh_table_path->ps_path);
2151+ XT_PRINT1(self, "ha_release_exclusive_use (%s) PBXT X UNLOCK\n", share->sh_table_path->ps_path);
2152 xt_lock_mutex_ns((xt_mutex_type *) share->sh_ex_mutex);
2153 share->sh_table_lock = FALSE;
2154 xt_broadcast_cond_ns((xt_cond_type *) share->sh_ex_cond);
2155@@ -1589,7 +1837,7 @@
2156 {
2157 time_t end_time = time(NULL) + XT_SHARE_LOCK_TIMEOUT / 1000;
2158
2159- XT_PRINT1(xt_get_self(), "ha_wait_for_shared_use %s share lock wait...\n", share->sh_table_path->ps_path);
2160+ XT_PRINT1(xt_get_self(), "ha_wait_for_shared_use (%s) share lock wait...\n", share->sh_table_path->ps_path);
2161 mine->pb_ex_in_use = 0;
2162 xt_lock_mutex_ns((xt_mutex_type *) share->sh_ex_mutex);
2163 while (share->sh_table_lock) {
2164@@ -1667,14 +1915,38 @@
2165 *
2166 */
2167
2168-int pbxt_statistics_fill_table(THD *thd, TABLE_LIST *tables, COND *cond)
2169+static int pbxt_statistics_fill_table(THD *thd, TABLE_LIST *tables, COND *cond)
2170 {
2171- XTThreadPtr self;
2172+ XTThreadPtr self = NULL;
2173 int err = 0;
2174
2175+ if (!pbxt_hton) {
2176+ /* Can't do if PBXT is not loaded! */
2177+ XTExceptionRec e;
2178+
2179+ xt_exception_xterr(&e, XT_CONTEXT, XT_ERR_PBXT_NOT_INSTALLED);
2180+ xt_log_exception(NULL, &e, XT_LOG_DEFAULT);
2181+ /* Just return an empty set: */
2182+ return 0;
2183+ }
2184+
2185 if (!(self = ha_set_current_thread(thd, &err)))
2186 return xt_ha_pbxt_to_mysql_error(err);
2187+
2188+
2189 try_(a) {
2190+ /* If the thread has no open database, and the global
2191+ * database is already open, then open
2192+ * the database. Otherwise the statement will be
2193+ * executed without an open database, which means
2194+ * that the related statistics will be missing.
2195+ *
2196+ * This includes all background threads.
2197+ */
2198+ if (!self->st_database && pbxt_database) {
2199+ xt_ha_open_database_of_table(self, (XTPathStrPtr) NULL);
2200+ }
2201+
2202 err = myxt_statistics_fill_table(self, thd, tables, cond, system_charset_info);
2203 }
2204 catch_(a) {
2205@@ -1684,6 +1956,24 @@
2206 return err;
2207 }
2208
2209+#ifdef DRIZZLED
2210+ColumnInfo pbxt_statistics_fields_info[]=
2211+{
2212+ ColumnInfo("ID", 4, MYSQL_TYPE_LONG, 0, 0, "The ID of the statistic", SKIP_OPEN_TABLE),
2213+ ColumnInfo("Name", 40, MYSQL_TYPE_STRING, 0, 0, "The name of the statistic", SKIP_OPEN_TABLE),
2214+ ColumnInfo("Value", 8, MYSQL_TYPE_LONGLONG, 0, 0, "The accumulated value", SKIP_OPEN_TABLE),
2215+ ColumnInfo()
2216+};
2217+
2218+class PBXTStatisticsMethods : public InfoSchemaMethods
2219+{
2220+public:
2221+ int fillTable(Session *session, TableList *tables, COND *cond)
2222+ {
2223+ return pbxt_statistics_fill_table(session, tables, cond);
2224+ }
2225+};
2226+#else
2227 ST_FIELD_INFO pbxt_statistics_fields_info[]=
2228 {
2229 { "ID", 4, MYSQL_TYPE_LONG, 0, 0, "The ID of the statistic", SKIP_OPEN_TABLE},
2230@@ -1691,24 +1981,28 @@
2231 { "Value", 8, MYSQL_TYPE_LONGLONG, 0, 0, "The accumulated value", SKIP_OPEN_TABLE},
2232 { 0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2233 };
2234+#endif
2235
2236 #ifdef DRIZZLED
2237 static InfoSchemaTable *pbxt_statistics_table;
2238-
2239-int pbxt_init_statitics(PluginRegistry &registry)
2240+static PBXTStatisticsMethods pbxt_statistics_methods;
2241+static int pbxt_init_statistics(Registry &registry)
2242 #else
2243-int pbxt_init_statitics(void *p)
2244+static int pbxt_init_statistics(void *p)
2245 #endif
2246 {
2247 #ifdef DRIZZLED
2248- pbxt_statistics_table = (InfoSchemaTable *)xt_calloc_ns(sizeof(InfoSchemaTable));
2249- pbxt_statistics_table->table_name= "PBXT_STATISTICS";
2250+ //pbxt_statistics_table = (InfoSchemaTable *)xt_calloc_ns(sizeof(InfoSchemaTable));
2251+ //pbxt_statistics_table->table_name= "PBXT_STATISTICS";
2252+ pbxt_statistics_table = new InfoSchemaTable("PBXT_STATISTICS");
2253+ pbxt_statistics_table->setColumnInfo(pbxt_statistics_fields_info);
2254+ pbxt_statistics_table->setInfoSchemaMethods(&pbxt_statistics_methods);
2255 registry.add(pbxt_statistics_table);
2256 #else
2257 ST_SCHEMA_TABLE *pbxt_statistics_table = (ST_SCHEMA_TABLE *) p;
2258-#endif
2259 pbxt_statistics_table->fields_info = pbxt_statistics_fields_info;
2260 pbxt_statistics_table->fill_table = pbxt_statistics_fill_table;
2261+#endif
2262
2263 #if defined(XT_WIN) && defined(XT_COREDUMP)
2264 void register_crash_filter();
2265@@ -1721,14 +2015,14 @@
2266 }
2267
2268 #ifdef DRIZZLED
2269-int pbxt_exit_statitics(PluginRegistry &registry)
2270+static int pbxt_exit_statistics(Registry &registry)
2271 #else
2272-int pbxt_exit_statitics(void *XT_UNUSED(p))
2273+static int pbxt_exit_statistics(void *XT_UNUSED(p))
2274 #endif
2275 {
2276 #ifdef DRIZZLED
2277 registry.remove(pbxt_statistics_table);
2278- xt_free_ns(pbxt_statistics_table);
2279+ delete pbxt_statistics_table;
2280 #endif
2281 return(0);
2282 }
2283@@ -1758,7 +2052,11 @@
2284 * exist for the storage engine. This is also used by the default rename_table and
2285 * delete_table method in handler.cc.
2286 */
2287+#ifdef DRIZZLED
2288+const char **PBXTStorageEngine::bas_ext() const
2289+#else
2290 const char **ha_pbxt::bas_ext() const
2291+#endif
2292 {
2293 return pbxt_extensions;
2294 }
2295@@ -1800,11 +2098,13 @@
2296 * purposes!
2297 HA_NOT_EXACT_COUNT |
2298 */
2299+#ifndef DRIZZLED
2300 /*
2301 * This basically means we have a file with the name of
2302 * database table (which we do).
2303 */
2304 HA_FILE_BASED |
2305+#endif
2306 /*
2307 * Not sure what this does (but MyISAM and InnoDB have it)?!
2308 * Could it mean that we support the handler functions.
2309@@ -1971,7 +2271,7 @@
2310 if (!(self = ha_set_current_thread(thd, &err)))
2311 return xt_ha_pbxt_to_mysql_error(err);
2312
2313- XT_PRINT1(self, "ha_pbxt::open %s\n", table_path);
2314+ XT_PRINT1(self, "open (%s)\n", table_path);
2315
2316 pb_ex_in_use = 1;
2317 try_(a) {
2318@@ -2049,7 +2349,7 @@
2319 }
2320 }
2321
2322- XT_PRINT1(self, "ha_pbxt::close %s\n", pb_share && pb_share->sh_table_path->ps_path ? pb_share->sh_table_path->ps_path : "unknown");
2323+ XT_PRINT1(self, "close (%s)\n", pb_share && pb_share->sh_table_path->ps_path ? pb_share->sh_table_path->ps_path : "unknown");
2324
2325 if (self) {
2326 try_(a) {
2327@@ -2125,9 +2425,10 @@
2328 if (!TS(table)->next_number_key_offset) {
2329 // Autoincrement at key-start
2330 err = index_last(table->record[1]);
2331- if (!err)
2332+ if (!err && !table->next_number_field->is_null(TS(table)->rec_buff_length)) {
2333 /* {PRE-INC} */
2334 nr = (xtWord8) table->next_number_field->val_int_offset(TS(table)->rec_buff_length);
2335+ }
2336 }
2337 else {
2338 /* Do an index scan to find the largest value! */
2339@@ -2180,8 +2481,10 @@
2340 table->next_number_field = tmp_fie;
2341 table->in_use = tmp_thd;
2342
2343- if (xn_started)
2344+ if (xn_started) {
2345+ XT_PRINT0(self, "xt_xn_commit in init_auto_increment\n");
2346 xt_xn_commit(self);
2347+ }
2348 }
2349 xt_spinlock_unlock(&tab->tab_ainc_lock);
2350 }
2351@@ -2228,13 +2531,13 @@
2352 * insert into t1 values (-1);
2353 * insert into t1 values (NULL);
2354 */
2355-void ha_pbxt::set_auto_increment(Field *nr)
2356+xtPublic void ha_set_auto_increment(XTOpenTablePtr ot, Field *nr)
2357 {
2358 register XTTableHPtr tab;
2359 MX_ULONGLONG_T nr_int_val;
2360
2361 nr_int_val = nr->val_int();
2362- tab = pb_open_tab->ot_table;
2363+ tab = ot->ot_table;
2364
2365 if (nr->cmp((const unsigned char *)&tab->tab_auto_inc) > 0) {
2366 xt_spinlock_lock(&tab->tab_ainc_lock);
2367@@ -2260,9 +2563,9 @@
2368 #else
2369 tab->tab_dic.dic_min_auto_inc = nr_int_val + 100;
2370 #endif
2371- pb_open_tab->ot_thread = xt_get_self();
2372- if (!xt_tab_write_min_auto_inc(pb_open_tab))
2373- xt_log_and_clear_exception(pb_open_tab->ot_thread);
2374+ ot->ot_thread = xt_get_self();
2375+ if (!xt_tab_write_min_auto_inc(ot))
2376+ xt_log_and_clear_exception(ot->ot_thread);
2377 }
2378 }
2379 }
2380@@ -2305,7 +2608,7 @@
2381
2382 ASSERT_NS(pb_ex_in_use);
2383
2384- XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::write_row %s\n", pb_share->sh_table_path->ps_path);
2385+ XT_PRINT1(pb_open_tab->ot_thread, "write_row (%s)\n", pb_share->sh_table_path->ps_path);
2386 XT_DISABLED_TRACE(("INSERT tx=%d val=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&buf[1])));
2387 //statistic_increment(ha_write_count,&LOCK_status);
2388 #ifdef PBMS_ENABLED
2389@@ -2350,7 +2653,7 @@
2390 err = update_err;
2391 goto done;
2392 }
2393- set_auto_increment(table->next_number_field);
2394+ ha_set_auto_increment(pb_open_tab, table->next_number_field);
2395 }
2396
2397 if (!xt_tab_new_record(pb_open_tab, (xtWord1 *) buf)) {
2398@@ -2423,7 +2726,7 @@
2399
2400 ASSERT_NS(pb_ex_in_use);
2401
2402- XT_PRINT1(self, "ha_pbxt::update_row %s\n", pb_share->sh_table_path->ps_path);
2403+ XT_PRINT1(self, "update_row (%s)\n", pb_share->sh_table_path->ps_path);
2404 XT_DISABLED_TRACE(("UPDATE tx=%d val=%d\n", (int) self->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&new_data[1])));
2405 //statistic_increment(ha_update_count,&LOCK_status);
2406
2407@@ -2472,7 +2775,7 @@
2408
2409 old_map = mx_tmp_use_all_columns(table, table->read_set);
2410 nr = table->found_next_number_field->val_int();
2411- set_auto_increment(table->found_next_number_field);
2412+ ha_set_auto_increment(pb_open_tab, table->found_next_number_field);
2413 mx_tmp_restore_column_map(table, old_map);
2414 }
2415
2416@@ -2504,7 +2807,7 @@
2417
2418 ASSERT_NS(pb_ex_in_use);
2419
2420- XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::delete_row %s\n", pb_share->sh_table_path->ps_path);
2421+ XT_PRINT1(pb_open_tab->ot_thread, "delete_row (%s)\n", pb_share->sh_table_path->ps_path);
2422 XT_DISABLED_TRACE(("DELETE tx=%d val=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&buf[1])));
2423 //statistic_increment(ha_delete_count,&LOCK_status);
2424
2425@@ -2829,7 +3132,8 @@
2426
2427 int ha_pbxt::index_init(uint idx, bool XT_UNUSED(sorted))
2428 {
2429- XTIndexPtr ind;
2430+ XTIndexPtr ind;
2431+ XTThreadPtr thread = pb_open_tab->ot_thread;
2432
2433 /* select count(*) from smalltab_PBXT;
2434 * ignores the error below, and continues to
2435@@ -2851,6 +3155,15 @@
2436
2437 printf("index_init %s index %d cols req=%d/%d read_bits=%X write_bits=%X index_bits=%X\n", pb_open_tab->ot_table->tab_name->ps_path, (int) idx, pb_open_tab->ot_cols_req, pb_open_tab->ot_cols_req, (int) *table->read_set->bitmap, (int) *table->write_set->bitmap, (int) *ind->mi_col_map.bitmap);
2438 #endif
2439+ /* Start a statement based transaction as soon
2440+ * as a read is done for a modify type statement!
2441+ * Previously, this was done too late!
2442+ */
2443+ if (!thread->st_stat_trans) {
2444+ trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton);
2445+ XT_PRINT0(thread, "ha_pbxt::update_row trans_register_ha all=FALSE\n");
2446+ thread->st_stat_trans = TRUE;
2447+ }
2448 }
2449 else {
2450 pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set);
2451@@ -2901,7 +3214,7 @@
2452 #endif
2453 }
2454
2455- xt_xlog_check_long_writer(pb_open_tab->ot_thread);
2456+ xt_xlog_check_long_writer(thread);
2457
2458 pb_open_tab->ot_thread->st_statistics.st_scan_index++;
2459 return 0;
2460@@ -2911,7 +3224,7 @@
2461 {
2462 int err = 0;
2463
2464- XT_TRACE_CALL();
2465+ XT_TRACE_METHOD();
2466
2467 XTThreadPtr thread = pb_open_tab->ot_thread;
2468
2469@@ -2991,7 +3304,7 @@
2470
2471 ASSERT_NS(pb_ex_in_use);
2472
2473- XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::index_read_xt %s\n", pb_share->sh_table_path->ps_path);
2474+ XT_PRINT1(pb_open_tab->ot_thread, "index_read_xt (%s)\n", pb_share->sh_table_path->ps_path);
2475 XT_DISABLED_TRACE(("search tx=%d val=%d update=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(key), pb_modified));
2476 ind = (XTIndexPtr) pb_share->sh_dic_keys[idx];
2477
2478@@ -3072,7 +3385,7 @@
2479 int err = 0;
2480 XTIndexPtr ind;
2481
2482- XT_TRACE_CALL();
2483+ XT_TRACE_METHOD();
2484 //statistic_increment(ha_read_next_count,&LOCK_status);
2485 ASSERT_NS(pb_ex_in_use);
2486
2487@@ -3114,7 +3427,7 @@
2488 XTIndexPtr ind;
2489 XTIdxSearchKeyRec search_key;
2490
2491- XT_TRACE_CALL();
2492+ XT_TRACE_METHOD();
2493 //statistic_increment(ha_read_next_count,&LOCK_status);
2494 ASSERT_NS(pb_ex_in_use);
2495
2496@@ -3154,7 +3467,7 @@
2497 int err = 0;
2498 XTIndexPtr ind;
2499
2500- XT_TRACE_CALL();
2501+ XT_TRACE_METHOD();
2502 //statistic_increment(ha_read_prev_count,&LOCK_status);
2503 ASSERT_NS(pb_ex_in_use);
2504
2505@@ -3188,7 +3501,7 @@
2506 XTIndexPtr ind;
2507 XTIdxSearchKeyRec search_key;
2508
2509- XT_TRACE_CALL();
2510+ XT_TRACE_METHOD();
2511 //statistic_increment(ha_read_first_count,&LOCK_status);
2512 ASSERT_NS(pb_ex_in_use);
2513
2514@@ -3228,7 +3541,7 @@
2515 XTIndexPtr ind;
2516 XTIdxSearchKeyRec search_key;
2517
2518- XT_TRACE_CALL();
2519+ XT_TRACE_METHOD();
2520 //statistic_increment(ha_read_last_count,&LOCK_status);
2521 ASSERT_NS(pb_ex_in_use);
2522
2523@@ -3275,10 +3588,11 @@
2524 */
2525 int ha_pbxt::rnd_init(bool scan)
2526 {
2527- int err = 0;
2528+ int err = 0;
2529+ XTThreadPtr thread = pb_open_tab->ot_thread;
2530
2531- XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::rnd_init %s\n", pb_share->sh_table_path->ps_path);
2532- XT_DISABLED_TRACE(("seq scan tx=%d\n", (int) pb_open_tab->ot_thread->st_xact_data->xd_start_xn_id));
2533+ XT_PRINT1(thread, "rnd_init (%s)\n", pb_share->sh_table_path->ps_path);
2534+ XT_DISABLED_TRACE(("seq scan tx=%d\n", (int) thread->st_xact_data->xd_start_xn_id));
2535
2536 /* Call xt_tab_seq_exit() to make sure the resources used by the previous
2537 * scan are freed. In particular make sure cache page ref count is decremented.
2538@@ -3296,8 +3610,18 @@
2539 xt_tab_seq_exit(pb_open_tab);
2540
2541 /* The number of columns required: */
2542- if (pb_open_tab->ot_is_modify)
2543+ if (pb_open_tab->ot_is_modify) {
2544 pb_open_tab->ot_cols_req = table->read_set->MX_BIT_SIZE();
2545+ /* Start a statement based transaction as soon
2546+ * as a read is done for a modify type statement!
2547+ * Previously, this was done too late!
2548+ */
2549+ if (!thread->st_stat_trans) {
2550+ trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton);
2551+ XT_PRINT0(thread, "ha_pbxt::update_row trans_register_ha all=FALSE\n");
2552+ thread->st_stat_trans = TRUE;
2553+ }
2554+ }
2555 else {
2556 pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set);
2557
2558@@ -3322,14 +3646,14 @@
2559 else
2560 xt_tab_seq_reset(pb_open_tab);
2561
2562- xt_xlog_check_long_writer(pb_open_tab->ot_thread);
2563+ xt_xlog_check_long_writer(thread);
2564
2565 return err;
2566 }
2567
2568 int ha_pbxt::rnd_end()
2569 {
2570- XT_TRACE_CALL();
2571+ XT_TRACE_METHOD();
2572
2573 /*
2574 * make permanent the lock for the last scanned row
2575@@ -3358,7 +3682,7 @@
2576 int err = 0;
2577 xtBool eof;
2578
2579- XT_TRACE_CALL();
2580+ XT_TRACE_METHOD();
2581 ASSERT_NS(pb_ex_in_use);
2582 //statistic_increment(ha_read_rnd_next_count, &LOCK_status);
2583 xt_xlog_check_long_writer(pb_open_tab->ot_thread);
2584@@ -3393,7 +3717,7 @@
2585 */
2586 void ha_pbxt::position(const byte *XT_UNUSED(record))
2587 {
2588- XT_TRACE_CALL();
2589+ XT_TRACE_METHOD();
2590 ASSERT_NS(pb_ex_in_use);
2591 /*
2592 * I changed this from using little endian to big endian.
2593@@ -3429,10 +3753,10 @@
2594 {
2595 int err = 0;
2596
2597- XT_TRACE_CALL();
2598+ XT_TRACE_METHOD();
2599 ASSERT_NS(pb_ex_in_use);
2600 //statistic_increment(ha_read_rnd_count, &LOCK_status);
2601- XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::rnd_pos %s\n", pb_share->sh_table_path->ps_path);
2602+ XT_PRINT1(pb_open_tab->ot_thread, "rnd_pos (%s)\n", pb_share->sh_table_path->ps_path);
2603
2604 pb_open_tab->ot_curr_rec_id = mi_uint4korr((xtWord1 *) pos);
2605 switch (xt_tab_dirty_read_record(pb_open_tab, (xtWord1 *) buf)) {
2606@@ -3509,7 +3833,7 @@
2607 XTOpenTablePtr ot;
2608 int in_use;
2609
2610- XT_TRACE_CALL();
2611+ XT_TRACE_METHOD();
2612
2613 if (!(in_use = pb_ex_in_use)) {
2614 pb_ex_in_use = 1;
2615@@ -3535,7 +3859,7 @@
2616 stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof);
2617 stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size;
2618 //check_time = info.check_time;
2619- stats.mean_rec_length = ot->ot_rec_size;
2620+ stats.mean_rec_length = (ulong) ot->ot_rec_size;
2621 }
2622
2623 if (flag & HA_STATUS_CONST) {
2624@@ -3551,7 +3875,9 @@
2625 stats.block_size = XT_INDEX_PAGE_SIZE;
2626
2627 if (share->tmp_table == NO_TMP_TABLE)
2628-#if MYSQL_VERSION_ID > 60005
2629+#ifdef DRIZZLED
2630+#define WHICH_MUTEX mutex
2631+#elif MYSQL_VERSION_ID >= 50404
2632 #define WHICH_MUTEX LOCK_ha_data
2633 #else
2634 #define WHICH_MUTEX mutex
2635@@ -3559,19 +3885,15 @@
2636
2637 #ifdef SAFE_MUTEX
2638
2639-#if MYSQL_VERSION_ID < 60000
2640+#if MYSQL_VERSION_ID < 50404
2641 #if MYSQL_VERSION_ID < 50123
2642 safe_mutex_lock(&share->mutex,__FILE__,__LINE__);
2643 #else
2644 safe_mutex_lock(&share->mutex,0,__FILE__,__LINE__);
2645 #endif
2646 #else
2647-#if MYSQL_VERSION_ID < 60004
2648- safe_mutex_lock(&share->mutex,__FILE__,__LINE__);
2649-#else
2650 safe_mutex_lock(&share->WHICH_MUTEX,0,__FILE__,__LINE__);
2651 #endif
2652-#endif
2653
2654 #else // SAFE_MUTEX
2655
2656@@ -3675,7 +3997,7 @@
2657 {
2658 int err = 0;
2659
2660- XT_PRINT2(xt_get_self(), "ha_pbxt::extra %s operation=%d\n", pb_share->sh_table_path->ps_path, operation);
2661+ XT_PRINT2(xt_get_self(), "ha_pbxt::extra (%s) operation=%d\n", pb_share->sh_table_path->ps_path, operation);
2662
2663 switch (operation) {
2664 case HA_EXTRA_RESET_STATE:
2665@@ -3771,14 +4093,14 @@
2666 */
2667 int ha_pbxt::reset(void)
2668 {
2669- XT_TRACE_CALL();
2670+ XT_TRACE_METHOD();
2671 extra(HA_EXTRA_RESET_STATE);
2672 XT_RETURN(0);
2673 }
2674
2675 void ha_pbxt::unlock_row()
2676 {
2677- XT_TRACE_CALL();
2678+ XT_TRACE_METHOD();
2679 if (pb_open_tab)
2680 pb_open_tab->ot_table->tab_locks.xt_remove_temp_lock(pb_open_tab, FALSE);
2681 }
2682@@ -3802,7 +4124,7 @@
2683 XTDDTable *tab_def = NULL;
2684 char path[PATH_MAX];
2685
2686- XT_TRACE_CALL();
2687+ XT_TRACE_METHOD();
2688
2689 if (thd_sql_command(thd) != SQLCOM_TRUNCATE) {
2690 /* Just like InnoDB we only handle TRUNCATE TABLE
2691@@ -3906,7 +4228,7 @@
2692 xtXactID clean_xn_id = 0;
2693 uint cnt = 10;
2694
2695- XT_TRACE_CALL();
2696+ XT_TRACE_METHOD();
2697
2698 if (!pb_open_tab) {
2699 if ((err = reopen()))
2700@@ -4056,7 +4378,7 @@
2701 ASSERT_NS(pb_ex_in_use);
2702 */
2703
2704- XT_PRINT1(self, "ha_pbxt::EXTERNAL_LOCK %s lock_type=UNLOCK\n", pb_share->sh_table_path->ps_path);
2705+ XT_PRINT1(self, "EXTERNAL_LOCK (%s) lock_type=UNLOCK\n", pb_share->sh_table_path->ps_path);
2706
2707 /* Make any temporary locks on this table permanent.
2708 *
2709@@ -4189,10 +4511,9 @@
2710 xt_broadcast_cond_ns((xt_cond_type *) pb_share->sh_ex_cond);
2711 }
2712 else {
2713- XT_PRINT2(self, "ha_pbxt::EXTERNAL_LOCK %s lock_type=%d\n", pb_share->sh_table_path->ps_path, lock_type);
2714+ XT_PRINT2(self, "ha_pbxt::EXTERNAL_LOCK (%s) lock_type=%d\n", pb_share->sh_table_path->ps_path, lock_type);
2715
2716 if (pb_lock_table) {
2717-
2718 pb_ex_in_use = 1;
2719 try_(a) {
2720 if (!pb_table_locked)
2721@@ -4243,14 +4564,18 @@
2722 if ((pb_open_tab->ot_for_update = (lock_type == F_WRLCK))) {
2723 switch ((int) thd_sql_command(thd)) {
2724 case SQLCOM_DELETE:
2725+#ifndef DRIZZLED
2726 case SQLCOM_DELETE_MULTI:
2727+#endif
2728 /* turn DELETE IGNORE into normal DELETE. The IGNORE option causes problems because
2729 * when a record is deleted we add an xlog record which we cannot "rollback" later
2730 * when we find that an FK-constraint has failed.
2731 */
2732 thd->lex->ignore = false;
2733 case SQLCOM_UPDATE:
2734+#ifndef DRIZZLED
2735 case SQLCOM_UPDATE_MULTI:
2736+#endif
2737 case SQLCOM_REPLACE:
2738 case SQLCOM_REPLACE_SELECT:
2739 case SQLCOM_INSERT:
2740@@ -4265,7 +4590,9 @@
2741 case SQLCOM_DROP_TABLE:
2742 case SQLCOM_DROP_INDEX:
2743 case SQLCOM_LOAD:
2744+#ifndef DRIZZLED
2745 case SQLCOM_REPAIR:
2746+#endif
2747 case SQLCOM_OPTIMIZE:
2748 self->st_stat_modify = TRUE;
2749 break;
2750@@ -4316,11 +4643,16 @@
2751 self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ;
2752 self->st_ignore_fkeys = (thd_test_options(thd,OPTION_NO_FOREIGN_KEY_CHECKS)) != 0;
2753 self->st_auto_commit = (thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) == 0;
2754+#ifdef DRIZZLED
2755+ self->st_table_trans = FALSE;
2756+#else
2757 self->st_table_trans = thd_sql_command(thd) == SQLCOM_LOCK_TABLES;
2758+#endif
2759 self->st_abort_trans = FALSE;
2760 self->st_stat_ended = FALSE;
2761 self->st_stat_trans = FALSE;
2762 XT_PRINT0(self, "xt_xn_begin\n");
2763+ xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
2764 if (!xt_xn_begin(self)) {
2765 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
2766 pb_ex_in_use = 0;
2767@@ -4404,7 +4736,7 @@
2768 if (!(self = ha_set_current_thread(thd, &err)))
2769 return xt_ha_pbxt_to_mysql_error(err);
2770
2771- XT_PRINT2(self, "ha_pbxt::start_stmt %s lock_type=%d\n", pb_share->sh_table_path->ps_path, (int) lock_type);
2772+ XT_PRINT2(self, "ha_pbxt::start_stmt (%s) lock_type=%d\n", pb_share->sh_table_path->ps_path, (int) lock_type);
2773
2774 if (!pb_open_tab) {
2775 if ((err = reopen()))
2776@@ -4430,12 +4762,12 @@
2777 /* This section handles "auto-commit"... */
2778 if (self->st_xact_data && self->st_auto_commit && self->st_table_trans) {
2779 if (self->st_abort_trans) {
2780- XT_PRINT0(self, "xt_xn_rollback\n");
2781+ XT_PRINT0(self, "xt_xn_rollback in start_stmt\n");
2782 if (!xt_xn_rollback(self))
2783 err = xt_ha_pbxt_thread_error_for_mysql(pb_mysql_thd, self, pb_ignore_dup_key);
2784 }
2785 else {
2786- XT_PRINT0(self, "xt_xn_commit\n");
2787+ XT_PRINT0(self, "xt_xn_commit in start_stmt\n");
2788 if (!xt_xn_commit(self))
2789 err = xt_ha_pbxt_thread_error_for_mysql(pb_mysql_thd, self, pb_ignore_dup_key);
2790 }
2791@@ -4466,9 +4798,11 @@
2792 if (pb_open_tab->ot_for_update) {
2793 switch ((int) thd_sql_command(thd)) {
2794 case SQLCOM_UPDATE:
2795+ case SQLCOM_DELETE:
2796+#ifndef DRIZZLED
2797 case SQLCOM_UPDATE_MULTI:
2798- case SQLCOM_DELETE:
2799 case SQLCOM_DELETE_MULTI:
2800+#endif
2801 case SQLCOM_REPLACE:
2802 case SQLCOM_REPLACE_SELECT:
2803 case SQLCOM_INSERT:
2804@@ -4483,14 +4817,15 @@
2805 case SQLCOM_DROP_TABLE:
2806 case SQLCOM_DROP_INDEX:
2807 case SQLCOM_LOAD:
2808+#ifndef DRIZZLED
2809 case SQLCOM_REPAIR:
2810+#endif
2811 case SQLCOM_OPTIMIZE:
2812 self->st_stat_modify = TRUE;
2813 break;
2814 }
2815 }
2816
2817-
2818 /* (***) This is required at this level!
2819 * No matter how often it is called, it is still the start of a
2820 * statement. We need to make sure statements that are NOT mistaken
2821@@ -4516,6 +4851,7 @@
2822 self->st_stat_ended = FALSE;
2823 self->st_stat_trans = FALSE;
2824 XT_PRINT0(self, "xt_xn_begin\n");
2825+ xt_xres_wait_for_recovery(self, XT_RECOVER_SWEPT);
2826 if (!xt_xn_begin(self)) {
2827 err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
2828 goto complete;
2829@@ -4673,7 +5009,9 @@
2830 *
2831 */
2832 if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) &&
2833+#ifndef DRIZZLED
2834 !(thd_in_lock_tables(thd) && thd_sql_command(thd) == SQLCOM_LOCK_TABLES) &&
2835+#endif
2836 !thd_tablespace_op(thd) &&
2837 thd_sql_command(thd) != SQLCOM_TRUNCATE &&
2838 thd_sql_command(thd) != SQLCOM_OPTIMIZE &&
2839@@ -4691,22 +5029,23 @@
2840
2841 * Stewart: removed SQLCOM_CALL, not sure of implications.
2842 */
2843- if (lock_type == TL_READ_NO_INSERT &&
2844- (!thd_in_lock_tables(thd)
2845+ if (lock_type == TL_READ_NO_INSERT
2846 #ifndef DRIZZLED
2847+ && (!thd_in_lock_tables(thd)
2848 || thd_sql_command(thd) == SQLCOM_CALL
2849+ )
2850 #endif
2851- ))
2852+ )
2853 {
2854 lock_type = TL_READ;
2855 }
2856
2857- XT_PRINT3(xt_get_self(), "ha_pbxt::store_lock %s %d->%d\n", pb_share->sh_table_path->ps_path, pb_lock.type, lock_type);
2858+ XT_PRINT3(xt_get_self(), "store_lock (%s) %d->%d\n", pb_share->sh_table_path->ps_path, pb_lock.type, lock_type);
2859 pb_lock.type = lock_type;
2860 }
2861 #ifdef PBXT_HANDLER_TRACE
2862 else {
2863- XT_PRINT3(xt_get_self(), "ha_pbxt::store_lock %s %d->%d (ignore/unlock)\n", pb_share->sh_table_path->ps_path, lock_type, lock_type);
2864+ XT_PRINT3(xt_get_self(), "store_lock (%s) %d->%d (ignore/unlock)\n", pb_share->sh_table_path->ps_path, lock_type, lock_type);
2865 }
2866 #endif
2867 *to++= &pb_lock;
2868@@ -4723,15 +5062,23 @@
2869 * during create if the table_flag HA_DROP_BEFORE_CREATE was specified for
2870 * the storage engine.
2871 */
2872+#ifdef DRIZZLED
2873+int PBXTStorageEngine::doDropTable(Session &, std::string table_path_str)
2874+#else
2875 int ha_pbxt::delete_table(const char *table_path)
2876+#endif
2877 {
2878 THD *thd = current_thd;
2879 int err = 0;
2880 XTThreadPtr self = NULL;
2881 XTSharePtr share;
2882
2883+#ifdef DRIZZLED
2884+ const char *table_path = table_path_str.c_str();
2885+#endif
2886+
2887 STAT_TRACE(self, *thd_query(thd));
2888- XT_PRINT1(self, "ha_pbxt::delete_table %s\n", table_path);
2889+ XT_PRINT1(self, "delete_table (%s)\n", table_path);
2890
2891 if (XTSystemTableShare::isSystemTable(table_path))
2892 return delete_system_table(table_path);
2893@@ -4795,7 +5142,7 @@
2894 #endif
2895 }
2896 catch_(a) {
2897- err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
2898+ err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
2899 #ifdef DRIZZLED
2900 if (err == HA_ERR_NO_SUCH_TABLE)
2901 err = ENOENT;
2902@@ -4819,7 +5166,11 @@
2903 return err;
2904 }
2905
2906+#ifdef DRIZZLED
2907+int PBXTStorageEngine::delete_system_table(const char *table_path)
2908+#else
2909 int ha_pbxt::delete_system_table(const char *table_path)
2910+#endif
2911 {
2912 THD *thd = current_thd;
2913 XTExceptionRec e;
2914@@ -4857,7 +5208,13 @@
2915 * This function can be used to move a table from one database to
2916 * another.
2917 */
2918+#ifdef DRIZZLED
2919+int PBXTStorageEngine::doRenameTable(Session *,
2920+ const char *from,
2921+ const char *to)
2922+#else
2923 int ha_pbxt::rename_table(const char *from, const char *to)
2924+#endif
2925 {
2926 THD *thd = current_thd;
2927 int err = 0;
2928@@ -4865,15 +5222,13 @@
2929 XTSharePtr share;
2930 XTDatabaseHPtr to_db;
2931
2932- XT_TRACE_CALL();
2933-
2934 if (XTSystemTableShare::isSystemTable(from))
2935 return rename_system_table(from, to);
2936
2937 if (!(self = ha_set_current_thread(thd, &err)))
2938 return xt_ha_pbxt_to_mysql_error(err);
2939
2940- XT_PRINT2(self, "ha_pbxt::rename_table %s -> %s\n", from, to);
2941+ XT_PRINT2(self, "rename_table (%s -> %s)\n", from, to);
2942
2943 #ifdef PBMS_ENABLED
2944 PBMSResultRec result;
2945@@ -4929,7 +5284,7 @@
2946 #endif
2947 }
2948 catch_(a) {
2949- err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
2950+ err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
2951 }
2952 cont_(a);
2953
2954@@ -4940,7 +5295,11 @@
2955 XT_RETURN(err);
2956 }
2957
2958+#ifdef DRIZZLED
2959+int PBXTStorageEngine::rename_system_table(const char *XT_UNUSED(from), const char *XT_UNUSED(to))
2960+#else
2961 int ha_pbxt::rename_system_table(const char *XT_UNUSED(from), const char *XT_UNUSED(to))
2962+#endif
2963 {
2964 return ER_NOT_SUPPORTED_YET;
2965 }
2966@@ -5029,7 +5388,15 @@
2967
2968 * Called from handle.cc by ha_create_table().
2969 */
2970+#ifdef DRIZZLED
2971+int PBXTStorageEngine::doCreateTable(Session *,
2972+ const char *table_path,
2973+ Table &table_arg,
2974+ HA_CREATE_INFO &create_info,
2975+ drizzled::message::Table &XT_UNUSED(proto))
2976+#else
2977 int ha_pbxt::create(const char *table_path, TABLE *table_arg, HA_CREATE_INFO *create_info)
2978+#endif
2979 {
2980 THD *thd = current_thd;
2981 int err = 0;
2982@@ -5037,37 +5404,61 @@
2983 XTDDTable *tab_def = NULL;
2984 XTDictionaryRec dic;
2985
2986+ if ((strcmp(table_path, "./pbxt/location") == 0) || (strcmp(table_path, "./pbxt/statistics") == 0))
2987+ return 0;
2988+
2989 memset(&dic, 0, sizeof(dic));
2990
2991- XT_TRACE_CALL();
2992-
2993 if (!(self = ha_set_current_thread(thd, &err)))
2994 return xt_ha_pbxt_to_mysql_error(err);
2995+#ifdef DRIZZLED
2996+ XT_PRINT2(self, "create (%s) %s\n", table_path, (create_info.options & HA_LEX_CREATE_TMP_TABLE) ? "temporary" : "");
2997+#else
2998+ XT_PRINT2(self, "create (%s) %s\n", table_path, (create_info->options & HA_LEX_CREATE_TMP_TABLE) ? "temporary" : "");
2999+#endif
3000
3001 STAT_TRACE(self, *thd_query(thd));
3002- XT_PRINT1(self, "ha_pbxt::create %s\n", table_path);
3003
3004 try_(a) {
3005 xt_ha_open_database_of_table(self, (XTPathStrPtr) table_path);
3006
3007+#ifdef DRIZZLED
3008+ for (uint i=0; i<TS(&table_arg)->keys; i++) {
3009+ if (table_arg.key_info[i].key_length > XT_INDEX_MAX_KEY_SIZE)
3010+ xt_throw_sulxterr(XT_CONTEXT, XT_ERR_KEY_TOO_LARGE, table_arg.key_info[i].name, (u_long) XT_INDEX_MAX_KEY_SIZE);
3011+ }
3012+#else
3013 for (uint i=0; i<TS(table_arg)->keys; i++) {
3014 if (table_arg->key_info[i].key_length > XT_INDEX_MAX_KEY_SIZE)
3015 xt_throw_sulxterr(XT_CONTEXT, XT_ERR_KEY_TOO_LARGE, table_arg->key_info[i].name, (u_long) XT_INDEX_MAX_KEY_SIZE);
3016 }
3017+#endif
3018
3019 /* ($) auto_increment_value will be zero if
3020 * AUTO_INCREMENT is not used. Otherwise
3021 * Query was ALTER TABLE ... AUTO_INCREMENT = x; or
3022 * CREATE TABLE ... AUTO_INCREMENT = x;
3023 */
3024+#ifdef DRIZZLED
3025+ tab_def = xt_ri_create_table(self, true, (XTPathStrPtr) table_path, *thd_query(thd), myxt_create_table_from_table(self, &table_arg));
3026+ tab_def->checkForeignKeys(self, create_info.options & HA_LEX_CREATE_TMP_TABLE);
3027+#else
3028 tab_def = xt_ri_create_table(self, true, (XTPathStrPtr) table_path, *thd_query(thd), myxt_create_table_from_table(self, table_arg));
3029 tab_def->checkForeignKeys(self, create_info->options & HA_LEX_CREATE_TMP_TABLE);
3030+#endif
3031
3032 dic.dic_table = tab_def;
3033+#ifdef DRIZZLED
3034+ dic.dic_my_table = &table_arg;
3035+ dic.dic_tab_flags = (create_info.options & HA_LEX_CREATE_TMP_TABLE) ? XT_TAB_FLAGS_TEMP_TAB : 0;
3036+ dic.dic_min_auto_inc = (xtWord8) create_info.auto_increment_value; /* ($) */
3037+ dic.dic_def_ave_row_size = table_arg.s->getAvgRowLength();
3038+#else
3039 dic.dic_my_table = table_arg;
3040 dic.dic_tab_flags = (create_info->options & HA_LEX_CREATE_TMP_TABLE) ? XT_TAB_FLAGS_TEMP_TAB : 0;
3041 dic.dic_min_auto_inc = (xtWord8) create_info->auto_increment_value; /* ($) */
3042 dic.dic_def_ave_row_size = (xtWord8) table_arg->s->avg_row_length;
3043+#endif
3044 myxt_setup_dictionary(self, &dic);
3045
3046 /*
3047@@ -5089,7 +5480,7 @@
3048 if (tab_def)
3049 tab_def->finalize(self);
3050 dic.dic_table = NULL;
3051- err = xt_ha_pbxt_thread_error_for_mysql(thd, self, pb_ignore_dup_key);
3052+ err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
3053 }
3054 cont_(a);
3055
3056@@ -5161,7 +5552,7 @@
3057 if (!self->t_exception.e_xt_err)
3058 return FALSE;
3059
3060- buf->copy(self->t_exception.e_err_msg, strlen(self->t_exception.e_err_msg), system_charset_info);
3061+ buf->copy(self->t_exception.e_err_msg, (uint32) strlen(self->t_exception.e_err_msg), system_charset_info);
3062 return TRUE;
3063 }
3064
3065@@ -5421,16 +5812,31 @@
3066
3067 #ifdef DRIZZLED
3068 static MYSQL_SYSVAR_INT(max_threads, pbxt_max_threads,
3069- PLUGIN_VAR_OPCMDARG,
3070+ PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
3071 "The maximum number of threads used by PBXT",
3072 NULL, NULL, 500, 20, 20000, 1);
3073 #else
3074 static MYSQL_SYSVAR_INT(max_threads, pbxt_max_threads,
3075- PLUGIN_VAR_OPCMDARG,
3076+ PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
3077 "The maximum number of threads used by PBXT, 0 = set according to MySQL max_connections.",
3078 NULL, NULL, 0, 0, 20000, 1);
3079 #endif
3080
3081+#ifndef DEBUG
3082+static MYSQL_SYSVAR_BOOL(support_xa, pbxt_support_xa,
3083+ PLUGIN_VAR_OPCMDARG,
3084+ "Enable PBXT support for the XA two-phase commit, default is enabled",
3085+ NULL, NULL, TRUE);
3086+#else
3087+static MYSQL_SYSVAR_BOOL(support_xa, pbxt_support_xa,
3088+ PLUGIN_VAR_OPCMDARG,
3089+ "Enable PBXT support for the XA two-phase commit, default is disabled (due to assertion failure in MySQL)",
3090+ /* The problem is, in MySQL an assertion fails in debug mode:
3091+ * Assertion failed: (total_ha_2pc == (ulong) opt_bin_log+1), function ha_recover, file handler.cc, line 1557.
3092+ */
3093+ NULL, NULL, FALSE);
3094+#endif
3095+
3096 static struct st_mysql_sys_var* pbxt_system_variables[] = {
3097 MYSQL_SYSVAR(index_cache_size),
3098 MYSQL_SYSVAR(record_cache_size),
3099@@ -5448,6 +5854,7 @@
3100 MYSQL_SYSVAR(offline_log_function),
3101 MYSQL_SYSVAR(sweeper_priority),
3102 MYSQL_SYSVAR(max_threads),
3103+ MYSQL_SYSVAR(support_xa),
3104 NULL
3105 };
3106 #endif
3107@@ -5494,8 +5901,8 @@
3108 "Paul McCullagh, PrimeBase Technologies GmbH",
3109 "PBXT internal system statitics",
3110 PLUGIN_LICENSE_GPL,
3111- pbxt_init_statitics, /* plugin init */
3112- pbxt_exit_statitics, /* plugin deinit */
3113+ pbxt_init_statistics, /* plugin init */
3114+ pbxt_exit_statistics, /* plugin deinit */
3115 #ifndef DRIZZLED
3116 0x0005,
3117 #endif
3118
3119=== modified file 'storage/pbxt/src/ha_pbxt.h'
3120--- storage/pbxt/src/ha_pbxt.h 2009-08-17 11:12:36 +0000
3121+++ storage/pbxt/src/ha_pbxt.h 2009-12-10 11:48:17 +0000
3122@@ -27,9 +27,9 @@
3123
3124 #ifdef DRIZZLED
3125 #include <drizzled/common.h>
3126-#include <drizzled/handler.h>
3127-#include <drizzled/plugin/storage_engine.h>
3128 #include <mysys/thr_lock.h>
3129+#include <drizzled/cursor.h>
3130+
3131 #else
3132 #include "mysql_priv.h"
3133 #endif
3134@@ -53,17 +53,31 @@
3135
3136 #ifdef DRIZZLED
3137
3138-class PBXTStorageEngine : public StorageEngine {
3139+class PBXTStorageEngine : public drizzled::plugin::StorageEngine
3140+{
3141+
3142+ int delete_system_table(const char *table_path);
3143+ int rename_system_table(const char * from, const char * to);
3144+
3145 public:
3146 PBXTStorageEngine(std::string name_arg)
3147- : StorageEngine(name_arg, HTON_NO_FLAGS) {}
3148+ : drizzled::plugin::StorageEngine(name_arg, HTON_NO_FLAGS) {}
3149+
3150+ void operator delete(void *) {}
3151+ void operator delete[] (void *) {}
3152
3153 /* override */ int close_connection(Session *);
3154 /* override */ int commit(Session *, bool);
3155 /* override */ int rollback(Session *, bool);
3156- /* override */ handler *create(TABLE_SHARE *, MEM_ROOT *);
3157+ /* override */ Cursor *create(TABLE_SHARE *, MEM_ROOT *);
3158 /* override */ void drop_database(char *);
3159 /* override */ bool show_status(Session *, stat_print_fn *, enum ha_stat_type);
3160+ /* override */ const char **bas_ext() const;
3161+ /* override */ int doCreateTable(Session *session, const char *table_name,
3162+ Table &table_arg, HA_CREATE_INFO
3163+ &create_info, drizzled::message::Table &proto);
3164+ /* override */ int doRenameTable(Session *, const char *from, const char *to);
3165+ /* override */ int doDropTable(Session &session, std::string table_path);
3166 };
3167
3168 typedef PBXTStorageEngine handlerton;
3169@@ -139,9 +153,9 @@
3170 * don't implement this method unless you really have indexes.
3171 */
3172 const char *index_type(uint inx) { (void) inx; return "BTREE"; }
3173-
3174+#ifndef DRIZZLED
3175 const char **bas_ext() const;
3176-
3177+#endif
3178 MX_UINT8_T table_cache_type();
3179
3180 /*
3181@@ -241,11 +255,13 @@
3182 int optimize(THD* thd, HA_CHECK_OPT* check_opt);
3183 int check(THD* thd, HA_CHECK_OPT* check_opt);
3184 ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
3185+#ifndef DRIZZLED
3186+ int delete_system_table(const char *table_path);
3187 int delete_table(const char *from);
3188- int delete_system_table(const char *table_path);
3189+ int rename_system_table(const char * from, const char * to);
3190 int rename_table(const char * from, const char * to);
3191- int rename_system_table(const char * from, const char * to);
3192 int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); //required
3193+#endif
3194 void update_create_info(HA_CREATE_INFO *create_info);
3195
3196 THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); //required
3197@@ -277,6 +293,7 @@
3198 int xt_ha_pbxt_to_mysql_error(int xt_err);
3199 int xt_ha_pbxt_thread_error_for_mysql(THD *thd, const XTThreadPtr self, int ignore_dup_key);
3200 void xt_ha_all_threads_close_database(XTThreadPtr self, XTDatabase *db);
3201+void ha_set_auto_increment(XTOpenTablePtr ot, Field *nr);
3202
3203 /*
3204 * These hooks are suppossed to only be used by InnoDB:
3205
3206=== modified file 'storage/pbxt/src/ha_xtsys.h'
3207--- storage/pbxt/src/ha_xtsys.h 2009-08-17 11:12:36 +0000
3208+++ storage/pbxt/src/ha_xtsys.h 2009-12-10 11:48:17 +0000
3209@@ -30,8 +30,9 @@
3210
3211 #ifdef DRIZZLED
3212 #include <drizzled/common.h>
3213-#include <drizzled/handler.h>
3214+#include <drizzled/handler_structs.h>
3215 #include <drizzled/current_session.h>
3216+#include <drizzled/cursor.h>
3217 #else
3218 #include "mysql_priv.h"
3219 #endif
3220
3221=== modified file 'storage/pbxt/src/heap_xt.cc'
3222--- storage/pbxt/src/heap_xt.cc 2009-08-17 11:12:36 +0000
3223+++ storage/pbxt/src/heap_xt.cc 2009-12-10 11:48:17 +0000
3224@@ -73,7 +73,7 @@
3225 }
3226
3227 #ifdef DEBUG_MEMORY
3228-xtPublic void xt_mm_heap_reference(XTThreadPtr self, XTHeapPtr hp, u_int line, c_char *file)
3229+xtPublic void xt_mm_heap_reference(XTThreadPtr XT_UNUSED(self), XTHeapPtr hp, u_int line, c_char *file)
3230 #else
3231 xtPublic void xt_heap_reference(XTThreadPtr, XTHeapPtr hp)
3232 #endif
3233
3234=== modified file 'storage/pbxt/src/index_xt.cc'
3235--- storage/pbxt/src/index_xt.cc 2009-08-18 07:46:53 +0000
3236+++ storage/pbxt/src/index_xt.cc 2009-12-10 11:48:17 +0000
3237@@ -829,14 +829,25 @@
3238
3239 result->sr_item.i_item_offset += result->sr_item.i_item_size + result->sr_item.i_node_ref_size;
3240 bitem = branch->tb_data + result->sr_item.i_item_offset;
3241- if (ind->mi_fix_key)
3242- ilen = result->sr_item.i_item_size;
3243+ if (result->sr_item.i_item_offset < result->sr_item.i_total_size) {
3244+ if (ind->mi_fix_key)
3245+ ilen = result->sr_item.i_item_size;
3246+ else {
3247+ ilen = myxt_get_key_length(ind, bitem) + XT_RECORD_REF_SIZE;
3248+ result->sr_item.i_item_size = ilen;
3249+ }
3250+ xt_get_res_record_ref(bitem + ilen - XT_RECORD_REF_SIZE, result); /* (Only valid if i_item_offset < i_total_size) */
3251+ }
3252 else {
3253- ilen = myxt_get_key_length(ind, bitem) + XT_RECORD_REF_SIZE;
3254- result->sr_item.i_item_size = ilen;
3255+ result->sr_item.i_item_size = 0;
3256+ result->sr_rec_id = 0;
3257+ result->sr_row_id = 0;
3258 }
3259- xt_get_res_record_ref(bitem + ilen - XT_RECORD_REF_SIZE, result); /* (Only valid if i_item_offset < i_total_size) */
3260- result->sr_branch = IDX_GET_NODE_REF(tab, bitem, result->sr_item.i_node_ref_size);
3261+ if (result->sr_item.i_node_ref_size)
3262+ /* IDX_GET_NODE_REF() loads the branch reference to the LEFT of the item. */
3263+ result->sr_branch = IDX_GET_NODE_REF(tab, bitem, result->sr_item.i_node_ref_size);
3264+ else
3265+ result->sr_branch = 0;
3266 }
3267
3268 xtPublic void xt_prev_branch_item_fix(XTTableHPtr XT_UNUSED(tab), XTIndexPtr XT_UNUSED(ind), XTIdxBranchDPtr branch, register XTIdxResultRec *result)
3269@@ -3987,7 +3998,7 @@
3270 * here.
3271 */
3272 if (!(tab->tab_dic.dic_tab_flags & XT_TAB_FLAGS_TEMP_TAB)) {
3273- if (!xt_xlog_flush_log(ot->ot_thread))
3274+ if (!xt_xlog_flush_log(tab->tab_db, ot->ot_thread))
3275 goto failed_2;
3276 if (!il->il_flush(ot))
3277 goto failed_2;
3278
3279=== modified file 'storage/pbxt/src/lock_xt.cc'
3280--- storage/pbxt/src/lock_xt.cc 2009-08-17 11:12:36 +0000
3281+++ storage/pbxt/src/lock_xt.cc 2009-12-10 11:48:17 +0000
3282@@ -1246,7 +1246,7 @@
3283 (void) self;
3284 spl->spl_lock = 0;
3285 #ifdef XT_NO_ATOMICS
3286- xt_init_mutex(self, &spl->spl_mutex);
3287+ xt_init_mutex_with_autoname(self, &spl->spl_mutex);
3288 #endif
3289 #ifdef DEBUG
3290 spl->spl_locker = 0;
3291
3292=== modified file 'storage/pbxt/src/locklist_xt.h'
3293--- storage/pbxt/src/locklist_xt.h 2009-08-17 11:12:36 +0000
3294+++ storage/pbxt/src/locklist_xt.h 2009-12-10 11:48:17 +0000
3295@@ -24,11 +24,16 @@
3296 #ifndef __xt_locklist_h__
3297 #define __xt_locklist_h__
3298
3299+/*
3300+ * XT_THREAD_LOCK_INFO and DEBUG_LOCKING code must be updated to avoid calls to xt_get_self() as it can be called before hton->slot is
3301+ * assigned by MySQL which is used by xt_get_self()
3302+ */
3303+
3304 #ifdef DEBUG
3305-#define XT_THREAD_LOCK_INFO
3306+//#define XT_THREAD_LOCK_INFO
3307 #ifndef XT_WIN
3308 /* We need DEBUG_LOCKING in order to enable pthread function wrappers */
3309-#define DEBUG_LOCKING
3310+//#define DEBUG_LOCKING
3311 #endif
3312 #endif
3313
3314
3315=== modified file 'storage/pbxt/src/memory_xt.cc'
3316--- storage/pbxt/src/memory_xt.cc 2009-09-03 06:15:03 +0000
3317+++ storage/pbxt/src/memory_xt.cc 2009-12-10 11:48:17 +0000
3318@@ -34,7 +34,7 @@
3319 #include "trace_xt.h"
3320
3321 #ifdef DEBUG
3322-//#define RECORD_MM
3323+#define RECORD_MM
3324 #endif
3325
3326 #ifdef DEBUG
3327@@ -367,9 +367,8 @@
3328 return(-1);
3329 }
3330
3331-static long mm_add_pointer(void *ptr, u_int id)
3332+static long mm_add_pointer(void *ptr, u_int XT_UNUSED(id))
3333 {
3334-#pragma unused(id)
3335 register int i, n, guess;
3336
3337 if (mm_nr_in_use == mm_total_allocated) {
3338
3339=== modified file 'storage/pbxt/src/myxt_xt.cc'
3340--- storage/pbxt/src/myxt_xt.cc 2009-09-03 06:15:03 +0000
3341+++ storage/pbxt/src/myxt_xt.cc 2009-12-10 11:48:17 +0000
3342@@ -36,7 +36,7 @@
3343 #include <drizzled/current_session.h>
3344 #include <drizzled/sql_lex.h>
3345 #include <drizzled/session.h>
3346-extern "C" struct charset_info_st *session_charset(Session *session);
3347+//extern "C" struct charset_info_st *session_charset(Session *session);
3348 extern pthread_key_t THR_Session;
3349 #else
3350 #include "mysql_priv.h"
3351@@ -171,7 +171,9 @@
3352
3353 for (u_int i=0; i<ind->mi_seg_count && (int) k_length > 0; i++, old += keyseg->length, keyseg++)
3354 {
3355+#ifndef DRIZZLED
3356 enum ha_base_keytype type = (enum ha_base_keytype) keyseg->type;
3357+#endif
3358 u_int length = keyseg->length < k_length ? keyseg->length : k_length;
3359 u_int char_length;
3360 xtWord1 *pos;
3361@@ -192,14 +194,18 @@
3362 pos = old;
3363 if (keyseg->flag & HA_SPACE_PACK) {
3364 uchar *end = pos + length;
3365+#ifndef DRIZZLED
3366 if (type != HA_KEYTYPE_NUM) {
3367+#endif
3368 while (end > pos && end[-1] == ' ')
3369 end--;
3370+#ifndef DRIZZLED
3371 }
3372 else {
3373 while (pos < end && pos[0] == ' ')
3374 pos++;
3375 }
3376+#endif
3377 k_length -= length;
3378 length = (u_int) (end-pos);
3379 FIX_LENGTH(cs, pos, length, char_length);
3380@@ -276,6 +282,7 @@
3381 char_length= ((cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length);
3382
3383 pos = record + keyseg->start;
3384+#ifndef DRIZZLED
3385 if (type == HA_KEYTYPE_BIT)
3386 {
3387 if (keyseg->bit_length)
3388@@ -289,17 +296,22 @@
3389 key+= length;
3390 continue;
3391 }
3392+#endif
3393 if (keyseg->flag & HA_SPACE_PACK)
3394 {
3395 end = pos + length;
3396+#ifndef DRIZZLED
3397 if (type != HA_KEYTYPE_NUM) {
3398+#endif
3399 while (end > pos && end[-1] == ' ')
3400 end--;
3401+#ifndef DRIZZLED
3402 }
3403 else {
3404 while (pos < end && pos[0] == ' ')
3405 pos++;
3406 }
3407+#endif
3408 length = (u_int) (end-pos);
3409 FIX_LENGTH(cs, pos, length, char_length);
3410 store_key_length_inc(key,char_length);
3411@@ -333,6 +345,7 @@
3412 if (keyseg->flag & HA_SWAP_KEY)
3413 { /* Numerical column */
3414 #ifdef HAVE_ISNAN
3415+#ifndef DRIZZLED
3416 if (type == HA_KEYTYPE_FLOAT)
3417 {
3418 float nr;
3419@@ -345,7 +358,9 @@
3420 continue;
3421 }
3422 }
3423- else if (type == HA_KEYTYPE_DOUBLE) {
3424+ else
3425+#endif
3426+ if (type == HA_KEYTYPE_DOUBLE) {
3427 double nr;
3428
3429 float8get(nr,pos);
3430@@ -414,6 +429,7 @@
3431 char_length= ((cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length);
3432
3433 pos = record + keyseg->start;
3434+#ifndef DRIZZLED
3435 if (type == HA_KEYTYPE_BIT)
3436 {
3437 if (keyseg->bit_length)
3438@@ -427,17 +443,22 @@
3439 key+= length;
3440 continue;
3441 }
3442+#endif
3443 if (keyseg->flag & HA_SPACE_PACK)
3444 {
3445 end = pos + length;
3446+#ifndef DRIZZLED
3447 if (type != HA_KEYTYPE_NUM) {
3448+#endif
3449 while (end > pos && end[-1] == ' ')
3450 end--;
3451+#ifndef DRIZZLED
3452 }
3453 else {
3454 while (pos < end && pos[0] == ' ')
3455 pos++;
3456 }
3457+#endif
3458 length = (u_int) (end-pos);
3459 FIX_LENGTH(cs, pos, length, char_length);
3460 store_key_length_inc(key,char_length);
3461@@ -471,6 +492,7 @@
3462 if (keyseg->flag & HA_SWAP_KEY)
3463 { /* Numerical column */
3464 #ifdef HAVE_ISNAN
3465+#ifndef DRIZZLED
3466 if (type == HA_KEYTYPE_FLOAT)
3467 {
3468 float nr;
3469@@ -483,7 +505,9 @@
3470 continue;
3471 }
3472 }
3473- else if (type == HA_KEYTYPE_DOUBLE) {
3474+ else
3475+#endif
3476+ if (type == HA_KEYTYPE_DOUBLE) {
3477 double nr;
3478
3479 float8get(nr,pos);
3480@@ -622,7 +646,6 @@
3481 case MYSQL_TYPE_SET:
3482 case MYSQL_TYPE_GEOMETRY:
3483 #else
3484- case DRIZZLE_TYPE_TINY:
3485 case DRIZZLE_TYPE_LONG:
3486 case DRIZZLE_TYPE_DOUBLE:
3487 case DRIZZLE_TYPE_NULL:
3488@@ -740,7 +763,6 @@
3489 case MYSQL_TYPE_SET:
3490 case MYSQL_TYPE_GEOMETRY:
3491 #else
3492- case DRIZZLE_TYPE_TINY:
3493 case DRIZZLE_TYPE_LONG:
3494 case DRIZZLE_TYPE_DOUBLE:
3495 case DRIZZLE_TYPE_NULL:
3496@@ -825,6 +847,7 @@
3497 }
3498 record[keyseg->null_pos] &= ~keyseg->null_bit;
3499 }
3500+#ifndef DRIZZLED
3501 if (keyseg->type == HA_KEYTYPE_BIT)
3502 {
3503 uint length = keyseg->length;
3504@@ -845,6 +868,7 @@
3505 key+= length;
3506 continue;
3507 }
3508+#endif
3509 if (keyseg->flag & HA_SPACE_PACK)
3510 {
3511 uint length;
3512@@ -854,16 +878,20 @@
3513 goto err;
3514 #endif
3515 pos = record+keyseg->start;
3516+#ifndef DRIZZLED
3517 if (keyseg->type != (int) HA_KEYTYPE_NUM)
3518 {
3519+#endif
3520 memcpy(pos,key,(size_t) length);
3521 bfill(pos+length,keyseg->length-length,' ');
3522+#ifndef DRIZZLED
3523 }
3524 else
3525 {
3526 bfill(pos,keyseg->length-length,' ');
3527 memcpy(pos+keyseg->length-length,key,(size_t) length);
3528 }
3529+#endif
3530 key+=length;
3531 continue;
3532 }
3533@@ -945,7 +973,7 @@
3534 static int my_compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
3535 my_bool part_key, my_bool skip_end_space)
3536 {
3537- uint length= min(a_length,b_length);
3538+ uint length= a_length < b_length ? a_length : b_length;
3539 uchar *end= a+ length;
3540 int flag;
3541
3542@@ -1023,6 +1051,7 @@
3543 get_key_pack_length(seg_len, pack_len, key_data);
3544 key_data += seg_len;
3545 break;
3546+#ifndef DRIZZLED
3547 case HA_KEYTYPE_NUM: {
3548 /* Numeric key */
3549 if (keyseg->flag & HA_SPACE_PACK)
3550@@ -1035,15 +1064,16 @@
3551 case HA_KEYTYPE_INT8:
3552 case HA_KEYTYPE_SHORT_INT:
3553 case HA_KEYTYPE_USHORT_INT:
3554+ case HA_KEYTYPE_INT24:
3555+ case HA_KEYTYPE_FLOAT:
3556+ case HA_KEYTYPE_BIT:
3557+#endif
3558 case HA_KEYTYPE_LONG_INT:
3559 case HA_KEYTYPE_ULONG_INT:
3560- case HA_KEYTYPE_INT24:
3561 case HA_KEYTYPE_UINT24:
3562- case HA_KEYTYPE_FLOAT:
3563 case HA_KEYTYPE_DOUBLE:
3564 case HA_KEYTYPE_LONGLONG:
3565 case HA_KEYTYPE_ULONGLONG:
3566- case HA_KEYTYPE_BIT:
3567 key_data += keyseg->length;
3568 break;
3569 case HA_KEYTYPE_END:
3570@@ -1190,6 +1220,7 @@
3571 b += b_length;
3572 break;
3573 }
3574+#ifndef DRIZZLED
3575 case HA_KEYTYPE_INT8:
3576 {
3577 int i_1 = (int) *((signed char *) a);
3578@@ -1218,6 +1249,7 @@
3579 b += keyseg->length;
3580 break;
3581 }
3582+#endif
3583 case HA_KEYTYPE_LONG_INT: {
3584 int32 l_1 = sint4korr(a);
3585 int32 l_2 = sint4korr(b);
3586@@ -1236,6 +1268,7 @@
3587 b += keyseg->length;
3588 break;
3589 }
3590+#ifndef DRIZZLED
3591 case HA_KEYTYPE_INT24: {
3592 int32 l_1 = sint3korr(a);
3593 int32 l_2 = sint3korr(b);
3594@@ -1245,6 +1278,7 @@
3595 b += keyseg->length;
3596 break;
3597 }
3598+#endif
3599 case HA_KEYTYPE_UINT24: {
3600 int32 l_1 = uint3korr(a);
3601 int32 l_2 = uint3korr(b);
3602@@ -1254,6 +1288,7 @@
3603 b += keyseg->length;
3604 break;
3605 }
3606+#ifndef DRIZZLED
3607 case HA_KEYTYPE_FLOAT: {
3608 float f_1, f_2;
3609
3610@@ -1270,6 +1305,7 @@
3611 b += keyseg->length;
3612 break;
3613 }
3614+#endif
3615 case HA_KEYTYPE_DOUBLE: {
3616 double d_1, d_2;
3617
3618@@ -1286,6 +1322,7 @@
3619 b += keyseg->length;
3620 break;
3621 }
3622+#ifndef DRIZZLED
3623 case HA_KEYTYPE_NUM: {
3624 /* Numeric key */
3625 if (keyseg->flag & HA_SPACE_PACK) {
3626@@ -1339,6 +1376,7 @@
3627 b += b_length;
3628 break;
3629 }
3630+#endif
3631 #ifdef HAVE_LONG_LONG
3632 case HA_KEYTYPE_LONGLONG: {
3633 longlong ll_a = sint8korr(a);
3634@@ -1359,9 +1397,11 @@
3635 break;
3636 }
3637 #endif
3638+#ifndef DRIZZLED
3639 case HA_KEYTYPE_BIT:
3640 /* TODO: What here? */
3641 break;
3642+#endif
3643 case HA_KEYTYPE_END: /* Ready */
3644 goto end;
3645 }
3646@@ -1410,16 +1450,19 @@
3647 key_length = has_null + a_length + pack_len;
3648 break;
3649 }
3650+#ifndef DRIZZLED
3651 case HA_KEYTYPE_INT8:
3652 case HA_KEYTYPE_SHORT_INT:
3653 case HA_KEYTYPE_USHORT_INT:
3654+ case HA_KEYTYPE_INT24:
3655+ case HA_KEYTYPE_FLOAT:
3656+#endif
3657 case HA_KEYTYPE_LONG_INT:
3658 case HA_KEYTYPE_ULONG_INT:
3659- case HA_KEYTYPE_INT24:
3660 case HA_KEYTYPE_UINT24:
3661- case HA_KEYTYPE_FLOAT:
3662 case HA_KEYTYPE_DOUBLE:
3663 break;
3664+#ifndef DRIZZLED
3665 case HA_KEYTYPE_NUM: {
3666 /* Numeric key */
3667 if (keyseg->flag & HA_SPACE_PACK) {
3668@@ -1428,14 +1471,17 @@
3669 }
3670 break;
3671 }
3672+#endif
3673 #ifdef HAVE_LONG_LONG
3674 case HA_KEYTYPE_LONGLONG:
3675 case HA_KEYTYPE_ULONGLONG:
3676 break;
3677 #endif
3678+#ifndef DRIZZLED
3679 case HA_KEYTYPE_BIT:
3680 /* TODO: What here? */
3681 break;
3682+#endif
3683 case HA_KEYTYPE_END: /* Ready */
3684 break;
3685 }
3686@@ -1486,7 +1532,7 @@
3687 return row_size;
3688 }
3689
3690-static xtWord4 mx_store_row(XTOpenTablePtr ot, xtWord4 row_size, char *rec_buff)
3691+xtPublic xtWord4 myxt_store_row_data(XTOpenTablePtr ot, xtWord4 row_size, char *rec_buff)
3692 {
3693 TABLE *table = ot->ot_table->tab_dic.dic_my_table;
3694 char *sdata;
3695@@ -1614,8 +1660,9 @@
3696 }
3697
3698 /* Unload from PBXT variable length format to the MySQL row format. */
3699-xtPublic xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt)
3700+xtPublic xtWord4 myxt_load_row_data(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt)
3701 {
3702+ xtWord1 *input_buf = source_buf;
3703 TABLE *table;
3704 xtWord4 len;
3705 Field *curr_field;
3706@@ -1624,7 +1671,7 @@
3707
3708 if (!(table = ot->ot_table->tab_dic.dic_my_table)) {
3709 xt_register_taberr(XT_REG_CONTEXT, XT_ERR_NO_DICTIONARY, ot->ot_table->tab_name);
3710- return FAILED;
3711+ return 0;
3712 }
3713
3714 /* According to the InnoDB implementation:
3715@@ -1657,7 +1704,7 @@
3716 default: // Length byte
3717 if (*source_buf > 240) {
3718 xt_register_xterr(XT_REG_CONTEXT, XT_ERR_BAD_RECORD_FORMAT);
3719- return FAILED;
3720+ return 0;
3721 }
3722 len = *source_buf;
3723 source_buf++;
3724@@ -1671,7 +1718,12 @@
3725
3726 source_buf += len;
3727 }
3728- return OK;
3729+ return (xtWord4) (source_buf - input_buf);
3730+}
3731+
3732+xtPublic xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt)
3733+{
3734+ return myxt_load_row_data(ot, source_buf, dest_buff, col_cnt) != 0;
3735 }
3736
3737 xtPublic xtBool myxt_find_column(XTOpenTablePtr ot, u_int *col_idx, const char *col_name)
3738@@ -1784,7 +1836,7 @@
3739 else {
3740 xtWord4 row_size;
3741
3742- if (!(row_size = mx_store_row(ot, XT_REC_EXT_HEADER_SIZE, rec_buff)))
3743+ if (!(row_size = myxt_store_row_data(ot, XT_REC_EXT_HEADER_SIZE, rec_buff)))
3744 return FAILED;
3745 if (row_size - XT_REC_FIX_EXT_HEADER_DIFF <= ot->ot_rec_size) {
3746 rec_info->ri_fix_rec_buf = (XTTabRecFixDPtr) &ot->ot_row_wbuffer[XT_REC_FIX_EXT_HEADER_DIFF];
3747@@ -1951,7 +2003,7 @@
3748
3749 #ifdef DRIZZLED
3750 share->init(db_name, 0, name, path);
3751- if ((error = open_table_def(thd, share)) ||
3752+ if ((error = open_table_def(*thd, share)) ||
3753 (error = open_table_from_share(thd, share, "", 0, (uint32_t) READ_ALL, 0, table, OTM_OPEN)))
3754 {
3755 xt_free(self, table);
3756@@ -1995,7 +2047,7 @@
3757 return NULL;
3758 }
3759
3760-#if MYSQL_VERSION_ID >= 60003
3761+#if MYSQL_VERSION_ID >= 50404
3762 if ((error = open_table_from_share(thd, share, "", 0, (uint) READ_ALL, 0, table, OTM_OPEN)))
3763 #else
3764 if ((error = open_table_from_share(thd, share, "", 0, (uint) READ_ALL, 0, table, FALSE)))
3765@@ -2145,7 +2197,10 @@
3766 if (options & HA_OPTION_PACK_KEYS ||
3767 (index->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY | HA_SPACE_PACK_USED)))
3768 {
3769- if (key_part->length > 8 && (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_NUM ||
3770+ if (key_part->length > 8 && (type == HA_KEYTYPE_TEXT ||
3771+#ifndef DRIZZLED
3772+ type == HA_KEYTYPE_NUM ||
3773+#endif
3774 (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
3775 {
3776 /* No blobs here */
3777@@ -2213,8 +2268,12 @@
3778 else if (field->type() == MYSQL_TYPE_ENUM) {
3779 switch (seg->length) {
3780 case 2:
3781+#ifdef DRIZZLED
3782+ ASSERT_NS(FALSE);
3783+#else
3784 seg->type = HA_KEYTYPE_USHORT_INT;
3785 break;
3786+#endif
3787 case 3:
3788 seg->type = HA_KEYTYPE_UINT24;
3789 break;
3790@@ -2675,7 +2734,11 @@
3791 if (!(my_tab = my_open_table(self, db, tab_path)))
3792 return FAILED;
3793 dic->dic_my_table = my_tab;
3794+#ifdef DRIZZLED
3795+ dic->dic_def_ave_row_size = (xtWord8) my_tab->s->getAvgRowLength();
3796+#else
3797 dic->dic_def_ave_row_size = (xtWord8) my_tab->s->avg_row_length;
3798+#endif
3799 myxt_setup_dictionary(self, dic);
3800 dic->dic_keys = (XTIndexPtr *) xt_calloc(self, sizeof(XTIndexPtr) * TS(my_tab)->keys);
3801 for (uint i=0; i<TS(my_tab)->keys; i++)
3802@@ -2805,8 +2868,10 @@
3803
3804 static char *my_type_to_string(XTThreadPtr self, Field *field, TABLE *XT_UNUSED(my_tab))
3805 {
3806- char buffer[MAX_FIELD_WIDTH + 400], *ptr;
3807+ char buffer[MAX_FIELD_WIDTH + 400];
3808+ const char *ptr;
3809 String type((char *) buffer, sizeof(buffer), system_charset_info);
3810+ xtWord4 len;
3811
3812 /* GOTCHA:
3813 * - Above sets the string length to the same as the buffer,
3814@@ -2817,10 +2882,17 @@
3815 */
3816 type.length(0);
3817 field->sql_type(type);
3818- ptr = type.c_ptr();
3819+ ptr = type.ptr();
3820+ len = type.length();
3821+
3822+ if (len >= sizeof(buffer))
3823+ len = sizeof(buffer)-1;
3824+
3825 if (ptr != buffer)
3826- xt_strcpy(sizeof(buffer), buffer, ptr);
3827+ xt_strcpy(sizeof(buffer), buffer, ptr);
3828
3829+ buffer[len] = 0;
3830+
3831 if (field->has_charset()) {
3832 /* Always include the charset so that we can compare types
3833 * for FK/PK releations.
3834@@ -2877,6 +2949,10 @@
3835
3836 xtPublic void myxt_static_convert_identifier(XTThreadPtr XT_UNUSED(self), MX_CHARSET_INFO *cs, char *from, char *to, size_t to_len)
3837 {
3838+#ifdef DRIZZLED
3839+ ((void *)cs);
3840+ xt_strcpy(to_len, to, from);
3841+#else
3842 uint errors;
3843
3844 /*
3845@@ -2888,11 +2964,16 @@
3846 xt_strcpy(to_len, to, from);
3847 else
3848 strconvert(cs, from, &my_charset_utf8_general_ci, to, to_len, &errors);
3849+#endif
3850 }
3851
3852 // cs == current_thd->charset()
3853 xtPublic char *myxt_convert_identifier(XTThreadPtr self, MX_CHARSET_INFO *cs, char *from)
3854 {
3855+#ifdef DRIZZLED
3856+ char *to = xt_dup_string(self, from);
3857+ ((void *)cs);
3858+#else
3859 uint errors;
3860 u_int len;
3861 char *to;
3862@@ -2904,6 +2985,7 @@
3863 to = (char *) xt_malloc(self, len);
3864 strconvert(cs, from, &my_charset_utf8_general_ci, to, len, &errors);
3865 }
3866+#endif
3867 return to;
3868 }
3869
3870@@ -2954,9 +3036,9 @@
3871 THD *thd = current_thd;
3872
3873 if (thd)
3874- return thd_charset(thd);
3875+ return (MX_CHARSET_INFO *)thd_charset(thd);
3876 }
3877- return &my_charset_utf8_general_ci;
3878+ return (MX_CHARSET_INFO *)&my_charset_utf8_general_ci;
3879 }
3880
3881 xtPublic void *myxt_create_thread()
3882@@ -3011,12 +3093,26 @@
3883 return NULL;
3884 }
3885
3886- if (!(new_thd = new THD())) {
3887+ if (!(new_thd = new THD)) {
3888 my_thread_end();
3889 xt_register_error(XT_REG_CONTEXT, XT_ERR_MYSQL_ERROR, 0, "Unable to create MySQL thread (THD)");
3890 return NULL;
3891 }
3892
3893+ /*
3894+ * If PBXT is the default storage engine, then creating any THD objects will add extra
3895+ * references to the PBXT plugin object. because the threads are created but PBXT
3896+ * this creates a self reference, and the reference count does not go to zero
3897+ * on shutdown.
3898+ *
3899+ * The server then issues a message that it is forcing shutdown of the plugin.
3900+ *
3901+ * However, the engine reference is not required by the THDs used by PBXT, so
3902+ * I just remove them here.
3903+ */
3904+ plugin_unlock(NULL, new_thd->variables.table_plugin);
3905+ new_thd->variables.table_plugin = NULL;
3906+
3907 new_thd->thread_stack = (char *) &new_thd;
3908 new_thd->store_globals();
3909 lex_start(new_thd);
3910@@ -3051,7 +3147,7 @@
3911 #else
3912 close_thread_tables(thd);
3913 #endif
3914-
3915+
3916 delete thd;
3917
3918 /* Remember that we don't have a THD */
3919@@ -3128,11 +3224,12 @@
3920 const char *stat_name;
3921 u_llong stat_value;
3922 XTStatisticsRec statistics;
3923+ XTDatabaseHPtr db = self->st_database;
3924
3925 xt_gather_statistics(&statistics);
3926 for (u_int rec_id=0; !err && rec_id<XT_STAT_CURRENT_MAX; rec_id++) {
3927 stat_name = xt_get_stat_meta_data(rec_id)->sm_name;
3928- stat_value = xt_get_statistic(&statistics, self->st_database, rec_id);
3929+ stat_value = xt_get_statistic(&statistics, db, rec_id);
3930
3931 col=0;
3932 mx_put_u_llong(table, col++, rec_id+1);
3933@@ -3213,19 +3310,31 @@
3934 my_bitmap_map *buf;
3935 uint size_in_bytes = (((n_bits) + 31) / 32) * 4;
3936
3937- buf = (my_bitmap_map *) xt_malloc(self, size_in_bytes);
3938+ buf = (my_bitmap_map *) xt_malloc(self, size_in_bytes);
3939+
3940+#ifdef DRIZZLED
3941+ map->init(buf, n_bits);
3942+#else
3943 map->bitmap= buf;
3944 map->n_bits= n_bits;
3945 create_last_word_mask(map);
3946 bitmap_clear_all(map);
3947+#endif
3948 }
3949
3950 static void myxt_bitmap_free(XTThreadPtr self, MX_BITMAP *map)
3951 {
3952+#ifdef DRIZZLED
3953+ my_bitmap_map *buf = map->getBitmap();
3954+ if (buf)
3955+ xt_free(self, buf);
3956+ map->setBitmap(NULL);
3957+#else
3958 if (map->bitmap) {
3959 xt_free(self, map->bitmap);
3960 map->bitmap = NULL;
3961 }
3962+#endif
3963 }
3964
3965 /*
3966@@ -3269,3 +3378,29 @@
3967 return col;
3968 }
3969
3970+/*
3971+ * -----------------------------------------------------------------------
3972+ * utilities
3973+ */
3974+
3975+/*
3976+ * MySQL (not sure about Drizzle) first calls hton->init and then assigns the plugin a thread slot
3977+ * which is used by xt_get_self(). This is a problem as pbxt_init() starts a number of daemon threads
3978+ * which could try to use the slot before it is assigned. This code waits till slot is inited.
3979+ * We cannot directly check hton->slot as in some versions of MySQL it can be 0 before init which is a
3980+ * valid value.
3981+ */
3982+extern ulong total_ha;
3983+
3984+xtPublic void myxt_wait_pbxt_plugin_slot_assigned(XTThread *self)
3985+{
3986+#ifdef DRIZZLED
3987+ static LEX_STRING plugin_name = { C_STRING_WITH_LEN("PBXT") };
3988+
3989+ while (!self->t_quit && !Registry::singleton().find(&plugin_name))
3990+ xt_sleep_milli_second(1);
3991+#else
3992+ while(!self->t_quit && (pbxt_hton->slot >= total_ha))
3993+ xt_sleep_milli_second(1);
3994+#endif
3995+}
3996
3997=== modified file 'storage/pbxt/src/myxt_xt.h'
3998--- storage/pbxt/src/myxt_xt.h 2009-09-03 06:15:03 +0000
3999+++ storage/pbxt/src/myxt_xt.h 2009-12-10 11:48:17 +0000
4000@@ -52,8 +52,10 @@
4001 void myxt_print_key(XTIndexPtr ind, xtWord1 *key_value);
4002
4003 xtWord4 myxt_store_row_length(XTOpenTablePtr ot, char *rec_buff);
4004+xtWord4 myxt_store_row_data(XTOpenTablePtr ot, xtWord4 row_size, char *rec_buff);
4005 xtBool myxt_store_row(XTOpenTablePtr ot, XTTabRecInfoPtr rec_info, char *rec_buff);
4006 size_t myxt_load_row_length(XTOpenTablePtr ot, size_t buffer_size, xtWord1 *source_buf, u_int *ret_col_cnt);
4007+xtWord4 myxt_load_row_data(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt);
4008 xtBool myxt_load_row(XTOpenTablePtr ot, xtWord1 *source_buf, xtWord1 *dest_buff, u_int col_cnt);
4009 xtBool myxt_find_column(XTOpenTablePtr ot, u_int *col_idx, const char *col_name);
4010 void myxt_get_column_name(XTOpenTablePtr ot, u_int col_idx, u_int len, char *col_name);
4011@@ -93,4 +95,6 @@
4012 static XTDDColumn *createFromMySQLField(XTThread *self, STRUCT_TABLE *, Field *);
4013 };
4014
4015+void myxt_wait_pbxt_plugin_slot_assigned(XTThread *self);
4016+
4017 #endif
4018
4019=== modified file 'storage/pbxt/src/pbms.h'
4020--- storage/pbxt/src/pbms.h 2009-08-18 07:46:53 +0000
4021+++ storage/pbxt/src/pbms.h 2009-12-10 11:48:17 +0000
4022@@ -344,16 +344,16 @@
4023 int couldBeURL(char *blob_url, int size)
4024 {
4025 if (blob_url && (size < PBMS_BLOB_URL_SIZE)) {
4026- char buffer[PBMS_BLOB_URL_SIZE+1];
4027- u_int32_t db_id = 0;
4028- u_int32_t tab_id = 0;
4029- u_int64_t blob_id = 0;
4030- u_int64_t blob_ref_id = 0;
4031- u_int64_t blob_size = 0;
4032- u_int32_t auth_code = 0;
4033- u_int32_t server_id = 0;
4034- char type, junk[5];
4035- int scanned;
4036+ char buffer[PBMS_BLOB_URL_SIZE+1];
4037+ unsigned long db_id = 0;
4038+ unsigned long tab_id = 0;
4039+ unsigned long long blob_id = 0;
4040+ unsigned long long blob_ref_id = 0;
4041+ unsigned long long blob_size = 0;
4042+ unsigned long auth_code = 0;
4043+ unsigned long server_id = 0;
4044+ char type, junk[5];
4045+ int scanned;
4046
4047 junk[0] = 0;
4048 if (blob_url[size]) { // There is no guarantee that the URL will be null terminated.
4049@@ -364,12 +364,12 @@
4050
4051 scanned = sscanf(blob_url, URL_FMT"%4s", &db_id, &type, &tab_id, &blob_id, &auth_code, &server_id, &blob_ref_id, &blob_size, junk);
4052 if (scanned != 8) {// If junk is found at the end this will also result in an invalid URL.
4053- printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]);
4054+ printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]);
4055 return 0;
4056 }
4057
4058 if (junk[0] || (type != '~' && type != '_')) {
4059- printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]);
4060+ printf("Bad URL \"%s\": scanned = %d, junk: %d, %d, %d, %d\n", blob_url, scanned, junk[0], junk[1], junk[2], junk[3]);
4061 return 0;
4062 }
4063
4064
4065=== modified file 'storage/pbxt/src/pbms_enabled.cc'
4066--- storage/pbxt/src/pbms_enabled.cc 2009-10-06 15:16:01 +0000
4067+++ storage/pbxt/src/pbms_enabled.cc 2009-12-10 11:48:17 +0000
4068@@ -29,15 +29,10 @@
4069 *
4070 */
4071
4072-/*
4073- The following two lines backported by psergey. Remove them when we merge from PBXT again.
4074-*/
4075 #include "xt_config.h"
4076+
4077 #ifdef PBMS_ENABLED
4078
4079-#define PBMS_API pbms_enabled_api
4080-
4081-#include "pbms_enabled.h"
4082 #ifdef DRIZZLED
4083 #include <sys/stat.h>
4084 #include <drizzled/common_includes.h>
4085@@ -47,11 +42,15 @@
4086 #include <mysql/plugin.h>
4087 #define session_alloc(sess, size) thd_alloc(sess, size);
4088 #define current_session current_thd
4089-#endif
4090-
4091-#define GET_BLOB_FIELD(t, i) (Field_blob *)(t->field[t->s->blob_field[i]])
4092-#define DB_NAME(f) (f->table->s->db.str)
4093-#define TAB_NAME(f) (*(f->table_name))
4094+#endif
4095+
4096+#define GET_BLOB_FIELD(t, i) (Field_blob *)(t->field[t->s->blob_field[i]])
4097+#define DB_NAME(f) (f->table->s->db.str)
4098+#define TAB_NAME(f) (*(f->table_name))
4099+
4100+#define PBMS_API pbms_enabled_api
4101+
4102+#include "pbms_enabled.h"
4103
4104 static PBMS_API pbms_api;
4105
4106@@ -242,4 +241,4 @@
4107 return ;
4108 }
4109
4110-#endif
4111\ No newline at end of file
4112+#endif // PBMS_ENABLED
4113
4114=== modified file 'storage/pbxt/src/pbms_enabled.h'
4115--- storage/pbxt/src/pbms_enabled.h 2009-08-18 07:46:53 +0000
4116+++ storage/pbxt/src/pbms_enabled.h 2009-12-10 11:48:17 +0000
4117@@ -35,13 +35,6 @@
4118
4119 #include "pbms.h"
4120
4121-#ifdef DRIZZLED
4122-#include <drizzled/server_includes.h>
4123-#define TABLE Table
4124-#else
4125-#include <mysql_priv.h>
4126-#endif
4127-
4128 /*
4129 * pbms_initialize() should be called from the engines plugIn's 'init()' function.
4130 * The engine_name is the name of your engine, "PBXT" or "InnoDB" for example.
4131
4132=== modified file 'storage/pbxt/src/pthread_xt.cc'
4133--- storage/pbxt/src/pthread_xt.cc 2009-08-18 07:46:53 +0000
4134+++ storage/pbxt/src/pthread_xt.cc 2009-12-10 11:48:17 +0000
4135@@ -578,8 +578,8 @@
4136
4137 xtPublic int xt_p_mutex_destroy(xt_mutex_type *mutex)
4138 {
4139- ASSERT_NS(mutex->mu_init == 12345);
4140- mutex->mu_init = 89898;
4141+ //ASSERT_NS(mutex->mu_init == 12345);
4142+ mutex->mu_init = 11111;
4143 #ifdef XT_THREAD_LOCK_INFO
4144 xt_thread_lock_info_free(&mutex->mu_lock_info);
4145 #endif
4146
4147=== modified file 'storage/pbxt/src/restart_xt.cc'
4148--- storage/pbxt/src/restart_xt.cc 2009-09-03 06:15:03 +0000
4149+++ storage/pbxt/src/restart_xt.cc 2009-12-10 11:48:17 +0000
4150@@ -34,12 +34,16 @@
4151
4152 #include "ha_pbxt.h"
4153
4154+#ifdef DRIZZLED
4155+#include <drizzled/data_home.h>
4156+using drizzled::plugin::Registry;
4157+#endif
4158+
4159 #include "xactlog_xt.h"
4160 #include "database_xt.h"
4161 #include "util_xt.h"
4162 #include "strutil_xt.h"
4163 #include "filesys_xt.h"
4164-#include "restart_xt.h"
4165 #include "myxt_xt.h"
4166 #include "trace_xt.h"
4167
4168@@ -57,13 +61,27 @@
4169 //#define PRINTF xt_ftracef
4170 //#define PRINTF xt_trace
4171
4172-void xt_print_bytes(xtWord1 *buf, u_int len)
4173+/*
4174+ * -----------------------------------------------------------------------
4175+ * GLOBALS
4176+ */
4177+
4178+xtPublic int pbxt_recovery_state;
4179+
4180+/*
4181+ * -----------------------------------------------------------------------
4182+ * UTILITIES
4183+ */
4184+
4185+#ifdef TRACE_RECORD_DATA
4186+static void xt_print_bytes(xtWord1 *buf, u_int len)
4187 {
4188 for (u_int i=0; i<len; i++) {
4189 PRINTF("%02x ", (u_int) *buf);
4190 buf++;
4191 }
4192 }
4193+#endif
4194
4195 void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr record)
4196 {
4197@@ -252,7 +270,7 @@
4198 rec_type = "DELETE";
4199 break;
4200 case XT_LOG_ENT_DELETE_FL:
4201- rec_type = "DELETE-FL-BG";
4202+ rec_type = "DELETE-FL";
4203 break;
4204 case XT_LOG_ENT_UPDATE_BG:
4205 rec_type = "UPDATE-BG";
4206@@ -320,6 +338,11 @@
4207 case XT_LOG_ENT_END_OF_LOG:
4208 rec_type = "END OF LOG";
4209 break;
4210+ case XT_LOG_ENT_PREPARE:
4211+ rec_type = "PREPARE";
4212+ xn_id = XT_GET_DISK_4(record->xp.xp_xact_id_4);
4213+ xn_set = TRUE;
4214+ break;
4215 }
4216
4217 if (log)
4218@@ -327,6 +350,8 @@
4219 PRINTF("%s ", rec_type);
4220 if (type)
4221 PRINTF("op=%lu tab=%lu %s=%lu ", (u_long) op_no, (u_long) tab_id, type, (u_long) rec_id);
4222+ else if (tab_id)
4223+ PRINTF("tab=%lu ", (u_long) tab_id);
4224 if (row_id)
4225 PRINTF("row=%lu ", (u_long) row_id);
4226 if (log_id)
4227@@ -459,6 +484,7 @@
4228 }
4229 return OK;
4230 }
4231+
4232 ws->ws_tab_gone = tab_id;
4233 return FAILED;
4234 }
4235@@ -629,6 +655,7 @@
4236 xtWord1 *rec_data = NULL;
4237 XTTabRecFreeDPtr free_data;
4238
4239+ ASSERT(ot->ot_thread == self);
4240 if (tab->tab_dic.dic_key_count == 0)
4241 check_index = FALSE;
4242
4243@@ -1300,7 +1327,7 @@
4244 * These operations are applied even though operations
4245 * in sequence are missing.
4246 */
4247-xtBool xres_sync_operations(XTThreadPtr self, XTDatabaseHPtr db, XTWriterStatePtr ws)
4248+static xtBool xres_sync_operations(XTThreadPtr self, XTDatabaseHPtr db, XTWriterStatePtr ws)
4249 {
4250 u_int edx;
4251 XTTableEntryPtr te_ptr;
4252@@ -1881,15 +1908,6 @@
4253 void XTXactRestart::xres_recover_progress(XTThreadPtr self, XTOpenFilePtr *of, int perc)
4254 {
4255 #ifdef XT_USE_GLOBAL_DB
4256- if (!perc) {
4257- char file_path[PATH_MAX];
4258-
4259- xt_strcpy(PATH_MAX, file_path, xres_db->db_main_path);
4260- xt_add_pbxt_file(PATH_MAX, file_path, "recovery-progress");
4261- *of = xt_open_file(self, file_path, XT_FS_CREATE | XT_FS_MAKE_PATH);
4262- xt_set_eof_file(self, *of, 0);
4263- }
4264-
4265 if (perc > 100) {
4266 char file_path[PATH_MAX];
4267
4268@@ -1905,6 +1923,15 @@
4269 else {
4270 char number[40];
4271
4272+ if (!*of) {
4273+ char file_path[PATH_MAX];
4274+
4275+ xt_strcpy(PATH_MAX, file_path, xres_db->db_main_path);
4276+ xt_add_pbxt_file(PATH_MAX, file_path, "recovery-progress");
4277+ *of = xt_open_file(self, file_path, XT_FS_CREATE | XT_FS_MAKE_PATH);
4278+ xt_set_eof_file(self, *of, 0);
4279+ }
4280+
4281 sprintf(number, "%d", perc);
4282 if (!xt_pwrite_file(*of, 0, strlen(number), number, &self->st_statistics.st_x, self))
4283 xt_throw(self);
4284@@ -1927,10 +1954,11 @@
4285 off_t bytes_to_read;
4286 volatile xtBool print_progress = FALSE;
4287 volatile off_t perc_size = 0, next_goal = 0;
4288- int perc_complete = 1;
4289+ int perc_complete = 1, perc_to_write = 1;
4290 XTOpenFilePtr progress_file = NULL;
4291 xtBool min_ram_xn_id_set = FALSE;
4292 u_int log_count;
4293+ time_t start_time;
4294
4295 memset(&ws, 0, sizeof(ws));
4296
4297@@ -1955,12 +1983,11 @@
4298 /* Don't print anything about recovering an empty database: */
4299 if (bytes_to_read != 0)
4300 xt_logf(XT_NT_INFO, "PBXT: Recovering from %lu-%llu, bytes to read: %llu\n", (u_long) xres_cp_log_id, (u_llong) xres_cp_log_offset, (u_llong) bytes_to_read);
4301- if (bytes_to_read >= 10*1024*1024) {
4302- print_progress = TRUE;
4303- perc_size = bytes_to_read / 100;
4304- next_goal = perc_size;
4305- xres_recover_progress(self, &progress_file, 0);
4306- }
4307+
4308+ print_progress = FALSE;
4309+ start_time = time(NULL);
4310+ perc_size = bytes_to_read / 100;
4311+ next_goal = perc_size;
4312
4313 if (!db->db_xlog.xlog_seq_start(&ws.ws_seqread, xres_cp_log_id, xres_cp_log_offset, FALSE)) {
4314 ok = FALSE;
4315@@ -1983,17 +2010,28 @@
4316 #ifdef PRINT_LOG_ON_RECOVERY
4317 xt_print_log_record(ws.ws_seqread.xseq_rec_log_id, ws.ws_seqread.xseq_rec_log_offset, record);
4318 #endif
4319- if (print_progress && bytes_read > next_goal) {
4320- if (((perc_complete - 1) % 25) == 0)
4321- xt_logf(XT_NT_INFO, "PBXT: ");
4322- if ((perc_complete % 25) == 0)
4323- xt_logf(XT_NT_INFO, "%2d\n", (int) perc_complete);
4324- else
4325- xt_logf(XT_NT_INFO, "%2d ", (int) perc_complete);
4326- xt_log_flush(self);
4327- xres_recover_progress(self, &progress_file, perc_complete);
4328- next_goal += perc_size;
4329- perc_complete++;
4330+ if (bytes_read >= next_goal) {
4331+ while (bytes_read >= next_goal) {
4332+ next_goal += perc_size;
4333+ perc_complete++;
4334+ }
4335+ if (!print_progress) {
4336+ if (time(NULL) - start_time > 2)
4337+ print_progress = TRUE;
4338+ }
4339+ if (print_progress) {
4340+ while (perc_to_write < perc_complete) {
4341+ if (((perc_to_write - 1) % 25) == 0)
4342+ xt_logf(XT_NT_INFO, "PBXT: ");
4343+ if ((perc_to_write % 25) == 0)
4344+ xt_logf(XT_NT_INFO, "%2d\n", (int) perc_to_write);
4345+ else
4346+ xt_logf(XT_NT_INFO, "%2d ", (int) perc_to_write);
4347+ xt_log_flush(self);
4348+ xres_recover_progress(self, &progress_file, perc_to_write);
4349+ perc_to_write++;
4350+ }
4351+ }
4352 }
4353 switch (record->xl.xl_status_1) {
4354 case XT_LOG_ENT_HEADER:
4355@@ -2053,8 +2091,11 @@
4356 xact->xd_end_xn_id = xn_id;
4357 xact->xd_flags |= XT_XN_XAC_ENDED | XT_XN_XAC_SWEEP;
4358 xact->xd_flags &= ~XT_XN_XAC_RECOVERED; // We can expect an end record on cleanup!
4359+ xact->xd_flags &= ~XT_XN_XAC_PREPARED; // Prepared transactions cannot be swept!
4360 if (record->xl.xl_status_1 == XT_LOG_ENT_COMMIT)
4361 xact->xd_flags |= XT_XN_XAC_COMMITTED;
4362+ if (xt_sl_get_size(db->db_xn_xa_list) > 0)
4363+ xt_xn_delete_xa_data_by_xact(db, xn_id, self);
4364 }
4365 break;
4366 case XT_LOG_ENT_CLEANUP:
4367@@ -2071,6 +2112,14 @@
4368 rec_log_id = XT_GET_DISK_4(record->xl.xl_log_id_4);
4369 xt_dl_set_to_delete(self, db, rec_log_id);
4370 break;
4371+ case XT_LOG_ENT_PREPARE:
4372+ xn_id = XT_GET_DISK_4(record->xp.xp_xact_id_4);
4373+ if ((xact = xt_xn_get_xact(db, xn_id, self))) {
4374+ xact->xd_flags |= XT_XN_XAC_PREPARED;
4375+ if (!xt_xn_store_xa_data(db, xn_id, record->xp.xp_xa_len_1, record->xp.xp_xa_data, self))
4376+ xt_throw(self);
4377+ }
4378+ break;
4379 default:
4380 xt_xres_apply_in_order(self, &ws, ws.ws_seqread.xseq_rec_log_id, ws.ws_seqread.xseq_rec_log_offset, record);
4381 break;
4382@@ -2534,7 +2583,8 @@
4383 /* This condition means we could checkpoint: */
4384 if (!(xt_sl_get_size(db->db_datalogs.dlc_to_delete) == 0 &&
4385 xt_sl_get_size(db->db_datalogs.dlc_deleted) == 0 &&
4386- xt_comp_log_pos(log_id, log_offset, db->db_restart.xres_cp_log_id, db->db_restart.xres_cp_log_offset) <= 0))
4387+ xt_comp_log_pos(log_id, log_offset, db->db_restart.xres_cp_log_id, db->db_restart.xres_cp_log_offset) <= 0) &&
4388+ xt_sl_get_size(db->db_xn_xa_list) == 0)
4389 break;
4390
4391 xres_cp_wait_for_log_writer(self, db, 400);
4392@@ -2654,7 +2704,7 @@
4393 * until they are flushed.
4394 */
4395 /* This is an alternative to the above.
4396- if (!xt_xlog_flush_log(self))
4397+ if (!xt_xlog_flush_log(db, self))
4398 xt_throw(self);
4399 */
4400 xt_lock_mutex_ns(&db->db_wr_lock);
4401@@ -2776,6 +2826,14 @@
4402 size_t chk_size = 0;
4403 u_int no_of_logs = 0;
4404
4405+ /* As long as we have outstanding XA transactions, we may not checkpoint! */
4406+ if (xt_sl_get_size(db->db_xn_xa_list) > 0) {
4407+#ifdef DEBUG
4408+ printf("Checkpoint must wait\n");
4409+#endif
4410+ return OK;
4411+ }
4412+
4413 #ifdef NEVER_CHECKPOINT
4414 return OK;
4415 #endif
4416@@ -3183,7 +3241,7 @@
4417 * D A T A B A S E R E C O V E R Y T H R E A D
4418 */
4419
4420-extern XTDatabaseHPtr pbxt_database;
4421+
4422 static XTThreadPtr xres_recovery_thread;
4423
4424 static void *xn_xres_run_recovery_thread(XTThreadPtr self)
4425@@ -3193,18 +3251,18 @@
4426 if (!(mysql_thread = (THD *) myxt_create_thread()))
4427 xt_throw(self);
4428
4429- while (!xres_recovery_thread->t_quit && !ha_resolve_by_legacy_type(mysql_thread, DB_TYPE_PBXT))
4430- xt_sleep_milli_second(1);
4431+ myxt_wait_pbxt_plugin_slot_assigned(self);
4432
4433 if (!xres_recovery_thread->t_quit) {
4434- /* {GLOBAL-DB}
4435- * It can happen that something will just get in before this
4436- * thread and open/recover the database!
4437- */
4438- if (!pbxt_database) {
4439- try_(a) {
4440+ try_(a) {
4441+ /* {GLOBAL-DB}
4442+ * It can happen that something will just get in before this
4443+ * thread and open/recover the database!
4444+ */
4445+ if (!pbxt_database) {
4446 xt_open_database(self, mysql_real_data_home, TRUE);
4447- /* This can be done at the same time by a foreground thread,
4448+ /* {GLOBAL-DB}
4449+ * This can be done at the same time as the recovery thread,
4450 * strictly speaking I need a lock.
4451 */
4452 if (!pbxt_database) {
4453@@ -3212,11 +3270,22 @@
4454 xt_heap_reference(self, pbxt_database);
4455 }
4456 }
4457- catch_(a) {
4458- xt_log_and_clear_exception(self);
4459- }
4460- cont_(a);
4461- }
4462+ else
4463+ xt_use_database(self, pbxt_database, XT_FOR_USER);
4464+
4465+ pbxt_recovery_state = XT_RECOVER_DONE;
4466+
4467+ /* {WAIT-FOR-SW-AFTER-RECOV}
4468+ * Moved to here...
4469+ */
4470+ xt_wait_for_sweeper(self, self->st_database, 0);
4471+
4472+ pbxt_recovery_state = XT_RECOVER_SWEPT;
4473+ }
4474+ catch_(a) {
4475+ xt_log_and_clear_exception(self);
4476+ }
4477+ cont_(a);
4478 }
4479
4480 /*
4481@@ -3261,11 +3330,12 @@
4482 sprintf(name, "DB-RECOVERY-%s", xt_last_directory_of_path(mysql_real_data_home));
4483 xt_remove_dir_char(name);
4484
4485+ pbxt_recovery_state = XT_RECOVER_PENDING;
4486 xres_recovery_thread = xt_create_daemon(self, name);
4487 xt_run_thread(self, xres_recovery_thread, xn_xres_run_recovery_thread);
4488 }
4489
4490-xtPublic void xt_xres_wait_for_recovery(XTThreadPtr self)
4491+xtPublic void xt_xres_terminate_recovery(XTThreadPtr self)
4492 {
4493 XTThreadPtr thr_rec;
4494
4495
4496=== modified file 'storage/pbxt/src/restart_xt.h'
4497--- storage/pbxt/src/restart_xt.h 2009-09-03 06:15:03 +0000
4498+++ storage/pbxt/src/restart_xt.h 2009-12-10 11:48:17 +0000
4499@@ -37,6 +37,8 @@
4500 struct XTDatabase;
4501 struct XTTable;
4502
4503+extern int pbxt_recovery_state;
4504+
4505 typedef struct XTWriterState {
4506 struct XTDatabase *ws_db;
4507 xtBool ws_in_recover;
4508@@ -132,6 +134,16 @@
4509 void xt_dump_xlogs(struct XTDatabase *db, xtLogID start_log);
4510
4511 void xt_xres_start_database_recovery(XTThreadPtr self);
4512-void xt_xres_wait_for_recovery(XTThreadPtr self);
4513+void xt_xres_terminate_recovery(XTThreadPtr self);
4514+
4515+#define XT_RECOVER_PENDING 0
4516+#define XT_RECOVER_DONE 1
4517+#define XT_RECOVER_SWEPT 2
4518+
4519+inline void xt_xres_wait_for_recovery(XTThreadPtr XT_UNUSED(self), int state)
4520+{
4521+ while (pbxt_recovery_state < state)
4522+ xt_sleep_milli_second(100);
4523+}
4524
4525 #endif
4526
4527=== modified file 'storage/pbxt/src/strutil_xt.cc'
4528--- storage/pbxt/src/strutil_xt.cc 2009-10-26 11:35:42 +0000
4529+++ storage/pbxt/src/strutil_xt.cc 2009-12-10 11:48:17 +0000
4530@@ -21,8 +21,10 @@
4531 * H&G2JCtL
4532 */
4533
4534-#include "mysql_priv.h"
4535 #include "xt_config.h"
4536+
4537+#include <stdio.h>
4538+#include <string.h>
4539 #include <ctype.h>
4540
4541 #include "strutil_xt.h"
4542@@ -107,13 +109,17 @@
4543 *dest = 0;
4544 return;
4545 }
4546- /* If temporary file */
4547- if (!is_prefix(path, mysql_data_home) &&
4548+
4549+ /* {INVALID-OLD-TABLE-FIX}
4550+ * I have changed the implementation of
4551+ * this bug fix (see {INVALID-OLD-TABLE-FIX}).
4552+ if (!is_prefix(path, mysql_data_home) &&
4553 !is_prefix(path, mysql_real_data_home))
4554 {
4555 *dest= 0;
4556 return;
4557 }
4558+ */
4559
4560 ptr = path + len - 1;
4561 while (ptr != path && !XT_IS_DIR_CHAR(*ptr))
4562@@ -374,7 +380,7 @@
4563 /* Version number must also be set in configure.in! */
4564 xtPublic c_char *xt_get_version(void)
4565 {
4566- return "1.0.08d RC";
4567+ return "1.0.09f RC";
4568 }
4569
4570 /* Copy and URL decode! */
4571
4572=== modified file 'storage/pbxt/src/systab_xt.cc'
4573--- storage/pbxt/src/systab_xt.cc 2009-08-17 11:12:36 +0000
4574+++ storage/pbxt/src/systab_xt.cc 2009-12-10 11:48:17 +0000
4575@@ -130,7 +130,7 @@
4576 * MYSQL UTILITIES
4577 */
4578
4579-void xt_my_set_notnull_in_record(Field *field, char *record)
4580+static void xt_my_set_notnull_in_record(Field *field, char *record)
4581 {
4582 if (field->null_ptr)
4583 record[(uint) (field->null_ptr - (uchar *) field->table->record[0])] &= (uchar) ~field->null_bit;
4584@@ -518,7 +518,7 @@
4585 * SYSTEM TABLE SHARES
4586 */
4587
4588-void st_path_to_table_name(size_t size, char *buffer, const char *path)
4589+static void st_path_to_table_name(size_t size, char *buffer, const char *path)
4590 {
4591 char *str;
4592
4593
4594=== modified file 'storage/pbxt/src/tabcache_xt.cc'
4595--- storage/pbxt/src/tabcache_xt.cc 2009-09-03 06:15:03 +0000
4596+++ storage/pbxt/src/tabcache_xt.cc 2009-12-10 11:48:17 +0000
4597@@ -590,7 +590,7 @@
4598 * So there could be a deadlock if I don't flush the log!
4599 */
4600 if ((self = xt_get_self())) {
4601- if (!xt_xlog_flush_log(self))
4602+ if (!xt_xlog_flush_log(tci_table->tab_db, self))
4603 goto failed;
4604 }
4605
4606@@ -1150,6 +1150,8 @@
4607 int count;
4608 void *mysql_thread;
4609
4610+ myxt_wait_pbxt_plugin_slot_assigned(self);
4611+
4612 mysql_thread = myxt_create_thread();
4613
4614 while (!self->t_quit) {
4615
4616=== modified file 'storage/pbxt/src/tabcache_xt.h'
4617--- storage/pbxt/src/tabcache_xt.h 2009-08-17 11:12:36 +0000
4618+++ storage/pbxt/src/tabcache_xt.h 2009-12-10 11:48:17 +0000
4619@@ -168,7 +168,7 @@
4620 #define TAB_CAC_UNLOCK(i, o) xt_xsmutex_unlock(i, o)
4621 #elif defined(TAB_CAC_USE_PTHREAD_RW)
4622 #define TAB_CAC_LOCK_TYPE xt_rwlock_type
4623-#define TAB_CAC_INIT_LOCK(s, i) xt_init_rwlock(s, i)
4624+#define TAB_CAC_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i)
4625 #define TAB_CAC_FREE_LOCK(s, i) xt_free_rwlock(i)
4626 #define TAB_CAC_READ_LOCK(i, o) xt_slock_rwlock_ns(i)
4627 #define TAB_CAC_WRITE_LOCK(i, o) xt_xlock_rwlock_ns(i)
4628
4629=== modified file 'storage/pbxt/src/table_xt.cc'
4630--- storage/pbxt/src/table_xt.cc 2009-08-18 07:46:53 +0000
4631+++ storage/pbxt/src/table_xt.cc 2009-12-10 11:48:17 +0000
4632@@ -35,7 +35,6 @@
4633 #include <drizzled/common.h>
4634 #include <mysys/thr_lock.h>
4635 #include <drizzled/dtcollation.h>
4636-#include <drizzled/plugin/storage_engine.h>
4637 #else
4638 #include "mysql_priv.h"
4639 #endif
4640@@ -48,7 +47,6 @@
4641 #include "cache_xt.h"
4642 #include "trace_xt.h"
4643 #include "index_xt.h"
4644-#include "restart_xt.h"
4645 #include "systab_xt.h"
4646
4647 #ifdef DEBUG
4648@@ -2347,7 +2345,7 @@
4649
4650 }
4651
4652-xtPublic XTOpenTablePtr tab_open_table(XTTableHPtr tab)
4653+static XTOpenTablePtr tab_open_table(XTTableHPtr tab)
4654 {
4655 volatile XTOpenTablePtr ot;
4656 XTThreadPtr self;
4657@@ -2588,7 +2586,7 @@
4658 return FAILED;
4659 }
4660
4661- return xt_xlog_modify_table(ot, status, op_seq, free_rec_id, rec_id, size, buffer);
4662+ return xt_xlog_modify_table(tab->tab_id, status, op_seq, free_rec_id, rec_id, size, buffer, ot->ot_thread);
4663 }
4664
4665 xtPublic xtBool xt_tab_put_log_rec_data(XTOpenTablePtr ot, u_int status, xtRecordID free_rec_id, xtRecordID rec_id, size_t size, xtWord1 *buffer, xtOpSeqNo *op_seq)
4666@@ -2606,7 +2604,7 @@
4667 return FAILED;
4668 }
4669
4670- return xt_xlog_modify_table(ot, status, *op_seq, free_rec_id, rec_id, size, buffer);
4671+ return xt_xlog_modify_table(tab->tab_id, status, *op_seq, free_rec_id, rec_id, size, buffer, ot->ot_thread);
4672 }
4673
4674 xtPublic xtBool xt_tab_get_rec_data(XTOpenTablePtr ot, xtRecordID rec_id, size_t size, xtWord1 *buffer)
4675@@ -3541,7 +3539,7 @@
4676 tab->tab_row_fnum++;
4677 xt_unlock_mutex_ns(&tab->tab_row_lock);
4678
4679- if (!xt_xlog_modify_table(ot, XT_LOG_ENT_ROW_FREED, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &free_row))
4680+ 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))
4681 return FAILED;
4682
4683 return OK;
4684@@ -3791,7 +3789,7 @@
4685 xt_unlock_mutex_ns(&tab->tab_rec_lock);
4686
4687 free_rec->rf_rec_type_1 = old_rec_type;
4688- return xt_xlog_modify_table(ot, XT_LOG_ENT_REC_REMOVED_BI, op_seq, (xtRecordID) new_rec_type, rec_id, rec_size, ot->ot_row_rbuffer);
4689+ 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);
4690 }
4691
4692 static xtRowID tab_new_row(XTOpenTablePtr ot, XTTableHPtr tab)
4693@@ -3837,7 +3835,7 @@
4694 op_seq = tab->tab_seq.ts_get_op_seq();
4695 xt_unlock_mutex_ns(&tab->tab_row_lock);
4696
4697- if (!xt_xlog_modify_table(ot, status, op_seq, next_row_id, row_id, 0, NULL))
4698+ if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, next_row_id, row_id, 0, NULL, ot->ot_thread))
4699 return 0;
4700
4701 XT_DISABLED_TRACE(("new row tx=%d row=%d\n", (int) ot->ot_thread->st_xact_data->xd_start_xn_id, (int) row_id));
4702@@ -3868,7 +3866,7 @@
4703 if (!tab->tab_rows.xt_tc_write(ot->ot_row_file, row_id, 0, sizeof(XTTabRowRefDRec), (xtWord1 *) &row_buf, &op_seq, TRUE, ot->ot_thread))
4704 return FAILED;
4705
4706- return xt_xlog_modify_table(ot, status, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &row_buf);
4707+ return xt_xlog_modify_table(tab->tab_id, status, op_seq, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &row_buf, ot->ot_thread);
4708 }
4709
4710 xtPublic xtBool xt_tab_free_record(XTOpenTablePtr ot, u_int status, xtRecordID rec_id, xtBool clean_delete)
4711@@ -3937,7 +3935,7 @@
4712 tab->tab_rec_fnum++;
4713 xt_unlock_mutex_ns(&tab->tab_rec_lock);
4714
4715- if (!xt_xlog_modify_table(ot, status, op_seq, rec_id, rec_id, sizeof(XTactFreeRecEntryDRec) - offsetof(XTactFreeRecEntryDRec, fr_stat_id_1), &free_rec.fr_stat_id_1))
4716+ if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, rec_id, rec_id, sizeof(XTactFreeRecEntryDRec) - offsetof(XTactFreeRecEntryDRec, fr_stat_id_1), &free_rec.fr_stat_id_1, ot->ot_thread))
4717 return FAILED;
4718 }
4719 return OK;
4720@@ -4016,7 +4014,7 @@
4721 }
4722 xt_unlock_mutex_ns(&tab->tab_rec_lock);
4723
4724- if (!xt_xlog_modify_table(ot, status, op_seq, next_rec_id, rec_id, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf))
4725+ if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, next_rec_id, rec_id, rec_info->ri_rec_buf_size, (xtWord1 *) rec_info->ri_fix_rec_buf, ot->ot_thread))
4726 return FAILED;
4727
4728 if (rec_info->ri_ext_rec) {
4729@@ -4932,6 +4930,12 @@
4730 #endif
4731 #endif
4732
4733+xtPublic void xt_tab_seq_repeat(XTOpenTablePtr ot)
4734+{
4735+ ot->ot_seq_rec_id--;
4736+ ot->ot_seq_offset -= ot->ot_table->tab_dic.dic_rec_size;
4737+}
4738+
4739 xtPublic xtBool xt_tab_seq_next(XTOpenTablePtr ot, xtWord1 *buffer, xtBool *eof)
4740 {
4741 register XTTableHPtr tab = ot->ot_table;
4742@@ -5094,7 +5098,7 @@
4743 return FALSE;
4744 }
4745 else {
4746- if (!xt_open_file_ns(&of, file_path, XT_FS_DEFAULT))
4747+ if (!xt_open_file_ns(&of, file_path, XT_FS_DEFAULT | XT_FS_MISSING_OK))
4748 return FALSE;
4749 }
4750 if (!of)
4751@@ -5190,15 +5194,76 @@
4752 return FALSE;
4753 }
4754
4755-xtPublic void tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size)
4756+static void tab_make_table_name(XTTableHPtr tab, char *table_name, size_t size)
4757 {
4758- char name_buf[XT_IDENTIFIER_NAME_SIZE*3+3];
4759-
4760- xt_2nd_last_name_of_path(sizeof(name_buf), name_buf, tab->tab_name->ps_path);
4761- myxt_static_convert_file_name(name_buf, table_name, size);
4762- xt_strcat(size, table_name, ".");
4763- myxt_static_convert_file_name(xt_last_name_of_path(tab->tab_name->ps_path), name_buf, sizeof(name_buf));
4764- xt_strcat(size, table_name, name_buf);
4765+ char *nptr;
4766+
4767+ nptr = xt_last_name_of_path(tab->tab_name->ps_path);
4768+ if (xt_starts_with(nptr, "#sql")) {
4769+ /* {INVALID-OLD-TABLE-FIX}
4770+ * Temporary files can have strange paths, for example
4771+ * ..../var/tmp/mysqld.1/#sqldaec_1_6
4772+ * This occurs, for example, occurs when the temp_table.test is
4773+ * run using the PBXT suite in MariaDB:
4774+ * ./mtr --suite=pbxt --do-test=temp_table
4775+ *
4776+ * Calling myxt_static_convert_file_name, with a '.', in the name
4777+ * causes the error:
4778+ * [ERROR] Invalid (old?) table or database name 'mysqld.1'
4779+ * To prevent this, we do not convert the temporary
4780+ * table names using the mysql functions.
4781+ *
4782+ * Note, this bug was found by Monty, and fixed by modifying
4783+ * xt_2nd_last_name_of_path(), see {INVALID-OLD-TABLE-FIX}.
4784+ *
4785+ */
4786+ xt_2nd_last_name_of_path(size, table_name, tab->tab_name->ps_path);
4787+ xt_strcat(size, table_name, ".");
4788+ xt_strcat(size, table_name, nptr);
4789+ }
4790+ else {
4791+ char name_buf[XT_TABLE_NAME_SIZE*3+3];
4792+ char *part_ptr;
4793+ size_t len;
4794+
4795+ xt_2nd_last_name_of_path(sizeof(name_buf), name_buf, tab->tab_name->ps_path);
4796+ myxt_static_convert_file_name(name_buf, table_name, size);
4797+ xt_strcat(size, table_name, ".");
4798+
4799+ /* Handle partition extensions to table names: */
4800+ if ((part_ptr = strstr(nptr, "#P#")))
4801+ xt_strncpy(sizeof(name_buf), name_buf, nptr, part_ptr - nptr);
4802+ else
4803+ xt_strcpy(sizeof(name_buf), name_buf, nptr);
4804+
4805+ len = strlen(table_name);
4806+ myxt_static_convert_file_name(name_buf, table_name + len, size - len);
4807+
4808+ if (part_ptr) {
4809+ /* Add the partition extension (which is relevant to the engine). */
4810+ char *sub_part_ptr;
4811+
4812+ part_ptr += 3;
4813+ if ((sub_part_ptr = strstr(part_ptr, "#SP#")))
4814+ xt_strncpy(sizeof(name_buf), name_buf, part_ptr, sub_part_ptr - part_ptr);
4815+ else
4816+ xt_strcpy(sizeof(name_buf), name_buf, part_ptr);
4817+
4818+ xt_strcat(size, table_name, " (");
4819+ len = strlen(table_name);
4820+ myxt_static_convert_file_name(name_buf, table_name + len, size - len);
4821+
4822+ if (sub_part_ptr) {
4823+
4824+ sub_part_ptr += 4;
4825+ xt_strcat(size, table_name, " - ");
4826+ len = strlen(table_name);
4827+ myxt_static_convert_file_name(sub_part_ptr, table_name + len, size - len);
4828+ }
4829+
4830+ xt_strcat(size, table_name, ")");
4831+ }
4832+ }
4833 }
4834
4835 xtPublic xtBool xt_tab_is_table_repair_pending(XTTableHPtr tab)
4836
4837=== modified file 'storage/pbxt/src/table_xt.h'
4838--- storage/pbxt/src/table_xt.h 2009-08-18 07:46:53 +0000
4839+++ storage/pbxt/src/table_xt.h 2009-12-10 11:48:17 +0000
4840@@ -127,7 +127,7 @@
4841 #define XT_TAB_ROW_UNLOCK(i, s) xt_xsmutex_unlock(i, (s)->t_id)
4842 #elif defined(XT_TAB_ROW_USE_PTHREAD_RW)
4843 #define XT_TAB_ROW_LOCK_TYPE xt_rwlock_type
4844-#define XT_TAB_ROW_INIT_LOCK(s, i) xt_init_rwlock(s, i)
4845+#define XT_TAB_ROW_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i)
4846 #define XT_TAB_ROW_FREE_LOCK(s, i) xt_free_rwlock(i)
4847 #define XT_TAB_ROW_READ_LOCK(i, s) xt_slock_rwlock_ns(i)
4848 #define XT_TAB_ROW_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i)
4849@@ -528,13 +528,14 @@
4850 void xt_enum_tables_init(u_int *edx);
4851 XTTableEntryPtr xt_enum_tables_next(struct XTThread *self, struct XTDatabase *db, u_int *edx);
4852
4853-void xt_enum_files_of_tables_init(struct XTDatabase *db, char *tab_name, xtTableID tab_id, XTFilesOfTablePtr ft);
4854+void xt_enum_files_of_tables_init(XTPathStrPtr tab_name, xtTableID tab_id, XTFilesOfTablePtr ft);
4855 xtBool xt_enum_files_of_tables_next(XTFilesOfTablePtr ft);
4856
4857 xtBool xt_tab_seq_init(XTOpenTablePtr ot);
4858 void xt_tab_seq_reset(XTOpenTablePtr ot);
4859 void xt_tab_seq_exit(XTOpenTablePtr ot);
4860 xtBool xt_tab_seq_next(XTOpenTablePtr ot, xtWord1 *buffer, xtBool *eof);
4861+void xt_tab_seq_repeat(XTOpenTablePtr ot);
4862
4863 xtBool xt_tab_new_record(XTOpenTablePtr ot, xtWord1 *buffer);
4864 xtBool xt_tab_delete_record(XTOpenTablePtr ot, xtWord1 *buffer);
4865
4866=== modified file 'storage/pbxt/src/thread_xt.cc'
4867--- storage/pbxt/src/thread_xt.cc 2009-10-06 15:16:01 +0000
4868+++ storage/pbxt/src/thread_xt.cc 2009-12-10 11:48:17 +0000
4869@@ -75,6 +75,13 @@
4870 /* Global accumulated statistics: */
4871 static XTStatisticsRec thr_statistics;
4872
4873+#ifdef DEBUG
4874+static void break_in_assertion(c_char *expr, c_char *func, c_char *file, u_int line)
4875+{
4876+ printf("%s(%s:%d) %s\n", func, file, (int) line, expr);
4877+}
4878+#endif
4879+
4880 /*
4881 * -----------------------------------------------------------------------
4882 * Error logging
4883@@ -658,6 +665,9 @@
4884 case XT_ERR_FK_REF_TEMP_TABLE: str = "Foreign key may not reference temporary table"; break;
4885 case XT_ERR_MYSQL_SHUTDOWN: str = "Cannot open table, MySQL has shutdown"; break;
4886 case XT_ERR_MYSQL_NO_THREAD: str = "Cannot create thread, MySQL has shutdown"; break;
4887+ case XT_ERR_BUFFER_TOO_SMALL: str = "System backup buffer too small"; break;
4888+ case XT_ERR_BAD_BACKUP_FORMAT: str = "Unknown or corrupt backup format, restore aborted"; break;
4889+ case XT_ERR_PBXT_NOT_INSTALLED: str = "PBXT plugin is not installed"; break;
4890 default: str = "Unknown XT error"; break;
4891 }
4892 return str;
4893@@ -862,6 +872,11 @@
4894 return FAILED;
4895 }
4896
4897+xtPublic void xt_exception_xterr(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err)
4898+{
4899+ xt_exception_error(e, self, func, file, line, xt_err, 0, thr_get_err_string(xt_err));
4900+}
4901+
4902 /*
4903 * -----------------------------------------------------------------------
4904 * LOG ERRORS
4905@@ -887,7 +902,7 @@
4906 #ifdef DEBUG
4907 //xt_set_fflush(TRUE);
4908 //xt_dump_trace();
4909- printf("%s(%s:%d) %s\n", func, file, (int) line, expr);
4910+ break_in_assertion(expr, func, file, line);
4911 #ifdef CRASH_ON_ASSERT
4912 abort();
4913 #endif
4914
4915=== modified file 'storage/pbxt/src/thread_xt.h'
4916--- storage/pbxt/src/thread_xt.h 2009-08-17 11:12:36 +0000
4917+++ storage/pbxt/src/thread_xt.h 2009-12-10 11:48:17 +0000
4918@@ -536,6 +536,8 @@
4919 * Function prototypes
4920 */
4921
4922+extern "C" void *thr_main(void *data);
4923+
4924 void xt_get_now(char *buffer, size_t len);
4925 xtBool xt_init_logging(void);
4926 void xt_exit_logging(void);
4927@@ -583,6 +585,7 @@
4928 void xt_exceptionf(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *fmt, ...);
4929 void xt_exception_error(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *msg);
4930 xtBool xt_exception_errno(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int err);
4931+void xt_exception_xterr(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err);
4932
4933 void xt_log_errno(XTThreadPtr self, c_char *func, c_char *file, u_int line, int err);
4934
4935@@ -610,7 +613,7 @@
4936 void xt_yield(void);
4937 void xt_sleep_milli_second(u_int t);
4938 xtBool xt_suspend(XTThreadPtr self);
4939-xtBool xt_unsuspend(XTThreadPtr self, XTThreadPtr target);
4940+xtBool xt_unsuspend(XTThreadPtr target);
4941 void xt_lock_thread(XTThreadPtr thread);
4942 void xt_unlock_thread(XTThreadPtr thread);
4943 xtBool xt_wait_thread(XTThreadPtr thread);
4944
4945=== modified file 'storage/pbxt/src/util_xt.cc'
4946--- storage/pbxt/src/util_xt.cc 2009-08-17 11:12:36 +0000
4947+++ storage/pbxt/src/util_xt.cc 2009-12-10 11:48:17 +0000
4948@@ -150,6 +150,23 @@
4949 return (xtWord1) (sum ^ (sum >> 24) ^ (sum >> 16) ^ (sum >> 8));
4950 }
4951
4952+xtPublic xtWord4 xt_get_checksum4(xtWord1 *data, size_t len)
4953+{
4954+ register xtWord4 sum = 0, g;
4955+ xtWord1 *chk;
4956+
4957+ chk = data + len - 1;
4958+ while (chk > data) {
4959+ sum = (sum << 4) + *chk;
4960+ if ((g = sum & 0xF0000000)) {
4961+ sum = sum ^ (g >> 24);
4962+ sum = sum ^ g;
4963+ }
4964+ chk--;
4965+ }
4966+ return sum;
4967+}
4968+
4969 /*
4970 * --------------- Data Buffer ------------------
4971 */
4972
4973=== modified file 'storage/pbxt/src/util_xt.h'
4974--- storage/pbxt/src/util_xt.h 2009-03-26 12:18:01 +0000
4975+++ storage/pbxt/src/util_xt.h 2009-12-10 11:48:17 +0000
4976@@ -39,6 +39,7 @@
4977 xtBool xt_time_difference(register xtWord4 now, register xtWord4 then);
4978 xtWord2 xt_get_checksum(xtWord1 *data, size_t len, u_int interval);
4979 xtWord1 xt_get_checksum1(xtWord1 *data, size_t len);
4980+xtWord4 xt_get_checksum4(xtWord1 *data, size_t len);
4981
4982 typedef struct XTDataBuffer {
4983 size_t db_size;
4984
4985=== modified file 'storage/pbxt/src/xaction_xt.cc'
4986--- storage/pbxt/src/xaction_xt.cc 2009-09-03 06:15:03 +0000
4987+++ storage/pbxt/src/xaction_xt.cc 2009-12-10 11:48:17 +0000
4988@@ -1075,6 +1075,7 @@
4989 #endif
4990 xt_spinlock_init_with_autoname(self, &db->db_xn_id_lock);
4991 xt_spinlock_init_with_autoname(self, &db->db_xn_wait_spinlock);
4992+ xt_init_mutex_with_autoname(self, &db->db_xn_xa_lock);
4993 //xt_init_mutex_with_autoname(self, &db->db_xn_wait_lock);
4994 //xt_init_cond(self, &db->db_xn_wait_cond);
4995 xt_init_mutex_with_autoname(self, &db->db_sw_lock);
4996@@ -1096,6 +1097,9 @@
4997 }
4998 }
4999
5000+ /* Create a sorted list for XA transactions recovered: */
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches