Commit 4c6971b4 authored by unknown's avatar unknown

Manually merging changes made to MyISAM into Maria. End of merge.


storage/maria/ft_maria.c:
  Rename: BitKeeper/deleted/.del-ft_maria.c -> storage/maria/ft_maria.c
configure.in:
  maria moves to its plug.in
storage/maria/Makefile.am:
  merging changes made to MyISAM into Maria.
  ft_maria.c is still needed.
storage/maria/ha_maria.cc:
  merging changes made to MyISAM into Maria
storage/maria/ma_dynrec.c:
  merging changes made to MyISAM into Maria
storage/maria/ma_extra.c:
  merging changes made to MyISAM into Maria
storage/maria/ma_ft_parser.c:
  merging changes made to MyISAM into Maria
storage/maria/ma_open.c:
  merging changes made to MyISAM into Maria
storage/maria/ma_sort.c:
  merging changes made to MyISAM into Maria
storage/maria/ma_update.c:
  merging changes made to MyISAM into Maria
storage/maria/ma_write.c:
  merging changes made to MyISAM into Maria
storage/maria/maria_def.h:
  merging changes made to MyISAM into Maria
storage/myisam/Makefile.am:
  merging changes made to MyISAM into Maria
storage/maria/plug.in:
  merging changes made to MyISAM into Maria
parent 5920b021
...@@ -2149,13 +2149,6 @@ MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support], ...@@ -2149,13 +2149,6 @@ MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support],
[MySQL Partitioning Support], [max,max-no-ndb]) [MySQL Partitioning Support], [max,max-no-ndb])
dnl -- ndbcluster requires partition to be enabled dnl -- ndbcluster requires partition to be enabled
MYSQL_PLUGIN_DEPENDS(ndbcluster, [partition])
MYSQL_STORAGE_ENGINE(maria,maria, [Maria Storage Engine],
[Traditional transactional MySQL tables], [max,max-no-ndb])
MYSQL_PLUGIN_DIRECTORY(maria, [storage/maria])
MYSQL_PLUGIN_STATIC(maria, [libmaria.a])
MYSQL_PLUGIN_MANDATORY(maria)
MYSQL_CONFIGURE_PLUGINS([none]) MYSQL_CONFIGURE_PLUGINS([none])
......
...@@ -14,31 +14,87 @@ ...@@ -14,31 +14,87 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
MYSQLLIBdir= $(pkglibdir)
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/sql \
-I$(srcdir)
WRAPLIBS=
LDADD =
DEFS = @DEFS@
EXTRA_DIST = ma_test_all.sh ma_test_all.res ma_ft_stem.c CMakeLists.txt EXTRA_DIST = ma_test_all.sh ma_test_all.res ma_ft_stem.c CMakeLists.txt
pkgdata_DATA = ma_test_all ma_test_all.res pkgdata_DATA = ma_test_all ma_test_all.res
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
pkglib_LIBRARIES = libmaria.a pkglib_LIBRARIES = libmaria.a
bin_PROGRAMS = maria_chk maria_pack maria_ftdump bin_PROGRAMS = maria_chk maria_pack maria_ftdump
maria_chk_DEPENDENCIES= $(LIBRARIES) maria_chk_DEPENDENCIES= $(LIBRARIES)
# Only reason to link with libmyisam.a here is that it's where some fulltext
# pieces are (but soon we'll remove fulltext dependencies from Maria).
# For now, it imposes that storage/myisam be built before storage/maria.
maria_chk_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
maria_pack_DEPENDENCIES=$(LIBRARIES) maria_pack_DEPENDENCIES=$(LIBRARIES)
maria_pack_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
noinst_PROGRAMS = ma_test1 ma_test2 ma_test3 ma_rt_test ma_sp_test ma_control_file_test noinst_PROGRAMS = ma_test1 ma_test2 ma_test3 ma_rt_test ma_sp_test ma_control_file_test
noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h \ noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h \
ma_sp_defs.h ma_fulltext.h ma_ftdefs.h ma_ft_test1.h ma_ft_eval.h \ ma_sp_defs.h ma_fulltext.h ma_ftdefs.h ma_ft_test1.h ma_ft_eval.h \
ma_control_file.h ma_control_file.h ha_maria.h
ma_test1_DEPENDENCIES= $(LIBRARIES) ma_test1_DEPENDENCIES= $(LIBRARIES)
ma_test1_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
ma_test2_DEPENDENCIES= $(LIBRARIES) ma_test2_DEPENDENCIES= $(LIBRARIES)
ma_test2_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
ma_test3_DEPENDENCIES= $(LIBRARIES) ma_test3_DEPENDENCIES= $(LIBRARIES)
ma_test3_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
#ma_ft_test1_DEPENDENCIES= $(LIBRARIES) #ma_ft_test1_DEPENDENCIES= $(LIBRARIES)
#ma_ft_eval_DEPENDENCIES= $(LIBRARIES) #ma_ft_eval_DEPENDENCIES= $(LIBRARIES)
maria_ftdump_DEPENDENCIES= $(LIBRARIES) maria_ftdump_DEPENDENCIES= $(LIBRARIES)
maria_ftdump_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
ma_rt_test_DEPENDENCIES= $(LIBRARIES) ma_rt_test_DEPENDENCIES= $(LIBRARIES)
ma_rt_test_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
ma_sp_test_DEPENDENCIES= $(LIBRARIES) ma_sp_test_DEPENDENCIES= $(LIBRARIES)
ma_sp_test_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
ma_control_file_test_DEPENDENCIES= $(LIBRARIES)
ma_control_file_test_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_rnext.c ma_rnext_same.c \ ma_rnext.c ma_rnext_same.c \
ma_search.c ma_page.c ma_key.c ma_locking.c \ ma_search.c ma_page.c ma_key.c ma_locking.c \
...@@ -53,12 +109,11 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \ ...@@ -53,12 +109,11 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_delete_table.c ma_rename.c ma_check.c \ ma_delete_table.c ma_rename.c ma_check.c \
ma_keycache.c ma_preload.c ma_ft_parser.c \ ma_keycache.c ma_preload.c ma_ft_parser.c \
ma_ft_update.c ma_ft_boolean_search.c \ ma_ft_update.c ma_ft_boolean_search.c \
ma_ft_nlq_search.c ma_sort.c \ ma_ft_nlq_search.c ft_maria.c ma_sort.c \
ha_maria.cc \
ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c \ ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c \
ma_sp_key.c \ ma_sp_key.c ma_control_file.c
ma_control_file.c
CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA? maria_control CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA? maria_control
DEFS =
SUFFIXES = .sh SUFFIXES = .sh
......
/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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 */
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
/*
This function is for interface functions between fulltext and maria
*/
#include "ma_ftdefs.h"
FT_INFO *maria_ft_init_search(uint flags, void *info, uint keynr,
byte *query, uint query_len, CHARSET_INFO *cs,
byte *record)
{
FT_INFO *res;
if (flags & FT_BOOL)
res= maria_ft_init_boolean_search((MARIA_HA *) info, keynr, query,
query_len, cs);
else
res= maria_ft_init_nlq_search((MARIA_HA *) info, keynr, query, query_len,
flags, record);
return res;
}
const struct _ft_vft _ma_ft_vft_nlq = {
maria_ft_nlq_read_next, maria_ft_nlq_find_relevance,
maria_ft_nlq_close_search, maria_ft_nlq_get_relevance,
maria_ft_nlq_reinit_search
};
const struct _ft_vft _ma_ft_vft_boolean = {
maria_ft_boolean_read_next, maria_ft_boolean_find_relevance,
maria_ft_boolean_close_search, maria_ft_boolean_get_relevance,
maria_ft_boolean_reinit_search
};
...@@ -19,18 +19,15 @@ ...@@ -19,18 +19,15 @@
#pragma implementation // gcc: Class implementation #pragma implementation // gcc: Class implementation
#endif #endif
#define MYSQL_SERVER 1
#include "mysql_priv.h" #include "mysql_priv.h"
#include <mysql/plugin.h>
#include <m_ctype.h> #include <m_ctype.h>
#include <myisampack.h> #include <myisampack.h>
#include "ha_maria.h" #include "ha_maria.h"
#ifndef MASTER
#include "../srclib/maria/maria_def.h"
#else
#include "../storage/maria/maria_def.h"
#include "../storage/maria/ma_rt_index.h"
#endif
#include <mysql/plugin.h> #include "maria_def.h"
#include "ma_rt_index.h"
ulong maria_recover_options= HA_RECOVER_NONE; ulong maria_recover_options= HA_RECOVER_NONE;
...@@ -288,6 +285,15 @@ bool ha_maria::check_if_locking_is_allowed(uint sql_command, ...@@ -288,6 +285,15 @@ bool ha_maria::check_if_locking_is_allowed(uint sql_command,
table->s->table_name.str); table->s->table_name.str);
return FALSE; return FALSE;
} }
/*
Deny locking of the log tables, which is incompatible with
concurrent insert. Unless called from a logger THD:
general_log_thd or slow_log_thd.
*/
if (!called_by_logger_thread)
return check_if_log_table_locking_is_allowed(sql_command, type, table);
return TRUE; return TRUE;
} }
...@@ -486,11 +492,14 @@ int ha_maria::restore(THD * thd, HA_CHECK_OPT *check_opt) ...@@ -486,11 +492,14 @@ int ha_maria::restore(THD * thd, HA_CHECK_OPT *check_opt)
HA_CHECK_OPT tmp_check_opt; HA_CHECK_OPT tmp_check_opt;
char *backup_dir= thd->lex->backup_dir; char *backup_dir= thd->lex->backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char src_path[FN_REFLEN], dst_path[FN_REFLEN];
const char *table_name= table->s->table_name.str; char table_name[FN_REFLEN];
int error; int error;
const char *errmsg; const char *errmsg;
DBUG_ENTER("restore"); DBUG_ENTER("restore");
VOID(tablename_to_filename(table->s->table_name.str, table_name,
sizeof(table_name)));
if (fn_format_relative_to_data_home(src_path, table_name, backup_dir, if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
MARIA_NAME_DEXT)) MARIA_NAME_DEXT))
DBUG_RETURN(HA_ADMIN_INVALID); DBUG_RETURN(HA_ADMIN_INVALID);
...@@ -526,11 +535,14 @@ int ha_maria::backup(THD * thd, HA_CHECK_OPT *check_opt) ...@@ -526,11 +535,14 @@ int ha_maria::backup(THD * thd, HA_CHECK_OPT *check_opt)
{ {
char *backup_dir= thd->lex->backup_dir; char *backup_dir= thd->lex->backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char src_path[FN_REFLEN], dst_path[FN_REFLEN];
const char *table_name= table->s->table_name.str; char table_name[FN_REFLEN];
int error; int error;
const char *errmsg; const char *errmsg;
DBUG_ENTER("ha_maria::backup"); DBUG_ENTER("ha_maria::backup");
VOID(tablename_to_filename(table->s->table_name.str, table_name,
sizeof(table_name)));
if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir, if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
reg_ext)) reg_ext))
{ {
......
...@@ -1304,12 +1304,41 @@ void _ma_store_blob_length(byte *pos,uint pack_length,uint length) ...@@ -1304,12 +1304,41 @@ void _ma_store_blob_length(byte *pos,uint pack_length,uint length)
} }
/* Read record from datafile */ /*
/* Returns 0 if ok, -1 if error */ Read record from datafile.
SYNOPSIS
_ma_read_dynamic_record()
info MARIA_HA pointer to table.
filepos From where to read the record.
buf Destination for record.
NOTE
If a write buffer is active, it needs to be flushed if its contents
intersects with the record to read. We always check if the position
of the first byte of the write buffer is lower than the position
past the last byte to read. In theory this is also true if the write
buffer is completely below the read segment. That is, if there is no
intersection. But this case is unusual. We flush anyway. Only if the
first byte in the write buffer is above the last byte to read, we do
not flush.
A dynamic record may need several reads. So this check must be done
before every read. Reading a dynamic record starts with reading the
block header. If the record does not fit into the free space of the
header, the block may be longer than the header. In this case a
second read is necessary. These one or two reads repeat for every
part of the record.
RETURN
0 OK
-1 Error
*/
int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf) int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf)
{ {
int flag; int block_of_record;
uint b_type,left_length; uint b_type,left_length;
byte *to; byte *to;
MARIA_BLOCK_INFO block_info; MARIA_BLOCK_INFO block_info;
...@@ -1321,20 +1350,19 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf) ...@@ -1321,20 +1350,19 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf)
LINT_INIT(to); LINT_INIT(to);
LINT_INIT(left_length); LINT_INIT(left_length);
file=info->dfile; file=info->dfile;
block_info.next_filepos=filepos; /* for easyer loop */ block_of_record= 0; /* First block of record is numbered as zero. */
flag=block_info.second_read=0; block_info.second_read= 0;
do do
{ {
/* A corrupted table can have wrong pointers. (Bug# 19835) */
if (filepos == HA_OFFSET_ERROR)
goto panic;
if (info->opt_flag & WRITE_CACHE_USED && if (info->opt_flag & WRITE_CACHE_USED &&
info->rec_cache.pos_in_file <= block_info.next_filepos && info->rec_cache.pos_in_file < filepos + MARIA_BLOCK_INFO_HEADER_LENGTH &&
flush_io_cache(&info->rec_cache)) flush_io_cache(&info->rec_cache))
goto err; goto err;
/* A corrupted table can have wrong pointers. (Bug# 19835) */
if (block_info.next_filepos == HA_OFFSET_ERROR)
goto panic;
info->rec_cache.seek_not_done=1; info->rec_cache.seek_not_done=1;
if ((b_type= _ma_get_block_info(&block_info,file, if ((b_type= _ma_get_block_info(&block_info, file, filepos))
block_info.next_filepos))
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
BLOCK_FATAL_ERROR)) BLOCK_FATAL_ERROR))
{ {
...@@ -1342,15 +1370,14 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf) ...@@ -1342,15 +1370,14 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf)
my_errno=HA_ERR_RECORD_DELETED; my_errno=HA_ERR_RECORD_DELETED;
goto err; goto err;
} }
if (flag == 0) /* First block */ if (block_of_record++ == 0) /* First block */
{ {
flag=1;
if (block_info.rec_len > (uint) info->s->base.max_pack_length) if (block_info.rec_len > (uint) info->s->base.max_pack_length)
goto panic; goto panic;
if (info->s->base.blobs) if (info->s->base.blobs)
{ {
if (!(to=_ma_alloc_rec_buff(info, block_info.rec_len, if (!(to=_ma_alloc_rec_buff(info, block_info.rec_len,
&info->rec_buff))) &info->rec_buff)))
goto err; goto err;
} }
else else
...@@ -1359,11 +1386,41 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf) ...@@ -1359,11 +1386,41 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf)
} }
if (left_length < block_info.data_len || ! block_info.data_len) if (left_length < block_info.data_len || ! block_info.data_len)
goto panic; /* Wrong linked record */ goto panic; /* Wrong linked record */
if (info->s->file_read(info,(byte*) to,block_info.data_len,block_info.filepos, /* copy information that is already read */
MYF(MY_NABP))) {
goto panic; uint offset= (uint) (block_info.filepos - filepos);
left_length-=block_info.data_len; uint prefetch_len= (sizeof(block_info.header) - offset);
to+=block_info.data_len; filepos+= sizeof(block_info.header);
if (prefetch_len > block_info.data_len)
prefetch_len= block_info.data_len;
if (prefetch_len)
{
memcpy((byte*) to, block_info.header + offset, prefetch_len);
block_info.data_len-= prefetch_len;
left_length-= prefetch_len;
to+= prefetch_len;
}
}
/* read rest of record from file */
if (block_info.data_len)
{
if (info->opt_flag & WRITE_CACHE_USED &&
info->rec_cache.pos_in_file < filepos + block_info.data_len &&
flush_io_cache(&info->rec_cache))
goto err;
/*
What a pity that this method is not called 'file_pread' and that
there is no equivalent without seeking. We are at the right
position already. :(
*/
if (info->s->file_read(info, (byte*) to, block_info.data_len,
filepos, MYF(MY_NABP)))
goto panic;
left_length-=block_info.data_len;
to+=block_info.data_len;
}
filepos= block_info.next_filepos;
} while (left_length); } while (left_length);
info->update|= HA_STATE_AKTIV; /* We have a aktive record */ info->update|= HA_STATE_AKTIV; /* We have a aktive record */
...@@ -1520,11 +1577,45 @@ static int _ma_cmp_buffer(File file, const byte *buff, my_off_t filepos, ...@@ -1520,11 +1577,45 @@ static int _ma_cmp_buffer(File file, const byte *buff, my_off_t filepos,
} }
/*
Read record from datafile.
SYNOPSIS
_ma_read_rnd_dynamic_record()
info MARIA_HA pointer to table.
buf Destination for record.
filepos From where to read the record.
skip_deleted_blocks If to repeat reading until a non-deleted
record is found.
NOTE
If a write buffer is active, it needs to be flushed if its contents
intersects with the record to read. We always check if the position
of the first byte of the write buffer is lower than the position
past the last byte to read. In theory this is also true if the write
buffer is completely below the read segment. That is, if there is no
intersection. But this case is unusual. We flush anyway. Only if the
first byte in the write buffer is above the last byte to read, we do
not flush.
A dynamic record may need several reads. So this check must be done
before every read. Reading a dynamic record starts with reading the
block header. If the record does not fit into the free space of the
header, the block may be longer than the header. In this case a
second read is necessary. These one or two reads repeat for every
part of the record.
RETURN
0 OK
!= 0 Error
*/
int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf,
register my_off_t filepos, register my_off_t filepos,
my_bool skip_deleted_blocks) my_bool skip_deleted_blocks)
{ {
int flag,info_read,save_errno; int block_of_record, info_read, save_errno;
uint left_len,b_type; uint left_len,b_type;
byte *to; byte *to;
MARIA_BLOCK_INFO block_info; MARIA_BLOCK_INFO block_info;
...@@ -1544,7 +1635,8 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, ...@@ -1544,7 +1635,8 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf,
else else
info_read=1; /* memory-keyinfoblock is ok */ info_read=1; /* memory-keyinfoblock is ok */
flag=block_info.second_read=0; block_of_record= 0; /* First block of record is numbered as zero. */
block_info.second_read= 0;
left_len=1; left_len=1;
do do
{ {
...@@ -1567,15 +1659,15 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, ...@@ -1567,15 +1659,15 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf,
{ {
if (_ma_read_cache(&info->rec_cache,(byte*) block_info.header,filepos, if (_ma_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
sizeof(block_info.header), sizeof(block_info.header),
(!flag && skip_deleted_blocks ? READING_NEXT : 0) | (!block_of_record && skip_deleted_blocks ?
READING_HEADER)) READING_NEXT : 0) | READING_HEADER))
goto panic; goto panic;
b_type= _ma_get_block_info(&block_info,-1,filepos); b_type= _ma_get_block_info(&block_info,-1,filepos);
} }
else else
{ {
if (info->opt_flag & WRITE_CACHE_USED && if (info->opt_flag & WRITE_CACHE_USED &&
info->rec_cache.pos_in_file <= filepos && info->rec_cache.pos_in_file < filepos + MARIA_BLOCK_INFO_HEADER_LENGTH &&
flush_io_cache(&info->rec_cache)) flush_io_cache(&info->rec_cache))
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
info->rec_cache.seek_not_done=1; info->rec_cache.seek_not_done=1;
...@@ -1600,7 +1692,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, ...@@ -1600,7 +1692,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf,
} }
goto err; goto err;
} }
if (flag == 0) /* First block */ if (block_of_record == 0) /* First block */
{ {
if (block_info.rec_len > (uint) share->base.max_pack_length) if (block_info.rec_len > (uint) share->base.max_pack_length)
goto panic; goto panic;
...@@ -1642,11 +1734,17 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, ...@@ -1642,11 +1734,17 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf,
{ {
if (_ma_read_cache(&info->rec_cache,(byte*) to,filepos, if (_ma_read_cache(&info->rec_cache,(byte*) to,filepos,
block_info.data_len, block_info.data_len,
(!flag && skip_deleted_blocks) ? READING_NEXT :0)) (!block_of_record && skip_deleted_blocks) ?
READING_NEXT : 0))
goto panic; goto panic;
} }
else else
{ {
if (info->opt_flag & WRITE_CACHE_USED &&
info->rec_cache.pos_in_file <
block_info.filepos + block_info.data_len &&
flush_io_cache(&info->rec_cache))
goto err;
/* VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); */ /* VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); */
if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP))) if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP)))
{ {
...@@ -1656,7 +1754,11 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, ...@@ -1656,7 +1754,11 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf,
} }
} }
} }
if (flag++ == 0) /*
Increment block-of-record counter. If it was the first block,
remember the position behind the block for the next call.
*/
if (block_of_record++ == 0)
{ {
info->nextpos=block_info.filepos+block_info.block_len; info->nextpos=block_info.filepos+block_info.block_len;
skip_deleted_blocks=0; skip_deleted_blocks=0;
...@@ -1691,6 +1793,11 @@ uint _ma_get_block_info(MARIA_BLOCK_INFO *info, File file, my_off_t filepos) ...@@ -1691,6 +1793,11 @@ uint _ma_get_block_info(MARIA_BLOCK_INFO *info, File file, my_off_t filepos)
if (file >= 0) if (file >= 0)
{ {
/*
We do not use my_pread() here because we want to have the file
pointer set to the end of the header after this function.
my_pread() may leave the file pointer untouched.
*/
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
if (my_read(file,(char*) header,sizeof(info->header),MYF(0)) != if (my_read(file,(char*) header,sizeof(info->header),MYF(0)) !=
sizeof(info->header)) sizeof(info->header))
......
...@@ -366,6 +366,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg ...@@ -366,6 +366,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg
pthread_mutex_unlock(&share->intern_lock); pthread_mutex_unlock(&share->intern_lock);
#endif #endif
break; break;
case HA_EXTRA_MARK_AS_LOG_TABLE:
pthread_mutex_lock(&share->intern_lock);
share->is_log_table= TRUE;
pthread_mutex_unlock(&share->intern_lock);
break;
case HA_EXTRA_KEY_CACHE: case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE: case HA_EXTRA_NO_KEY_CACHE:
default: default:
......
...@@ -283,7 +283,7 @@ static int maria_ft_add_word(MYSQL_FTPARSER_PARAM *param, ...@@ -283,7 +283,7 @@ static int maria_ft_add_word(MYSQL_FTPARSER_PARAM *param,
static int maria_ft_parse_internal(MYSQL_FTPARSER_PARAM *param, static int maria_ft_parse_internal(MYSQL_FTPARSER_PARAM *param,
byte *doc, int doc_len) char *doc, int doc_len)
{ {
byte *end=doc+doc_len; byte *end=doc+doc_len;
MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam; MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam;
......
...@@ -475,6 +475,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -475,6 +475,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->data_file_type = DYNAMIC_RECORD; share->data_file_type = DYNAMIC_RECORD;
my_afree((gptr) disk_cache); my_afree((gptr) disk_cache);
_ma_setup_functions(share); _ma_setup_functions(share);
share->is_log_table= FALSE;
#ifdef THREAD #ifdef THREAD
thr_lock_init(&share->lock); thr_lock_init(&share->lock);
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST)); VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
......
...@@ -479,12 +479,6 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) ...@@ -479,12 +479,6 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
if (!got_error) if (!got_error)
{ {
maria_set_key_active(share->state.key_map, sinfo->key); maria_set_key_active(share->state.key_map, sinfo->key);
if (param->testflag & T_STATISTICS)
maria_update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique,
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
sinfo->notnull: NULL,
(ulonglong) info->state->records);
if (!sinfo->buffpek.elements) if (!sinfo->buffpek.elements)
{ {
...@@ -497,6 +491,11 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) ...@@ -497,6 +491,11 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
flush_maria_ft_buf(sinfo) || _ma_flush_pending_blocks(sinfo)) flush_maria_ft_buf(sinfo) || _ma_flush_pending_blocks(sinfo))
got_error=1; got_error=1;
} }
if (!got_error && param->testflag & T_STATISTICS)
maria_update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique,
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
sinfo->notnull: NULL,
(ulonglong) info->state->records);
} }
my_free((gptr) sinfo->sort_keys,MYF(0)); my_free((gptr) sinfo->sort_keys,MYF(0));
my_free(_ma_get_rec_buff_ptr(info, sinfo->rec_buff), my_free(_ma_get_rec_buff_ptr(info, sinfo->rec_buff),
......
...@@ -171,7 +171,18 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) ...@@ -171,7 +171,18 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec)
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
key_changed); key_changed);
VOID(_ma_writeinfo(info,key_changed ? WRITEINFO_UPDATE_KEYFILE : 0));
/*
Every Maria function that updates Maria table must end with
call to _ma_writeinfo(). If operation (second param of
_ma_writeinfo()) is not 0 it sets share->changed to 1, that is
flags that data has changed. If operation is 0, this function
equals to no-op in this case.
ma_update() must always pass !0 value as operation, since even if
there is no index change there could be data change.
*/
VOID(_ma_writeinfo(info, WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */ allow_break(); /* Allow SIGHUP & SIGINT */
if (info->invalidator != 0) if (info->invalidator != 0)
{ {
......
...@@ -158,6 +158,18 @@ int maria_write(MARIA_HA *info, byte *record) ...@@ -158,6 +158,18 @@ int maria_write(MARIA_HA *info, byte *record)
(*info->invalidator)(info->filename); (*info->invalidator)(info->filename);
info->invalidator=0; info->invalidator=0;
} }
/*
Update status of the table. We need to do so after each row write
for the log tables, as we want the new row to become visible to
other threads as soon as possible. We lock mutex here to follow
pthread memory visibility rules.
*/
pthread_mutex_lock(&share->intern_lock);
if (share->is_log_table)
_ma_update_status((void*) info);
pthread_mutex_unlock(&share->intern_lock);
allow_break(); /* Allow SIGHUP & SIGINT */ allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -211,6 +211,9 @@ typedef struct st_maria_share ...@@ -211,6 +211,9 @@ typedef struct st_maria_share
uint blocksize; /* blocksize of keyfile */ uint blocksize; /* blocksize of keyfile */
myf write_flag; myf write_flag;
enum data_file_type data_file_type; enum data_file_type data_file_type;
/* Below flag is needed to make log tables work with concurrent insert */
my_bool is_log_table;
my_bool changed, /* If changed since lock */ my_bool changed, /* If changed since lock */
global_changed, /* If changed since open */ global_changed, /* If changed since open */
not_flushed, temporary, delay_key_write, concurrent_insert; not_flushed, temporary, delay_key_write, concurrent_insert;
......
MYSQL_STORAGE_ENGINE(maria, no, [Maria Storage Engine],
[Traditional transactional MySQL tables], [max,max-no-ndb])
MYSQL_PLUGIN_DIRECTORY(maria, [storage/maria])
MYSQL_PLUGIN_STATIC(maria, [libmaria.a])
# Maria will probably go first into max builds, not all builds,
# so we don't declare it mandatory.
...@@ -99,7 +99,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \ ...@@ -99,7 +99,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_keycache.c mi_preload.c \ mi_keycache.c mi_preload.c \
ft_parser.c ft_stopwords.c ft_static.c \ ft_parser.c ft_stopwords.c ft_static.c \
ft_update.c ft_boolean_search.c ft_nlq_search.c \ ft_update.c ft_boolean_search.c ft_nlq_search.c \
sort.c ha_myisam.cc \ sort.c ha_myisam.cc ft_myisam.c \
rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c
CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all rt_test.MY? sp_test.MY? CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all rt_test.MY? sp_test.MY?
......
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