Commit 2fd4f480 authored by Paul McCullagh's avatar Paul McCullagh

Merged changes for bug fix update 1.0.08c RC2

parent 10cedc20
PBXT Release Notes
==================
------- 1.0.08c RC2 - 2009-08-18
RN266: Updated BLOB streaming glue, used with the PBMS engine. The glue code is now identical to the version of "1.0.08-rc-pbms" version of PBXT available from http://blobstreaming.org/download.
RN265: Changes the sequential reading of data log files to skip gaps, instead of returning EOF. This ensures that extended data records are preserved even when something goes wrong with the way the file is written.
RN264: Fixed a bug that cased an "Data log not found" error after an out of disk space error on a log file. This bug is similar to RN262 in that it allows "gaps" to appear in the data logs.
RN263: Updated xtstat to compile on Windows/MS Visual C++.
RN262: Merged changes for PBMS version 0.5.09.
RN261: Concerning bug #377788: Cannot find index for FK. Fixed buffer overflow which occurred when the error was reported.
RN260: Fixed bug #377788: Cannot find index for FK. PBXT now correctly uses prefix of an index to support FK references (e.g. if key = (c1, c2) then an index on (c1, c2, c3) will work). Also fixed buffer overflow, which occurred when reporting the error.
RN259: Fixed bug #309424: xtstat doesn't use my.cnf. You can now add an [xtstat] section to my.cnf, for use with xtstat.
RN258: updated xt_p_join implementation for Windows to check if a thread has already exited or has not yet started
RN257: Removed false assertion that could fail during restore if a transaction log page was zero-filled
RN256: Update datalog eof pointer only if write opearions were sucessful
RN255: Added re-allocation of of filemap if allocating the of the new map failed. This often happens if there's not enough space on disk.
RN254: When a table with a corrupted index is detected, PBXT creates a file called 'repair-pending' in the pbxt directory, with the name of the table in it. Each table in the file is listed on a line by itself (the last line has no trailing \n). When the table is repaired (using the REPAIR TABLE command), this entry is removed from the file.
RN253: Use fcntl(F_FULLFSYNC) instead of fsync on platforms that support it. Improper fsync operation was presumably the reason of index corruption on Mac OS X.
RN252: Fixed bug #368692: PBXT not reporting data size correctly in information_schema.
------- 1.0.08 RC2 - 2009-06-30
RN251: A Windows-specific test update, also removed false assertion that failed on Windows.
RN250: Fixed a bug that caused recovery to fail when the transaction log ID exceeded 255. The problem was a checksum failed in the log record.
RN249: Fixed bug #313176: Test case timeout. This happened because record cache pages where not propoerly freed and as soon as cache filled up the performacne degraded.
RN249: Fixed bug #313176: Test case timeout. This happened because record cache pages where not properly freed and as soon as cache filled up the performacne degraded.
RN248: PBXT now compiles and runs with MySQL 5.1.35. All tests pass.
......
......@@ -1735,8 +1735,8 @@ void XTDDConstraint::alterColumnName(XTThreadPtr self, char *from_name, char *to
void XTDDConstraint::getColumnList(char *buffer, size_t size)
{
if (co_table->dt_table) {
xt_strcat(size, buffer, "`");
xt_strcpy(size, buffer, co_table->dt_table->tab_name->ps_path);
xt_strcpy(size, buffer, "`");
xt_strcat(size, buffer, co_table->dt_table->tab_name->ps_path);
xt_strcat(size, buffer, "` (`");
}
else
......@@ -1763,6 +1763,20 @@ bool XTDDConstraint::sameColumns(XTDDConstraint *co)
return OK;
}
bool XTDDConstraint::samePrefixColumns(XTDDConstraint *co)
{
u_int i = 0;
if (co_cols.size() > co->co_cols.size())
return false;
while (i<co_cols.size()) {
if (myxt_strcasecmp(co_cols.itemAt(i)->cr_col_name, co->co_cols.itemAt(i)->cr_col_name) != 0)
return false;
i++;
}
return OK;
}
bool XTDDConstraint::attachColumns()
{
XTDDColumn *col;
......@@ -2176,6 +2190,20 @@ bool XTDDForeignKey::sameReferenceColumns(XTDDConstraint *co)
return OK;
}
bool XTDDForeignKey::samePrefixReferenceColumns(XTDDConstraint *co)
{
u_int i = 0;
if (fk_ref_cols.size() > co->co_cols.size())
return false;
while (i<fk_ref_cols.size()) {
if (myxt_strcasecmp(fk_ref_cols.itemAt(i)->cr_col_name, co->co_cols.itemAt(i)->cr_col_name) != 0)
return false;
i++;
}
return OK;
}
bool XTDDForeignKey::checkReferencedTypes(XTDDTable *dt)
{
XTDDColumn *col, *ref_col;
......@@ -2720,16 +2748,24 @@ void XTDDTable::checkForeignKeys(XTThreadPtr self, bool temp_table)
XTDDIndex *XTDDTable::findIndex(XTDDConstraint *co)
{
XTDDIndex *ind;
XTDDIndex *ind = NULL;
XTDDIndex *cur_ind;
u_int index_size = UINT_MAX;
for (u_int i=0; i<dt_indexes.size(); i++) {
ind = dt_indexes.itemAt(i);
if (co->sameColumns(ind))
return ind;
cur_ind = dt_indexes.itemAt(i);
u_int sz = cur_ind->getIndexPtr()->mi_key_size;
if (sz < index_size && co->samePrefixColumns(cur_ind)) {
ind = cur_ind;
index_size = sz;
}
}
if (ind)
return ind;
{
char buffer[XT_ERR_MSG_SIZE - 200];
co->getColumnList(buffer, XT_ERR_MSG_SIZE - 200);
xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_NO_MATCHING_INDEX, buffer);
}
......@@ -2738,16 +2774,24 @@ XTDDIndex *XTDDTable::findIndex(XTDDConstraint *co)
XTDDIndex *XTDDTable::findReferenceIndex(XTDDForeignKey *fk)
{
XTDDIndex *ind;
XTDDIndex *ind = NULL;
XTDDIndex *cur_ind;
XTDDColumnRef *cr;
u_int i;
u_int index_size = UINT_MAX;
for (i=0; i<dt_indexes.size(); i++) {
ind = dt_indexes.itemAt(i);
if (fk->sameReferenceColumns(ind))
return ind;
cur_ind = dt_indexes.itemAt(i);
u_int sz = cur_ind->getIndexPtr()->mi_key_size;
if (sz < index_size && fk->samePrefixReferenceColumns(cur_ind)) {
ind = cur_ind;
index_size = sz;
}
}
if (ind)
return ind;
/* If the index does not exist, maybe the columns do not exist?! */
for (i=0; i<fk->fk_ref_cols.size(); i++) {
cr = fk->fk_ref_cols.itemAt(i);
......
......@@ -171,6 +171,7 @@ class XTDDConstraint : public XTObject {
virtual void alterColumnName(XTThreadPtr self, char *from_name, char *to_name);
void getColumnList(char *buffer, size_t size);
bool sameColumns(XTDDConstraint *co);
bool samePrefixColumns(XTDDConstraint *co);
bool attachColumns();
};
......@@ -240,6 +241,7 @@ class XTDDForeignKey : public XTDDIndex {
void getReferenceList(char *buffer, size_t size);
struct XTIndex *getReferenceIndexPtr();
bool sameReferenceColumns(XTDDConstraint *co);
bool samePrefixReferenceColumns(XTDDConstraint *co);
bool checkReferencedTypes(XTDDTable *dt);
void removeReference(XTThreadPtr self);
bool insertRow(xtWord1 *before, xtWord1 *after, XTThreadPtr thread);
......
This diff is collapsed.
......@@ -183,8 +183,8 @@ typedef struct XTSeqLogRead {
virtual xtBool sl_rnd_read(xtLogOffset log_offset, size_t size, xtWord1 *data, size_t *read, struct XTThread *thread) {
(void) log_offset; (void) size; (void) data; (void) read; (void) thread; return OK;
};
virtual xtBool sl_seq_next(XTXactLogBufferDPtr *entry, xtBool verify, struct XTThread *thread) {
(void) entry; (void) verify; (void) thread; return OK;
virtual xtBool sl_seq_next(XTXactLogBufferDPtr *entry, struct XTThread *thread) {
(void) entry; (void) thread; return OK;
};
virtual void sl_seq_skip(size_t size) { (void) size; }
} XTSeqLogReadRec, *XTSeqLogReadPtr;
......@@ -195,6 +195,7 @@ typedef struct XTDataSeqRead : public XTSeqLogRead {
xtLogOffset sl_rec_log_offset; /* The current log read position. */
size_t sl_record_len; /* The length of the current record. */
xtLogOffset sl_log_eof;
xtLogOffset sl_extra_garbage; /* Garbage found during a scan. */
size_t sl_buffer_size; /* Size of the buffer. */
xtLogOffset sl_buf_log_offset; /* File offset of the buffer. */
......@@ -208,7 +209,7 @@ typedef struct XTDataSeqRead : public XTSeqLogRead {
virtual void sl_seq_pos(xtLogID *log_id, xtLogOffset *log_offset);
virtual xtBool sl_seq_start(xtLogID log_id, xtLogOffset log_offset, xtBool missing_ok);
virtual xtBool sl_rnd_read(xtLogOffset log_offset, size_t size, xtWord1 *data, size_t *read, struct XTThread *thread);
virtual xtBool sl_seq_next(XTXactLogBufferDPtr *entry, xtBool verify, struct XTThread *thread);
virtual xtBool sl_seq_next(XTXactLogBufferDPtr *entry, struct XTThread *thread);
virtual void sl_seq_skip(size_t size);
virtual void sl_seq_skip_to(off_t offset);
} XTDataSeqReadRec, *XTDataSeqReadPtr;
......
......@@ -54,6 +54,7 @@
//#define DEBUG_TRACE_IO
//#define DEBUG_TRACE_MAP_IO
//#define DEBUG_TRACE_FILES
//#define INJECT_WRITE_REMAP_ERROR
#endif
#ifdef DEBUG_TRACE_FILES
......@@ -61,6 +62,11 @@
#define PRINTF xt_trace
#endif
#ifdef INJECT_WRITE_REMAP_ERROR
#define INJECT_REMAP_FILE_SIZE 1000000
#define INJECT_REMAP_FILE_TYPE "xtd"
#endif
/* ----------------------------------------------------------------------
* Globals
*/
......@@ -867,12 +873,23 @@ xtPublic xtBool xt_flush_file(XTOpenFilePtr of, XTIOStatsPtr stat, XTThreadPtr X
xt_register_ferrno(XT_REG_CONTEXT, fs_get_win_error(), xt_file_path(of));
goto failed;
}
#else
/* Mac OS X has problems with fsync. We had several cases of index corruption presumably because
* fsync didn't really flush index pages to disk. fcntl(F_FULLFSYNC) is considered more effective
* in such case.
*/
#ifdef F_FULLFSYNC
if (fcntl(of->of_filedes, F_FULLFSYNC, 0) == -1) {
xt_register_ferrno(XT_REG_CONTEXT, errno, xt_file_path(of));
goto failed;
}
#else
if (fsync(of->of_filedes) == -1) {
xt_register_ferrno(XT_REG_CONTEXT, errno, xt_file_path(of));
goto failed;
}
#endif
#endif
#ifdef DEBUG_TRACE_IO
xt_trace("/* %s */ pbxt_file_sync(\"%s\");\n", xt_trace_clock_diff(timef, start), of->fr_file->fil_path);
#endif
......@@ -1185,6 +1202,15 @@ off_t xt_dir_file_size(XTThreadPtr self, XTOpenDirPtr od)
static xtBool fs_map_file(XTFileMemMapPtr mm, XTFilePtr file, xtBool grow)
{
#ifdef INJECT_WRITE_REMAP_ERROR
if (xt_is_extension(file->fil_path, INJECT_REMAP_FILE_TYPE)) {
if (mm->mm_length > INJECT_REMAP_FILE_SIZE) {
xt_register_ferrno(XT_REG_CONTEXT, 30, file->fil_path);
return FAILED;
}
}
#endif
ASSERT_NS(!mm->mm_start);
#ifdef XT_WIN
/* This will grow the file to the given size: */
......@@ -1373,15 +1399,24 @@ static xtBool fs_remap_file(XTMapFilePtr map, off_t offset, size_t size, XTIOSta
}
mm->mm_start = NULL;
#ifdef XT_WIN
if (!CloseHandle(mm->mm_mapdes))
/* It is possible that a previous remap attempt has failed: the map was closed
* but the new map was not allocated (e.g. because of insufficient disk space).
* In this case mm->mm_mapdes will be NULL.
*/
if (mm->mm_mapdes && !CloseHandle(mm->mm_mapdes))
return xt_register_ferrno(XT_REG_CONTEXT, fs_get_win_error(), xt_file_path(map));
mm->mm_mapdes = NULL;
#endif
off_t old_size = mm->mm_length;
mm->mm_length = new_size;
if (!fs_map_file(mm, map->fr_file, TRUE))
if (!fs_map_file(mm, map->fr_file, TRUE)) {
/* Try to restore old mapping */
mm->mm_length = old_size;
fs_map_file(mm, map->fr_file, FALSE);
return FAILED;
}
}
return OK;
failed:
......
......@@ -65,8 +65,8 @@ extern "C" char **session_query(Session *session);
#include "heap_xt.h"
#include "myxt_xt.h"
#include "datadic_xt.h"
#ifdef XT_STREAMING
#include "streaming_xt.h"
#ifdef PBMS_ENABLED
#include "pbms_enabled.h"
#endif
#include "tabcache_xt.h"
#include "systab_xt.h"
......@@ -968,8 +968,8 @@ static void ha_exit(XTThreadPtr self)
/* This may cause the streaming engine to cleanup connections and
* tables belonging to this engine. This in turn may require some of
* the stuff below (like xt_create_thread() called from pbxt_close_table()! */
#ifdef XT_STREAMING
xt_exit_streaming();
#ifdef PBMS_ENABLED
pbms_finalize();
#endif
pbxt_call_exit(self);
xt_exit_threading(self);
......@@ -1041,7 +1041,7 @@ static int pbxt_init(void *p)
XT_TRACE_CALL();
if (sizeof(xtWordPS) != sizeof(void *)) {
printf("PBXT: This won't work, I require that sizeof(xtWordPS) != sizeof(void *)!\n");
printf("PBXT: This won't work, I require that sizeof(xtWordPS) == sizeof(void *)!\n");
XT_RETURN(1);
}
......@@ -1078,9 +1078,12 @@ static int pbxt_init(void *p)
if (!xt_init_logging()) /* Initialize logging */
goto error_1;
#ifdef XT_STREAMING
if (!xt_init_streaming())
#ifdef PBMS_ENABLED
PBMSResultRec result;
if (!pbms_initialize("PBXT", false, &result)) {
xt_logf(XT_NT_ERROR, "pbms_initialize() Error: %s", result.mr_message);
goto error_2;
}
#endif
if (!xt_init_memory()) /* Initialize memory */
......@@ -1129,7 +1132,7 @@ static int pbxt_init(void *p)
ASSERT(!pbxt_database);
{
THD *curr_thd = current_thd;
THD *thd = curr_thd;
THD *thd = NULL;
#ifndef DRIZZLED
extern myxt_mutex_t LOCK_plugin;
......@@ -1169,16 +1172,20 @@ static int pbxt_init(void *p)
xt_xres_start_database_recovery(self);
}
catch_(b) {
if (!curr_thd && thd)
myxt_destroy_thread(thd, FALSE);
#ifndef DRIZZLED
myxt_mutex_lock(&LOCK_plugin);
#endif
xt_throw(self);
/* It is possible that the error was reset by cleanup code.
* Set a generic error code in that case.
*/
/* PMC - This is not necessary in because exceptions are
* now preserved, in exception handler cleanup.
*/
if (!self->t_exception.e_xt_err)
xt_register_error(XT_REG_CONTEXT, XT_SYSTEM_ERROR, 0, "Initialization failed");
xt_log_exception(self, &self->t_exception, XT_LOG_DEFAULT);
init_err = 1;
}
cont_(b);
if (!curr_thd)
if (thd)
myxt_destroy_thread(thd, FALSE);
#ifndef DRIZZLED
myxt_mutex_lock(&LOCK_plugin);
......@@ -1237,8 +1244,8 @@ static int pbxt_init(void *p)
XT_RETURN(init_err);
error_3:
#ifdef XT_STREAMING
xt_exit_streaming();
#ifdef PBMS_ENABLED
pbms_finalize();
error_2:
#endif
......@@ -1295,9 +1302,6 @@ static int pbxt_close_connection(handlerton *hton, THD* thd)
{
#endif
XTThreadPtr self;
#ifdef XT_STREAMING
XTExceptionRec e;
#endif
XT_TRACE_CALL();
if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) {
......@@ -1308,10 +1312,6 @@ static int pbxt_close_connection(handlerton *hton, THD* thd)
xt_set_self(self);
xt_free_thread(self);
}
#ifdef XT_STREAMING
if (!xt_pbms_close_connection((void *) thd, &e))
xt_log_exception(NULL, &e, XT_LOG_DEFAULT);
#endif
return 0;
}
......@@ -2301,6 +2301,14 @@ int ha_pbxt::write_row(byte *buf)
XT_PRINT1(pb_open_tab->ot_thread, "ha_pbxt::write_row %s\n", pb_share->sh_table_path->ps_path);
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])));
//statistic_increment(ha_write_count,&LOCK_status);
#ifdef PBMS_ENABLED
PBMSResultRec result;
err = pbms_write_row_blobs(table, buf, &result);
if (err) {
xt_logf(XT_NT_ERROR, "pbms_write_row_blobs() Error: %s", result.mr_message);
return err;
}
#endif
/* GOTCHA: I have a huge problem with the transaction statement.
* It is not ALWAYS committed (I mean ha_commit_trans() is
......@@ -2332,7 +2340,8 @@ int ha_pbxt::write_row(byte *buf)
int update_err = update_auto_increment();
if (update_err) {
ha_log_pbxt_thread_error_for_mysql(pb_ignore_dup_key);
return update_err;
err = update_err;
goto done;
}
set_auto_increment(table->next_number_field);
}
......@@ -2350,6 +2359,10 @@ int ha_pbxt::write_row(byte *buf)
pb_open_tab->ot_thread->st_update_id++;
}
done:
#ifdef PBMS_ENABLED
pbms_completed(table, (err == 0));
#endif
return err;
}
......@@ -2423,6 +2436,21 @@ int ha_pbxt::update_row(const byte * old_data, byte * new_data)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
#ifdef PBMS_ENABLED
PBMSResultRec result;
err = pbms_delete_row_blobs(table, old_data, &result);
if (err) {
xt_logf(XT_NT_ERROR, "update_row:pbms_delete_row_blobs() Error: %s", result.mr_message);
return err;
}
err = pbms_write_row_blobs(table, new_data, &result);
if (err) {
xt_logf(XT_NT_ERROR, "update_row:pbms_write_row_blobs() Error: %s", result.mr_message);
goto pbms_done;
}
#endif
/* GOTCHA: We need to check the auto-increment value on update
* because of the following test (which fails for InnoDB) -
* auto_increment.test:
......@@ -2446,6 +2474,11 @@ int ha_pbxt::update_row(const byte * old_data, byte * new_data)
pb_open_tab->ot_table->tab_locks.xt_remove_temp_lock(pb_open_tab, TRUE);
#ifdef PBMS_ENABLED
pbms_done:
pbms_completed(table, (err == 0));
#endif
return err;
}
......@@ -2468,6 +2501,16 @@ int ha_pbxt::delete_row(const byte * buf)
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])));
//statistic_increment(ha_delete_count,&LOCK_status);
#ifdef PBMS_ENABLED
PBMSResultRec result;
err = pbms_delete_row_blobs(table, buf, &result);
if (err) {
xt_logf(XT_NT_ERROR, "pbms_delete_row_blobs() Error: %s", result.mr_message);
return err;
}
#endif
if (!pb_open_tab->ot_thread->st_stat_trans) {
trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton);
XT_PRINT0(pb_open_tab->ot_thread, "ha_pbxt::delete_row trans_register_ha all=FALSE\n");
......@@ -2481,6 +2524,9 @@ int ha_pbxt::delete_row(const byte * buf)
pb_open_tab->ot_table->tab_locks.xt_remove_temp_lock(pb_open_tab, TRUE);
#ifdef PBMS_ENABLED
pbms_completed(table, (err == 0));
#endif
return err;
}
......@@ -3478,7 +3524,7 @@ int ha_pbxt::info(uint flag)
if (flag & HA_STATUS_VARIABLE) {
stats.deleted = ot->ot_table->tab_row_fnum;
stats.records = (ha_rows) (ot->ot_table->tab_row_eof_id - 1 - stats.deleted);
stats.data_file_length = ot->ot_table->tab_rec_eof_id;
stats.data_file_length = xt_rec_id_to_rec_offset(ot->ot_table, ot->ot_table->tab_rec_eof_id);
stats.index_file_length = xt_ind_node_to_offset(ot->ot_table, ot->ot_table->tab_ind_eof);
stats.delete_length = ot->ot_table->tab_rec_fnum * ot->ot_rec_size;
//check_time = info.check_time;
......@@ -4750,6 +4796,19 @@ int ha_pbxt::delete_table(const char *table_path)
}
cont_(a);
#ifdef PBMS_ENABLED
/* Call pbms_delete_table_with_blobs() last because it cannot be undone. */
if (!err) {
PBMSResultRec result;
if (pbms_delete_table_with_blobs(table_path, &result)) {
xt_logf(XT_NT_WARNING, "pbms_delete_table_with_blobs() Error: %s", result.mr_message);
}
pbms_completed(NULL, true);
}
#endif
return err;
}
......@@ -4809,6 +4868,16 @@ int ha_pbxt::rename_table(const char *from, const char *to)
XT_PRINT2(self, "ha_pbxt::rename_table %s -> %s\n", from, to);
#ifdef PBMS_ENABLED
PBMSResultRec result;
err = pbms_rename_table_with_blobs(from, to, &result);
if (err) {
xt_logf(XT_NT_ERROR, "pbms_rename_table_with_blobs() Error: %s", result.mr_message);
return err;
}
#endif
try_(a) {
xt_ha_open_database_of_table(self, (XTPathStrPtr) to);
to_db = self->st_database;
......@@ -4837,10 +4906,6 @@ int ha_pbxt::rename_table(const char *from, const char *to)
freer_(); // ha_release_exclusive_use(share)
freer_(); // ha_unget_share(share)
#ifdef XT_STREAMING
/* PBMS remove the table? */
xt_pbms_rename_table(from, to);
#endif
/*
* If there are no more PBXT tables in the database, we
* "drop the database", which deletes all PBXT resources
......@@ -4861,6 +4926,10 @@ int ha_pbxt::rename_table(const char *from, const char *to)
}
cont_(a);
#ifdef PBMS_ENABLED
pbms_completed(NULL, (err == 0));
#endif
XT_RETURN(err);
}
......
......@@ -3424,7 +3424,7 @@ static void idx_set_index_selectivity(XTThreadPtr self, XTOpenTablePtr ot, XTInd
ot->ot_ind_rhandle = NULL;
failed:
ot->ot_table->tab_dic.dic_disable_index = XT_INDEX_CORRUPTED;
xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED);
xt_log_and_clear_exception_ns();
return;
}
......
......@@ -52,9 +52,6 @@ extern pthread_key_t THR_Session;
#include "myxt_xt.h"
#include "strutil_xt.h"
#include "database_xt.h"
#ifdef XT_STREAMING
#include "streaming_xt.h"
#endif
#include "cache_xt.h"
#include "datalog_xt.h"
......@@ -2914,6 +2911,11 @@ xtPublic void myxt_static_convert_table_name(XTThreadPtr XT_UNUSED(self), char *
tablename_to_filename(from, to, to_len);
}
xtPublic void myxt_static_convert_file_name(char *from, char *to, size_t to_len)
{
filename_to_tablename(from, to, to_len);
}
xtPublic int myxt_strcasecmp(char * a, char *b)
{
return my_strcasecmp(&my_charset_utf8_general_ci, a, b);
......@@ -2945,88 +2947,6 @@ xtPublic MX_CHARSET_INFO *myxt_getcharset(bool convert)
return &my_charset_utf8_general_ci;
}
#ifdef XT_STREAMING
xtPublic xtBool myxt_use_blobs(XTOpenTablePtr ot, void **ret_pbms_table, xtWord1 *rec_buf)
{
void *pbms_table;
XTTable *tab = ot->ot_table;
u_int idx = 0;
Field *field;
char *blob_ref;
xtWord4 len;
char in_url[PBMS_BLOB_URL_SIZE];
char *out_url;
if (!xt_pbms_open_table(&pbms_table, tab->tab_name->ps_path))
return FAILED;
for (idx=0; idx<tab->tab_dic.dic_blob_count; idx++) {
field = tab->tab_dic.dic_blob_cols[idx];
if ((blob_ref = mx_get_length_and_data(field, (char *) rec_buf, &len)) && len) {
xt_strncpy(PBMS_BLOB_URL_SIZE, in_url, blob_ref, len);
if (!xt_pbms_use_blob(pbms_table, &out_url, in_url, field->field_index)) {
xt_pbms_close_table(pbms_table);
return FAILED;
}
if (out_url) {
len = strlen(out_url);
mx_set_length_and_data(field, (char *) rec_buf, len, out_url);
}
}
}
*ret_pbms_table = pbms_table;
return OK;
}
xtPublic void myxt_unuse_blobs(XTOpenTablePtr XT_UNUSED(ot), void *pbms_table)
{
xt_pbms_close_table(pbms_table);
}
xtPublic xtBool myxt_retain_blobs(XTOpenTablePtr XT_UNUSED(ot), void *pbms_table, xtRecordID rec_id)
{
xtBool ok;
PBMSEngineRefRec eng_ref;
memset(&eng_ref, 0, sizeof(PBMSEngineRefRec));
XT_SET_DISK_8(eng_ref.er_data, rec_id);
ok = xt_pbms_retain_blobs(pbms_table, &eng_ref);
xt_pbms_close_table(pbms_table);
return ok;
}
xtPublic void myxt_release_blobs(XTOpenTablePtr ot, xtWord1 *rec_buf, xtRecordID rec_id)
{
void *pbms_table;
XTTable *tab = ot->ot_table;
u_int idx = 0;
Field *field;
char *blob_ref;
xtWord4 len;
char in_url[PBMS_BLOB_URL_SIZE];
PBMSEngineRefRec eng_ref;
memset(&eng_ref, 0, sizeof(PBMSEngineRefRec));
XT_SET_DISK_8(eng_ref.er_data, rec_id);
if (!xt_pbms_open_table(&pbms_table, tab->tab_name->ps_path))
return;
for (idx=0; idx<tab->tab_dic.dic_blob_count; idx++) {
field = tab->tab_dic.dic_blob_cols[idx];
if ((blob_ref = mx_get_length_and_data(field, (char *) rec_buf, &len)) && len) {
xt_strncpy(PBMS_BLOB_URL_SIZE, in_url, blob_ref, len);
xt_pbms_release_blob(pbms_table, in_url, field->field_index, &eng_ref);
}
}
xt_pbms_close_table(pbms_table);
}
#endif // XT_STREAMING
xtPublic void *myxt_create_thread()
{
#ifdef DRIZZLED
......
......@@ -70,6 +70,7 @@ XTDDTable *myxt_create_table_from_table(XTThreadPtr self, STRUCT_TABLE *my_tab);
void myxt_static_convert_identifier(XTThreadPtr self, struct charset_info_st *cs, char *from, char *to, size_t to_len);
char *myxt_convert_identifier(XTThreadPtr self, struct charset_info_st *cs, char *from);
void myxt_static_convert_table_name(XTThreadPtr self, char *from, char *to, size_t to_len);
void myxt_static_convert_file_name(char *from, char *to, size_t to_len);
char *myxt_convert_table_name(XTThreadPtr self, char *from);
int myxt_strcasecmp(char * a, char *b);
int myxt_isspace(struct charset_info_st *cs, char a);
......@@ -78,13 +79,6 @@ int myxt_isdigit(struct charset_info_st *cs, char a);
struct charset_info_st *myxt_getcharset(bool convert);
#ifdef XT_STREAMING
xtBool myxt_use_blobs(XTOpenTablePtr ot, void **ret_pbms_table, xtWord1 *rec_buf);
void myxt_unuse_blobs(XTOpenTablePtr ot, void *pbms_table);
xtBool myxt_retain_blobs(XTOpenTablePtr ot, void *pbms_table, xtRecordID record);
void myxt_release_blobs(XTOpenTablePtr ot, xtWord1 *rec_buf, xtRecordID record);
#endif
void *myxt_create_thread();
void myxt_destroy_thread(void *thread, xtBool end_threads);
XTThreadPtr myxt_get_self();
......
This diff is collapsed.
/* Copyright (c) 2009 PrimeBase Technologies GmbH, Germany
*
* PrimeBase Media Stream for MySQL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Barry Leslie
*
* 2009-07-16
*
* H&G2JCtL
*
* PBMS interface used to enable engines for use with the PBMS engine.
*
* For an example on how to build this into an engine have a look at the PBXT engine
* in file ha_pbxt.cc. Search for 'PBMS_ENABLED'.
*
*/
#define PBMS_API pbms_enabled_api
#include "pbms_enabled.h"
#ifdef DRIZZLED
#include <sys/stat.h>
#include <drizzled/common_includes.h>
#include <drizzled/plugin.h>
#else
#include "mysql_priv.h"
#include <mysql/plugin.h>
#define session_alloc(sess, size) thd_alloc(sess, size);
#define current_session current_thd
#endif
#define GET_BLOB_FIELD(t, i) (Field_blob *)(t->field[t->s->blob_field[i]])
#define DB_NAME(f) (f->table->s->db.str)
#define TAB_NAME(f) (*(f->table_name))
static PBMS_API pbms_api;
PBMSEngineRec enabled_engine = {
MS_ENGINE_VERSION
};
//====================
bool pbms_initialize(const char *engine_name, bool isServer, PBMSResultPtr result)
{
int err;
strncpy(enabled_engine.ms_engine_name, engine_name, 32);
enabled_engine.ms_internal = isServer;
enabled_engine.ms_engine_name[31] = 0;
err = pbms_api.registerEngine(&enabled_engine, result);
return (err == 0);
}
//====================
void pbms_finalize()
{
pbms_api.deregisterEngine(&enabled_engine);
}
//====================
int pbms_write_row_blobs(TABLE *table, uchar *row_buffer, PBMSResultPtr result)
{
Field_blob *field;
char *blob_rec, *blob;
size_t packlength, i, org_length, length;
char blob_url_buffer[PBMS_BLOB_URL_SIZE];
int err;
String type_name;
if (table->s->blob_fields == 0)
return 0;
for (i= 0; i < table->s->blob_fields; i++) {
field = GET_BLOB_FIELD(table, i);
// Note: field->type() always returns MYSQL_TYPE_BLOB regardless of the type of BLOB
field->sql_type(type_name);
if (strcasecmp(type_name.c_ptr(), "LongBlob"))
continue;
// Get the blob record:
blob_rec = (char *)row_buffer + field->offset(field->table->record[0]);
packlength = field->pack_length() - field->table->s->blob_ptr_size;
memcpy(&blob, blob_rec +packlength, sizeof(char*));
org_length = field->get_length((uchar *)blob_rec);
// Signal PBMS to record a new reference to the BLOB.
// If 'blob' is not a BLOB URL then it will be stored in the repositor as a new BLOB
// and a reference to it will be created.
err = pbms_api.retainBlob(DB_NAME(field), TAB_NAME(field), blob_url_buffer, blob, org_length, field->field_index, result);
if (err)
return err;
// If the BLOB length changed reset it.
// This will happen if the BLOB data was replaced with a BLOB reference.
length = strlen(blob_url_buffer) +1;
if ((length != org_length) || memcmp(blob_url_buffer, blob, length)) {
if (length != org_length) {
field->store_length((uchar *)blob_rec, packlength, length);
}
if (length > org_length) {
// This can only happen if the BLOB URL is actually larger than the BLOB itself.
blob = (char *) session_alloc(current_session, length);
memcpy(blob_rec+packlength, &blob, sizeof(char*));
}
memcpy(blob, blob_url_buffer, length);
}
}
return 0;
}
//====================
int pbms_delete_row_blobs(TABLE *table, const uchar *row_buffer, PBMSResultPtr result)
{
Field_blob *field;
const char *blob_rec;
char *blob;
size_t packlength, i, length;
int err;
String type_name;
if (table->s->blob_fields == 0)
return 0;
for (i= 0; i < table->s->blob_fields; i++) {
field = GET_BLOB_FIELD(table, i);
// Note: field->type() always returns MYSQL_TYPE_BLOB regardless of the type of BLOB
field->sql_type(type_name);
if (strcasecmp(type_name.c_ptr(), "LongBlob"))
continue;
// Get the blob record:
blob_rec = (char *)row_buffer + field->offset(field->table->record[0]);
packlength = field->pack_length() - field->table->s->blob_ptr_size;
length = field->get_length((uchar *)blob_rec);
memcpy(&blob, blob_rec +packlength, sizeof(char*));
// Signal PBMS to delete the reference to the BLOB.
err = pbms_api.releaseBlob(DB_NAME(field), TAB_NAME(field), blob, length, result);
if (err)
return err;
}
return 0;
}
#define MAX_NAME_SIZE 64
static void parse_table_path(const char *path, char *db_name, char *tab_name)
{
const char *ptr = path + strlen(path) -1, *eptr;
int len;
*db_name = *tab_name = 0;
while ((ptr > path) && (*ptr != '/'))ptr --;
if (*ptr != '/')
return;
strncpy(tab_name, ptr+1, MAX_NAME_SIZE);
tab_name[MAX_NAME_SIZE-1] = 0;
eptr = ptr;
ptr--;
while ((ptr > path) && (*ptr != '/'))ptr --;
if (*ptr != '/')
return;
ptr++;
len = eptr - ptr;
if (len >= MAX_NAME_SIZE)
len = MAX_NAME_SIZE-1;
memcpy(db_name, ptr, len);
db_name[len] = 0;
}
//====================
int pbms_rename_table_with_blobs(const char *old_table_path, const char *new_table_path, PBMSResultPtr result)
{
char o_db_name[MAX_NAME_SIZE], n_db_name[MAX_NAME_SIZE], o_tab_name[MAX_NAME_SIZE], n_tab_name[MAX_NAME_SIZE];
parse_table_path(old_table_path, o_db_name, o_tab_name);
parse_table_path(new_table_path, n_db_name, n_tab_name);
if (strcmp(o_db_name, n_db_name)) {
result->mr_code = MS_ERR_INVALID_OPERATION;
strcpy(result->mr_message, "PBMS does not support renaming tables across databases.");
strcpy(result->mr_stack, "pbms_rename_table_with_blobs()");
return MS_ERR_INVALID_OPERATION;
}
return pbms_api.renameTable(o_db_name, o_tab_name, n_tab_name, result);
}
//====================
int pbms_delete_table_with_blobs(const char *table_path, PBMSResultPtr result)
{
char db_name[MAX_NAME_SIZE], tab_name[MAX_NAME_SIZE];
parse_table_path(table_path, db_name, tab_name);
return pbms_api.dropTable(db_name, tab_name, result);
}
//====================
void pbms_completed(TABLE *table, bool ok)
{
if ((!table) || (table->s->blob_fields != 0))
pbms_api.completed(ok) ;
return ;
}
/* Copyright (c) 2009 PrimeBase Technologies GmbH, Germany
*
* PrimeBase Media Stream for MySQL
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Barry Leslie
*
* 2009-07-16
*
* H&G2JCtL
*
* PBMS interface used to enable engines for use with the PBMS engine.
*
* For an example on how to build this into an engine have a look at the PBXT engine
* in file ha_pbxt.cc. Search for 'PBMS_ENABLED'.
*
*/
#ifndef __PBMS_ENABLED_H__
#define __PBMS_ENABLED_H__
#include "pbms.h"
#ifdef DRIZZLED
#include <drizzled/server_includes.h>
#define TABLE Table
#else
#include <mysql_priv.h>
#endif
/*
* pbms_initialize() should be called from the engines plugIn's 'init()' function.
* The engine_name is the name of your engine, "PBXT" or "InnoDB" for example.
*
* The isServer flag indicates if this entire server is being enabled. This is only
* true if this is being built into the server's handler code above the engine level
* calls.
*/
extern bool pbms_initialize(const char *engine_name, bool isServer, PBMSResultPtr result);
/*
* pbms_finalize() should be called from the engines plugIn's 'deinit()' function.
*/
extern void pbms_finalize();
/*
* pbms_write_row_blobs() should be called from the engine's 'write_row' function.
* It can alter the row data so it must be called before any other function using the row data.
* It should also be called from engine's 'update_row' function for the new row.
*
* pbms_completed() must be called after calling pbms_write_row_blobs() and just before
* returning from write_row() to indicate if the operation completed successfully.
*/
extern int pbms_write_row_blobs(TABLE *table, uchar *buf, PBMSResultPtr result);
/*
* pbms_delete_row_blobs() should be called from the engine's 'delete_row' function.
* It should also be called from engine's 'update_row' function for the old row.
*
* pbms_completed() must be called after calling pbms_delete_row_blobs() and just before
* returning from delete_row() to indicate if the operation completed successfully.
*/
extern int pbms_delete_row_blobs(TABLE *table, const uchar *buf, PBMSResultPtr result);
/*
* pbms_rename_table_with_blobs() should be called from the engine's 'rename_table' function.
*
* NOTE: Renaming tables across databases is not supported.
*
* pbms_completed() must be called after calling pbms_rename_table_with_blobs() and just before
* returning from rename_table() to indicate if the operation completed successfully.
*/
extern int pbms_rename_table_with_blobs(const char *old_table_path, const char *new_table_path, PBMSResultPtr result);
/*
* pbms_delete_table_with_blobs() should be called from the engine's 'delete_table' function.
*
* NOTE: Currently pbms_delete_table_with_blobs() cannot be undone so it should only
* be called after the host engine has performed successfully drop it's table.
*
* pbms_completed() must be called after calling pbms_delete_table_with_blobs() and just before
* returning from delete_table() to indicate if the operation completed successfully.
*/
extern int pbms_delete_table_with_blobs(const char *table_path, PBMSResultPtr result);
/*
* pbms_completed() must be called to indicate success or failure of a an operation after having
* called pbms_write_row_blobs(), pbms_delete_row_blobs(), pbms_rename_table_with_blobs(), or
* pbms_delete_table_with_blobs().
*
* pbms_completed() has the effect of committing or rolling back the changes made if the session
* is in 'autocommit' mode.
*/
extern void pbms_completed(TABLE *table, bool ok);
#endif
......@@ -395,8 +395,12 @@ int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mt, struct timespec *
int xt_p_join(pthread_t thread, void **value)
{
switch (WaitForSingleObject(thread, INFINITE)) {
DWORD exitcode;
while(1) {
switch (WaitForSingleObject(thread, 10000)) {
case WAIT_OBJECT_0:
return 0;
case WAIT_TIMEOUT:
/* Don't do this! According to the Win docs:
* _endthread automatically closes the thread handle
......@@ -405,10 +409,17 @@ int xt_p_join(pthread_t thread, void **value)
* thread handle by calling the Win32 CloseHandle API.
CloseHandle(thread);
*/
/* This is done so that if the thread was not [yet] in the running
* state when this function was called we won't deadlock here.
*/
if (GetExitCodeThread(thread, &exitcode) && (exitcode == STILL_ACTIVE))
break;
return 0;
case WAIT_FAILED:
return GetLastError();
}
}
return 0;
}
......
......@@ -496,7 +496,7 @@ static xtBool xres_add_index_entries(XTOpenTablePtr ot, xtRowID row_id, xtRecord
/* TODO: Write something to the index header to indicate that
* it is corrupted.
*/
tab->tab_dic.dic_disable_index = XT_INDEX_CORRUPTED;
xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED);
xt_log_and_clear_exception_ns();
return OK;
}
......@@ -629,6 +629,9 @@ static void xres_apply_change(XTThreadPtr self, XTOpenTablePtr ot, XTXactLogBuff
xtWord1 *rec_data = NULL;
XTTabRecFreeDPtr free_data;
if (tab->tab_dic.dic_key_count == 0)
check_index = FALSE;
switch (record->xl.xl_status_1) {
case XT_LOG_ENT_REC_MODIFIED:
case XT_LOG_ENT_UPDATE:
......@@ -642,7 +645,7 @@ static void xres_apply_change(XTThreadPtr self, XTOpenTablePtr ot, XTXactLogBuff
/* This should be done before we apply change to table, as otherwise we lose
* the key value that we need to remove from index
*/
if (check_index && ot->ot_table->tab_dic.dic_key_count && record->xl.xl_status_1 == XT_LOG_ENT_REC_MODIFIED) {
if (check_index && record->xl.xl_status_1 == XT_LOG_ENT_REC_MODIFIED) {
if ((rec_data = xres_load_record(self, ot, rec_id, NULL, 0, rec_buf, tab->tab_dic.dic_ind_cols_req)))
xres_remove_index_entries(ot, rec_id, rec_data);
}
......@@ -652,7 +655,7 @@ static void xres_apply_change(XTThreadPtr self, XTOpenTablePtr ot, XTXactLogBuff
xt_throw(self);
tab->tab_bytes_to_flush += len;
if (check_index && ot->ot_table->tab_dic.dic_key_count) {
if (check_index) {
switch (record->xl.xl_status_1) {
case XT_LOG_ENT_DELETE:
case XT_LOG_ENT_DELETE_BG:
......@@ -851,9 +854,6 @@ static void xres_apply_change(XTThreadPtr self, XTOpenTablePtr ot, XTXactLogBuff
goto do_rec_freed;
record_loaded = TRUE;
}
#ifdef XT_STREAMING
myxt_release_blobs(ot, rec_data, rec_id);
#endif
}
if (record->xl.xl_status_1 == XT_LOG_ENT_REC_REMOVED_EXT) {
......@@ -959,31 +959,12 @@ static void xres_apply_change(XTThreadPtr self, XTOpenTablePtr ot, XTXactLogBuff
if (check_index) {
cols_required = tab->tab_dic.dic_ind_cols_req;
#ifdef XT_STREAMING
if (tab->tab_dic.dic_blob_cols_req > cols_required)
cols_required = tab->tab_dic.dic_blob_cols_req;
#endif
if (!(rec_data = xres_load_record(self, ot, rec_id, &record->rb.rb_rec_type_1, rec_size, rec_buf, cols_required)))
goto go_on_to_free;
record_loaded = TRUE;
xres_remove_index_entries(ot, rec_id, rec_data);
}
#ifdef XT_STREAMING
if (tab->tab_dic.dic_blob_count) {
if (!record_loaded) {
cols_required = tab->tab_dic.dic_blob_cols_req;
if (!(rec_data = xres_load_record(self, ot, rec_id, &record->rb.rb_rec_type_1, rec_size, rec_buf, cols_required)))
/* [(7)] REMOVE is followed by FREE:
goto get_rec_offset;
*/
goto go_on_to_free;
record_loaded = TRUE;
}
myxt_release_blobs(ot, rec_data, rec_id);
}
#endif
if (data_log_id && data_log_offset && log_over_size) {
if (!ot->ot_thread->st_dlog_buf.dlb_delete_log(data_log_id, data_log_offset, log_over_size, tab->tab_id, rec_id, self)) {
if (ot->ot_thread->t_exception.e_xt_err != XT_ERR_BAD_EXT_RECORD &&
......
This diff is collapsed.
/* Copyright (c) 2005 PrimeBase Technologies GmbH
*
* PrimeBase XT
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2006-06-07 Paul McCullagh
*
* H&G2JCtL
*
* This file contains PBXT streaming interface.
*/
#ifndef __streaming_xt_h__
#define __streaming_xt_h__
#include "xt_defs.h"
#define PBMS_API pbms_api_PBXT
#include "pbms.h"
xtBool xt_init_streaming(void);
void xt_exit_streaming(void);
void xt_pbms_close_all_tables(const char *table_url);
xtBool xt_pbms_close_connection(void *thd, XTExceptionPtr e);
xtBool xt_pbms_open_table(void **open_table, char *table_path);
void xt_pbms_close_table(void *open_table);
xtBool xt_pbms_use_blob(void *open_table, char **ret_blob_url, char *blob_url, unsigned short col_index);
xtBool xt_pbms_retain_blobs(void *open_table, PBMSEngineRefPtr eng_ref);
void xt_pbms_release_blob(void *open_table, char *blob_url, unsigned short col_index, PBMSEngineRefPtr eng_ref);
void xt_pbms_drop_table(const char *table_path);
void xt_pbms_rename_table(const char *from_table, const char *to_table);
#endif
......@@ -368,7 +368,7 @@ xtPublic void xt_int8_to_byte_size(xtInt8 value, char *string)
/* Version number must also be set in configure.in! */
xtPublic c_char *xt_get_version(void)
{
return "1.0.08 RC";
return "1.0.08c RC";
}
/* Copy and URL decode! */
......
This diff is collapsed.
......@@ -333,6 +333,7 @@ typedef struct XTTable : public XTHeap {
/* Values that belong in the header when flushed! */
xtBool tab_flush_pending; /* TRUE if the table needs to be flushed */
xtBool tab_recovery_done; /* TRUE if the table has been recovered */
xtBool tab_repair_pending; /* TRUE if the table has been marked for repair */
xtBool tab_temporary; /* TRUE if this is a temporary table {TEMP-TABLES}. */
off_t tab_bytes_to_flush; /* Number of bytes of the record/row files to flush. */
......@@ -562,8 +563,13 @@ xtBool xt_tab_put_eof_rec_data(XTOpenTablePtr ot, xtRecordID rec_id, size_t s
xtBool xt_tab_put_log_op_rec_data(XTOpenTablePtr ot, u_int status, xtRecordID free_rec_id, xtRecordID rec_id, size_t size, xtWord1 *buffer);
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);
xtBool xt_tab_get_rec_data(register XTOpenTablePtr ot, xtRecordID rec_id, size_t size, xtWord1 *buffer);
void xt_tab_disable_index(XTTableHPtr tab, u_int ind_error);
void xt_tab_set_index_error(XTTableHPtr tab);
xtBool xt_tab_is_table_repair_pending(XTTableHPtr tab);
void xt_tab_table_repaired(XTTableHPtr tab);
void xt_tab_set_table_repair_pending(XTTableHPtr tab);
inline off_t xt_row_id_to_row_offset(register XTTableHPtr tab, xtRowID row_id)
{
return (off_t) tab->tab_rows.tci_header_size + (off_t) (row_id - 1) * (off_t) tab->tab_rows.tci_rec_size;
......@@ -631,3 +637,4 @@ inline xtIndexNodeID xt_ind_offset_to_node(register XTTableHPtr tab, off_t ind_o
while (0)
#endif
......@@ -1132,6 +1132,7 @@ xtBool XTDatabaseLog::xlog_append(XTThreadPtr thread, size_t size1, xtWord1 *dat
/* [(8)] Flush the compactor log. */
xt_lock_mutex_ns(&xl_db->db_co_dlog_lock);
if (!xl_db->db_co_thread->st_dlog_buf.dlb_flush_log(TRUE, thread)) {
xl_log_bytes_written -= part_size;
xt_unlock_mutex_ns(&xl_db->db_co_dlog_lock);
goto write_failed;
}
......@@ -1140,8 +1141,10 @@ xtBool XTDatabaseLog::xlog_append(XTThreadPtr thread, size_t size1, xtWord1 *dat
/* And flush if required: */
flush_time = thread->st_statistics.st_xlog.ts_flush_time;
if (!xt_flush_file(xl_log_file, &thread->st_statistics.st_xlog, thread))
if (!xt_flush_file(xl_log_file, &thread->st_statistics.st_xlog, thread)) {
xl_log_bytes_written -= part_size;
goto write_failed;
}
xl_last_flush_time = (u_int) (thread->st_statistics.st_xlog.ts_flush_time - flush_time);
xl_log_bytes_flushed = xl_log_bytes_written;
......@@ -2514,9 +2517,6 @@ static void xlog_wr_main(XTThreadPtr self)
if (!record) {
break;
}
/* Count the number of bytes read from the log: */
db->db_xlog.xl_log_bytes_read += ws->ws_seqread.xseq_record_len;
switch (record->xl.xl_status_1) {
case XT_LOG_ENT_HEADER:
break;
......@@ -2540,6 +2540,8 @@ static void xlog_wr_main(XTThreadPtr self)
xt_xres_apply_in_order(self, ws, ws->ws_seqread.xseq_rec_log_id, ws->ws_seqread.xseq_rec_log_offset, record);
break;
}
/* Count the number of bytes read from the log: */
db->db_xlog.xl_log_bytes_read += ws->ws_seqread.xseq_record_len;
}
}
......
......@@ -81,7 +81,7 @@ const int max_connections = 500;
#define DEBUG
#endif // _DEBUG
#else
#define XT_STREAMING
#define PBMS_ENABLED
#endif
#ifdef __FreeBSD__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment