Commit d0ccff50 authored by monty@bitch.mysql.fi's avatar monty@bitch.mysql.fi

New improved IO_CACHE

parent d3288575
#! /bin/sh
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
aclocal && autoheader && aclocal && automake && autoconf
(cd bdb/dist && sh s_all)
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
if [ -d gemini ]
then
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
fi
CFLAGS="-g -Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wextern-inline -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-debug
gmake -j 4
...@@ -324,11 +324,6 @@ typedef unsigned short ushort; ...@@ -324,11 +324,6 @@ typedef unsigned short ushort;
#endif #endif
#include <dbug.h> #include <dbug.h>
#ifndef DBUG_OFF
#define dbug_assert(A) assert(A)
#else
#define dbug_assert(A)
#endif
#define MIN_ARRAY_SIZE 0 /* Zero or One. Gcc allows zero*/ #define MIN_ARRAY_SIZE 0 /* Zero or One. Gcc allows zero*/
#define ASCII_BITS_USED 8 /* Bit char used */ #define ASCII_BITS_USED 8 /* Bit char used */
......
...@@ -293,33 +293,21 @@ typedef struct st_dynamic_string { ...@@ -293,33 +293,21 @@ typedef struct st_dynamic_string {
struct st_io_cache; struct st_io_cache;
typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*); typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*);
#ifdef THREAD
#define lock_append_buffer(info) \
pthread_mutex_lock(&(info)->append_buffer_lock)
#define unlock_append_buffer(info) \
pthread_mutex_unlock(&(info)->append_buffer_lock)
#else
#define lock_append_buffer(info)
#define unlock_append_buffer(info)
#endif
typedef struct st_io_cache /* Used when cacheing files */ typedef struct st_io_cache /* Used when cacheing files */
{ {
my_off_t pos_in_file,end_of_file; my_off_t pos_in_file,end_of_file;
byte *rc_pos,*rc_end,*buffer,*rc_request_pos; byte *read_pos,*read_end,*buffer,*request_pos;
my_bool alloced_buffer; /* currented READ_NET is the only one byte *write_buffer, *append_read_pos, *write_pos, *write_end;
that will use a buffer allocated somewhere byte **current_pos, **current_end;
else /* The lock is for append buffer used in READ_APPEND cache */
*/
byte *append_buffer, *append_read_pos, *write_pos, *append_end,
*write_end;
/* for append buffer used in READ_APPEND cache */
#ifdef THREAD #ifdef THREAD
pthread_mutex_t append_buffer_lock; pthread_mutex_t append_buffer_lock;
/* need mutex copying from append buffer to read buffer */ /* need mutex copying from append buffer to read buffer */
#endif #endif
int (*read_function)(struct st_io_cache *,byte *,uint); int (*read_function)(struct st_io_cache *,byte *,uint);
int (*write_function)(struct st_io_cache *,const byte *,uint); int (*write_function)(struct st_io_cache *,const byte *,uint);
enum cache_type type;
/* callbacks when the actual read I/O happens */ /* callbacks when the actual read I/O happens */
IO_CACHE_CALLBACK pre_read; IO_CACHE_CALLBACK pre_read;
IO_CACHE_CALLBACK post_read; IO_CACHE_CALLBACK post_read;
...@@ -331,7 +319,11 @@ typedef struct st_io_cache /* Used when cacheing files */ ...@@ -331,7 +319,11 @@ typedef struct st_io_cache /* Used when cacheing files */
int seek_not_done,error; int seek_not_done,error;
uint buffer_length,read_length; uint buffer_length,read_length;
myf myflags; /* Flags used to my_read/my_write */ myf myflags; /* Flags used to my_read/my_write */
enum cache_type type; /*
Currently READ_NET is the only one that will use a buffer allocated
somewhere else
*/
my_bool alloced_buffer;
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
uint inited; uint inited;
my_off_t aio_read_pos; my_off_t aio_read_pos;
...@@ -349,9 +341,9 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *); ...@@ -349,9 +341,9 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *);
#define my_b_EOF INT_MIN #define my_b_EOF INT_MIN
#define my_b_read(info,Buffer,Count) \ #define my_b_read(info,Buffer,Count) \
((info)->rc_pos + (Count) <= (info)->rc_end ?\ ((info)->read_pos + (Count) <= (info)->read_end ?\
(memcpy(Buffer,(info)->rc_pos,(size_t) (Count)), \ (memcpy(Buffer,(info)->read_pos,(size_t) (Count)), \
((info)->rc_pos+=(Count)),0) :\ ((info)->read_pos+=(Count)),0) :\
(*(info)->read_function)((info),Buffer,Count)) (*(info)->read_function)((info),Buffer,Count))
#define my_b_write(info,Buffer,Count) \ #define my_b_write(info,Buffer,Count) \
...@@ -362,11 +354,10 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *); ...@@ -362,11 +354,10 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *);
#define my_b_get(info) \ #define my_b_get(info) \
((info)->rc_pos != (info)->rc_end ?\ ((info)->read_pos != (info)->read_end ?\
((info)->rc_pos++, (int) (uchar) (info)->rc_pos[-1]) :\ ((info)->read_pos++, (int) (uchar) (info)->read_pos[-1]) :\
_my_b_get(info)) _my_b_get(info))
/* my_b_write_byte dosn't have any err-check */ /* my_b_write_byte dosn't have any err-check */
#define my_b_write_byte(info,chr) \ #define my_b_write_byte(info,chr) \
(((info)->write_pos < (info)->write_end) ?\ (((info)->write_pos < (info)->write_end) ?\
...@@ -374,18 +365,14 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *); ...@@ -374,18 +365,14 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *);
(_my_b_write(info,0,0) , ((*(info)->write_pos++)=(chr)))) (_my_b_write(info,0,0) , ((*(info)->write_pos++)=(chr))))
#define my_b_fill_cache(info) \ #define my_b_fill_cache(info) \
(((info)->rc_end=(info)->rc_pos),(*(info)->read_function)(info,0,0)) (((info)->read_end=(info)->read_pos),(*(info)->read_function)(info,0,0))
#define my_write_cache(info) (((info)->type == WRITE_CACHE))
#define my_cache_pointer(info) (my_write_cache(info) ? \
((info)->write_pos) : ((info)->rc_pos))
#define my_b_tell(info) ((info)->pos_in_file + \ #define my_b_tell(info) ((info)->pos_in_file + \
my_cache_pointer(info) - (info)->rc_request_pos) (uint) (*(info)->current_pos - (info)->request_pos))
#define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \
*(info)->current_pos)
#define my_b_bytes_in_cache(info) (my_write_cache(info) ? \
((uint) ((info)->write_end - (info)->write_pos)): \
((uint) ((info)->rc_end - (info)->rc_pos)))
typedef struct st_changeable_var { typedef struct st_changeable_var {
const char *name; /* Name of variable */ const char *name; /* Name of variable */
...@@ -584,7 +571,7 @@ extern int _my_b_net_read(IO_CACHE *info,byte *Buffer,uint Count); ...@@ -584,7 +571,7 @@ extern int _my_b_net_read(IO_CACHE *info,byte *Buffer,uint Count);
extern int _my_b_get(IO_CACHE *info); extern int _my_b_get(IO_CACHE *info);
extern int _my_b_async_read(IO_CACHE *info,byte *Buffer,uint Count); extern int _my_b_async_read(IO_CACHE *info,byte *Buffer,uint Count);
extern int _my_b_write(IO_CACHE *info,const byte *Buffer,uint Count); extern int _my_b_write(IO_CACHE *info,const byte *Buffer,uint Count);
extern int _my_b_append(IO_CACHE *info,const byte *Buffer,uint Count); extern int my_b_append(IO_CACHE *info,const byte *Buffer,uint Count);
extern int my_block_write(IO_CACHE *info, const byte *Buffer, extern int my_block_write(IO_CACHE *info, const byte *Buffer,
uint Count, my_off_t pos); uint Count, my_off_t pos);
extern int flush_io_cache(IO_CACHE *info); extern int flush_io_cache(IO_CACHE *info);
......
...@@ -46,11 +46,11 @@ int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length, ...@@ -46,11 +46,11 @@ int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length,
buff+=read_length; buff+=read_length;
} }
if ((offset=pos - (ulong) info->pos_in_file) < if ((offset=pos - (ulong) info->pos_in_file) <
(ulong) (info->rc_end - info->rc_request_pos)) (ulong) (info->read_end - info->request_pos))
{ {
in_buff_pos=info->rc_request_pos+(uint) offset; in_buff_pos=info->request_pos+(uint) offset;
in_buff_length= min(length,(uint) (info->rc_end-in_buff_pos)); in_buff_length= min(length,(uint) (info->read_end-in_buff_pos));
memcpy(buff,info->rc_request_pos+(uint) offset,(size_t) in_buff_length); memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
if (!(length-=in_buff_length)) if (!(length-=in_buff_length))
return 0; return 0;
pos+=in_buff_length; pos+=in_buff_length;
...@@ -61,14 +61,14 @@ int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length, ...@@ -61,14 +61,14 @@ int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length,
if (flag & READING_NEXT) if (flag & READING_NEXT)
{ {
if (pos != ((info)->pos_in_file + if (pos != ((info)->pos_in_file +
(uint) ((info)->rc_end - (info)->rc_request_pos))) (uint) ((info)->read_end - (info)->request_pos)))
{ {
info->pos_in_file=pos; /* Force start here */ info->pos_in_file=pos; /* Force start here */
info->rc_pos=info->rc_end=info->rc_request_pos; /* Everything used */ info->read_pos=info->read_end=info->request_pos; /* Everything used */
info->seek_not_done=1; info->seek_not_done=1;
} }
else else
info->rc_pos=info->rc_end; /* All block used */ info->read_pos=info->read_end; /* All block used */
if (!(*info->read_function)(info,buff,length)) if (!(*info->read_function)(info,buff,length))
return 0; return 0;
if (!(flag & READING_HEADER) || info->error == -1 || if (!(flag & READING_HEADER) || info->error == -1 ||
......
...@@ -187,7 +187,7 @@ int _nisam_read_rnd_static_record(N_INFO *info, byte *buf, ...@@ -187,7 +187,7 @@ int _nisam_read_rnd_static_record(N_INFO *info, byte *buf,
(skipp_deleted_blocks || !filepos)) (skipp_deleted_blocks || !filepos))
{ {
cache_read=1; /* Read record using cache */ cache_read=1; /* Read record using cache */
cache_length=(uint) (info->rec_cache.rc_end - info->rec_cache.rc_pos); cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
} }
else else
info->rec_cache.seek_not_done=1; /* Filepos is changed */ info->rec_cache.seek_not_done=1; /* Filepos is changed */
......
...@@ -172,7 +172,7 @@ void start_test(int id) ...@@ -172,7 +172,7 @@ void start_test(int id)
} }
if (key_cacheing && rnd(2) == 0) if (key_cacheing && rnd(2) == 0)
init_key_cache(65536L,(uint) IO_SIZE*4*10); init_key_cache(65536L,(uint) IO_SIZE*4*10);
printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout); printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++) for (error=i=0 ; i < tests && !error; i++)
{ {
...@@ -356,7 +356,7 @@ int test_write(N_INFO *file,int id,int lock_type) ...@@ -356,7 +356,7 @@ int test_write(N_INFO *file,int id,int lock_type)
nisam_extra(file,HA_EXTRA_WRITE_CACHE); nisam_extra(file,HA_EXTRA_WRITE_CACHE);
} }
sprintf(record.id,"%7d",getpid()); sprintf(record.id,"%7d",(int) getpid());
strmov(record.text,"Testing..."); strmov(record.text,"Testing...");
tries=(uint) rnd(100)+10; tries=(uint) rnd(100)+10;
......
...@@ -45,11 +45,11 @@ int _mi_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, uint length, ...@@ -45,11 +45,11 @@ int _mi_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, uint length,
buff+=read_length; buff+=read_length;
} }
if ((offset= (my_off_t) (pos - info->pos_in_file)) < if ((offset= (my_off_t) (pos - info->pos_in_file)) <
(my_off_t) (info->rc_end - info->rc_request_pos)) (my_off_t) (info->read_end - info->request_pos))
{ {
in_buff_pos=info->rc_request_pos+(uint) offset; in_buff_pos=info->request_pos+(uint) offset;
in_buff_length= min(length,(uint) (info->rc_end-in_buff_pos)); in_buff_length= min(length,(uint) (info->read_end-in_buff_pos));
memcpy(buff,info->rc_request_pos+(uint) offset,(size_t) in_buff_length); memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
if (!(length-=in_buff_length)) if (!(length-=in_buff_length))
DBUG_RETURN(0); DBUG_RETURN(0);
pos+=in_buff_length; pos+=in_buff_length;
...@@ -60,14 +60,14 @@ int _mi_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, uint length, ...@@ -60,14 +60,14 @@ int _mi_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, uint length,
if (flag & READING_NEXT) if (flag & READING_NEXT)
{ {
if (pos != ((info)->pos_in_file + if (pos != ((info)->pos_in_file +
(uint) ((info)->rc_end - (info)->rc_request_pos))) (uint) ((info)->read_end - (info)->request_pos)))
{ {
info->pos_in_file=pos; /* Force start here */ info->pos_in_file=pos; /* Force start here */
info->rc_pos=info->rc_end=info->rc_request_pos; /* Everything used */ info->read_pos=info->read_end=info->request_pos; /* Everything used */
info->seek_not_done=1; info->seek_not_done=1;
} }
else else
info->rc_pos=info->rc_end; /* All block used */ info->read_pos=info->read_end; /* All block used */
if (!(*info->read_function)(info,buff,length)) if (!(*info->read_function)(info,buff,length))
DBUG_RETURN(0); DBUG_RETURN(0);
if (!(flag & READING_HEADER) || info->error == -1 || if (!(flag & READING_HEADER) || info->error == -1 ||
......
...@@ -221,7 +221,7 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf, ...@@ -221,7 +221,7 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf,
(skipp_deleted_blocks || !filepos)) (skipp_deleted_blocks || !filepos))
{ {
cache_read=1; /* Read record using cache */ cache_read=1; /* Read record using cache */
cache_length=(uint) (info->rec_cache.rc_end - info->rec_cache.rc_pos); cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
} }
else else
info->rec_cache.seek_not_done=1; /* Filepos is changed */ info->rec_cache.seek_not_done=1; /* Filepos is changed */
......
...@@ -19,7 +19,7 @@ TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work ...@@ -19,7 +19,7 @@ TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work
# Program Definitions # Program Definitions
#-- #--
PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin
# Standard functions # Standard functions
...@@ -49,6 +49,7 @@ BASENAME=`which basename | head -1` ...@@ -49,6 +49,7 @@ BASENAME=`which basename | head -1`
DIFF=`which diff | head -1` DIFF=`which diff | head -1`
CAT=cat CAT=cat
CUT=cut CUT=cut
HEAD=head
TAIL=tail TAIL=tail
ECHO=echo # use internal echo if possible ECHO=echo # use internal echo if possible
EXPR=expr # use internal if possible EXPR=expr # use internal if possible
...@@ -118,7 +119,7 @@ MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \ ...@@ -118,7 +119,7 @@ MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \
# #
# Set LD_LIBRARY_PATH if we are using shared libraries # Set LD_LIBRARY_PATH if we are using shared libraries
# #
LD_LIBRARY_PATH="$BASEDIR/lib:$LD_LIBRARY_PATH" LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH export LD_LIBRARY_PATH
MASTER_RUNNING=0 MASTER_RUNNING=0
...@@ -225,6 +226,8 @@ while test $# -gt 0; do ...@@ -225,6 +226,8 @@ while test $# -gt 0; do
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --gdb option" $ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --gdb option"
fi fi
DO_GDB=1 DO_GDB=1
# We must use manager, as things doesn't work on Linux without it
USE_MANAGER=1
USE_RUNNING_SERVER="" USE_RUNNING_SERVER=""
;; ;;
--client-gdb ) --client-gdb )
...@@ -310,6 +313,8 @@ if [ x$SOURCE_DIST = x1 ] ; then ...@@ -310,6 +313,8 @@ if [ x$SOURCE_DIST = x1 ] ; then
MYSQLD="$BASEDIR/sql/mysqld" MYSQLD="$BASEDIR/sql/mysqld"
if [ -f "$BASEDIR/client/.libs/lt-mysqltest" ] ; then if [ -f "$BASEDIR/client/.libs/lt-mysqltest" ] ; then
MYSQL_TEST="$BASEDIR/client/.libs/lt-mysqltest" MYSQL_TEST="$BASEDIR/client/.libs/lt-mysqltest"
elif [ -f "$BASEDIR/client/.libs/mysqltest" ] ; then
MYSQL_TEST="$BASEDIR/client/.libs/mysqltest"
else else
MYSQL_TEST="$BASEDIR/client/mysqltest" MYSQL_TEST="$BASEDIR/client/mysqltest"
fi fi
...@@ -428,7 +433,7 @@ do_gdb_test () ...@@ -428,7 +433,7 @@ do_gdb_test ()
$ECHO "set args $mysql_test_args < $2" > $GDB_CLIENT_INIT $ECHO "set args $mysql_test_args < $2" > $GDB_CLIENT_INIT
echo "Set breakpoints ( if needed) and type 'run' in gdb window" echo "Set breakpoints ( if needed) and type 'run' in gdb window"
#this xterm should not be backgrounded #this xterm should not be backgrounded
xterm -title "Client" -e gdb -x $GDB_CLIENT_INIT $MYSQL_TEST_BIN $XTERM -title "Client" -e gdb -x $GDB_CLIENT_INIT $MYSQL_TEST_BIN
} }
error () { error () {
...@@ -437,7 +442,7 @@ error () { ...@@ -437,7 +442,7 @@ error () {
} }
error_is () { error_is () {
$TR "\n" " " < $TIMEFILE | $SED -e 's/.* At line \(.*\)\: \(.*\)Command .*$/ \>\> Error at line \1: \2<\</' $CAT < $TIMEFILE | $SED -e 's/.* At line \(.*\)\: \(.*\)/ \>\> Error at line \1: \2<\</' | $HEAD -1
} }
prefix_to_8() { prefix_to_8() {
...@@ -802,8 +807,8 @@ start_slave() ...@@ -802,8 +807,8 @@ start_slave()
elif [ x$DO_GDB = x1 ] elif [ x$DO_GDB = x1 ]
then then
$ECHO "set args $slave_args" > $GDB_SLAVE_INIT $ECHO "set args $slave_args" > $GDB_SLAVE_INIT
manager_launch $slave_ident $XTERM -display $DISPLAY -title "Slave" -e gdb -x \ manager_launch $slave_ident $XTERM -display $DISPLAY -title "Slave" -e \
$GDB_SLAVE_INIT $SLAVE_MYSQLD gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD
else else
manager_launch $slave_ident $SLAVE_MYSQLD $slave_args manager_launch $slave_ident $SLAVE_MYSQLD $slave_args
fi fi
......
drop table if exists t1,t2; drop table if exists t1,t2;
create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)); create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)) type=isam;
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair status OK
delete from t1 where (a & 1); delete from t1 where (a & 1);
check table t1; select sum(length(b)) from t1;
Table Op Msg_type Msg_text sum(length(b))
test.t1 check status OK 3274494
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair status OK
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1; drop table t1;
create table t1 (a int not null auto_increment,b int, primary key (a)) type=isam; create table t1 (a int not null auto_increment,b int, primary key (a)) type=isam;
insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4); insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4);
......
...@@ -6,7 +6,7 @@ drop table if exists t1,t2; ...@@ -6,7 +6,7 @@ drop table if exists t1,t2;
# Test possible problem with rows that are about 65535 bytes long # Test possible problem with rows that are about 65535 bytes long
# #
create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)); create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)) type=isam;
let $1=100; let $1=100;
disable_query_log; disable_query_log;
...@@ -16,12 +16,8 @@ while ($1) ...@@ -16,12 +16,8 @@ while ($1)
dec $1; dec $1;
} }
enable_query_log; enable_query_log;
check table t1;
repair table t1;
delete from t1 where (a & 1); delete from t1 where (a & 1);
check table t1; select sum(length(b)) from t1;
repair table t1;
check table t1;
drop table t1; drop table t1;
# #
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
...@@ -23,12 +23,30 @@ ...@@ -23,12 +23,30 @@
Possibly use of asyncronic io. Possibly use of asyncronic io.
macros for read and writes for faster io. macros for read and writes for faster io.
Used instead of FILE when reading or writing whole files. Used instead of FILE when reading or writing whole files.
This will make mf_rec_cache obsolete. This code makes mf_rec_cache obsolete (currently only used by ISAM)
One can change info->pos_in_file to a higher value to skip bytes in file if One can change info->pos_in_file to a higher value to skip bytes in file if
also info->rc_pos is set to info->rc_end. also info->read_pos is set to info->read_end.
If called through open_cached_file(), then the temporary file will If called through open_cached_file(), then the temporary file will
only be created if a write exeeds the file buffer or if one calls only be created if a write exeeds the file buffer or if one calls
flush_io_cache(). flush_io_cache().
If one uses SEQ_READ_APPEND, then two buffers are allocated, one for
reading and another for writing. Reads are first done from disk and
then done from the write buffer. This is an efficient way to read
from a log file when one is writing to it at the same time.
For this to work, the file has to be opened in append mode!
Note that when one uses SEQ_READ_APPEND, one MUST write using
my_b_append ! This is needed because we need to lock the mutex
every time we access the write buffer.
TODO:
When one SEQ_READ_APPEND and we are reading and writing at the same time,
each time the write buffer gets full and it's written to disk, we will
always do a disk read to read a part of the buffer from disk to the
read buffer.
This should be fixed so that when we do a flush_io_cache() and
we have been reading the write buffer, we should transfer the rest of the
write buffer to the read buffer before we start to reuse it.
*/ */
#define MAP_TO_USE_RAID #define MAP_TO_USE_RAID
...@@ -41,18 +59,20 @@ static void my_aiowait(my_aio_result *result); ...@@ -41,18 +59,20 @@ static void my_aiowait(my_aio_result *result);
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#ifdef MAIN #ifdef THREAD
#include <my_dir.h> #define lock_append_buffer(info) \
pthread_mutex_lock(&(info)->append_buffer_lock)
#define unlock_append_buffer(info) \
pthread_mutex_unlock(&(info)->append_buffer_lock)
#else
#define lock_append_buffer(info)
#define unlock_append_buffer(info)
#endif #endif
static void init_read_function(IO_CACHE* info, enum cache_type type); static void
static void init_write_function(IO_CACHE* info, enum cache_type type); init_functions(IO_CACHE* info, enum cache_type type)
static void init_read_function(IO_CACHE* info, enum cache_type type)
{ {
switch (type) switch (type) {
{
#ifndef MYSQL_CLIENT
case READ_NET: case READ_NET:
/* must be initialized by the caller. The problem is that /* must be initialized by the caller. The problem is that
_my_b_net_read has to be defined in sql directory because of _my_b_net_read has to be defined in sql directory because of
...@@ -61,24 +81,25 @@ static void init_read_function(IO_CACHE* info, enum cache_type type) ...@@ -61,24 +81,25 @@ static void init_read_function(IO_CACHE* info, enum cache_type type)
as myisamchk as myisamchk
*/ */
break; break;
#endif
case SEQ_READ_APPEND: case SEQ_READ_APPEND:
info->read_function = _my_b_seq_read; info->read_function = _my_b_seq_read;
info->write_function = 0; /* Force a core if used */
break; break;
default: default:
info->read_function = _my_b_read; info->read_function = _my_b_read;
info->write_function = _my_b_write;
} }
}
static void init_write_function(IO_CACHE* info, enum cache_type type) /* Ensure that my_b_tell() and my_b_bytes_in_cache works */
{ if (type == WRITE_CACHE)
switch (type)
{ {
case SEQ_READ_APPEND: info->current_pos= &info->write_pos;
info->write_function = _my_b_append; info->current_end= &info->write_end;
break; }
default: else
info->write_function = _my_b_write; {
info->current_pos= &info->read_pos;
info->current_end= &info->read_end;
} }
} }
...@@ -93,62 +114,61 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, ...@@ -93,62 +114,61 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
pbool use_async_io, myf cache_myflags) pbool use_async_io, myf cache_myflags)
{ {
uint min_cache; uint min_cache;
my_off_t end_of_file= ~(my_off_t) 0;
DBUG_ENTER("init_io_cache"); DBUG_ENTER("init_io_cache");
DBUG_PRINT("enter",("type: %d pos: %ld",(int) type, (ulong) seek_offset)); DBUG_PRINT("enter",("type: %d pos: %ld",(int) type, (ulong) seek_offset));
/* There is no file in net_reading */
info->file= file; info->file= file;
info->type=type;
info->pos_in_file= seek_offset;
info->pre_close = info->pre_read = info->post_read = 0; info->pre_close = info->pre_read = info->post_read = 0;
info->arg = 0; info->arg = 0;
info->alloced_buffer = 0;
info->buffer=0;
info->seek_not_done= test(file >= 0);
if (!cachesize) if (!cachesize)
if (! (cachesize= my_default_record_cache_size)) if (! (cachesize= my_default_record_cache_size))
DBUG_RETURN(1); /* No cache requested */ DBUG_RETURN(1); /* No cache requested */
min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2; min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2;
info->alloced_buffer = 0;
if (type == READ_CACHE || type == SEQ_READ_APPEND) if (type == READ_CACHE || type == SEQ_READ_APPEND)
{ /* Assume file isn't growing */ { /* Assume file isn't growing */
if (cache_myflags & MY_DONT_CHECK_FILESIZE) if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
{ {
cache_myflags &= ~MY_DONT_CHECK_FILESIZE; /* Calculate end of file to not allocate to big buffers */
}
else
{
my_off_t file_pos,end_of_file;
if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR))
DBUG_RETURN(1);
end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0));
if (end_of_file < seek_offset) if (end_of_file < seek_offset)
end_of_file=seek_offset; end_of_file=seek_offset;
VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); /* Trim cache size if the file is very small */
/* Trim cache size if the file is very small. if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1)
However, we should not do this with SEQ_READ_APPEND cache
*/
if (type != SEQ_READ_APPEND &&
(my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1)
{ {
cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1;
use_async_io=0; /* No need to use async */ use_async_io=0; /* No need to use async */
} }
} }
} }
if ((int) type < (int) READ_NET) cache_myflags &= ~MY_DONT_CHECK_FILESIZE;
if (type != READ_NET && type != WRITE_NET)
{ {
uint buffer_block; /* Retry allocating memory in smaller blocks until we get one */
for (;;) for (;;)
{ {
buffer_block = cachesize=(uint) ((ulong) (cachesize + min_cache-1) & uint buffer_block;
cachesize=(uint) ((ulong) (cachesize + min_cache-1) &
(ulong) ~(min_cache-1)); (ulong) ~(min_cache-1));
if (type == SEQ_READ_APPEND)
buffer_block *= 2;
if (cachesize < min_cache) if (cachesize < min_cache)
cachesize = min_cache; cachesize = min_cache;
buffer_block = cachesize;
if (type == SEQ_READ_APPEND)
buffer_block *= 2;
if ((info->buffer= if ((info->buffer=
(byte*) my_malloc(buffer_block, (byte*) my_malloc(buffer_block,
MYF((cache_myflags & ~ MY_WME) | MYF((cache_myflags & ~ MY_WME) |
(cachesize == min_cache ? MY_WME : 0)))) != 0) (cachesize == min_cache ? MY_WME : 0)))) != 0)
{ {
info->write_buffer=info->buffer;
if (type == SEQ_READ_APPEND) if (type == SEQ_READ_APPEND)
info->append_buffer = info->buffer + cachesize; info->write_buffer = info->buffer + cachesize;
info->alloced_buffer=1; info->alloced_buffer=1;
break; /* Enough memory found */ break; /* Enough memory found */
} }
...@@ -157,45 +177,30 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, ...@@ -157,45 +177,30 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */ cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */
} }
} }
else
info->buffer=0;
DBUG_PRINT("info",("init_io_cache: cachesize = %u",cachesize)); DBUG_PRINT("info",("init_io_cache: cachesize = %u",cachesize));
info->pos_in_file= seek_offset;
info->read_length=info->buffer_length=cachesize; info->read_length=info->buffer_length=cachesize;
info->seek_not_done= test(file >= 0 && type != READ_FIFO &&
type != READ_NET);
info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP); info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
info->rc_request_pos=info->rc_pos= info->write_pos = info->buffer; info->request_pos= info->read_pos= info->write_pos = info->buffer;
info->write_pos = info->write_end = 0;
if (type == SEQ_READ_APPEND) if (type == SEQ_READ_APPEND)
{ {
info->append_read_pos = info->write_pos = info->append_buffer; info->append_read_pos = info->write_pos = info->write_buffer;
info->write_end = info->append_end = info->write_end = info->write_buffer + info->buffer_length;
info->append_buffer + info->buffer_length; #ifdef THREAD
#ifdef THREAD
pthread_mutex_init(&info->append_buffer_lock,MY_MUTEX_INIT_FAST); pthread_mutex_init(&info->append_buffer_lock,MY_MUTEX_INIT_FAST);
#endif #endif
} }
if (type == READ_CACHE || type == SEQ_READ_APPEND || if (type == WRITE_CACHE)
type == READ_NET || type == READ_FIFO)
{
info->rc_end=info->buffer; /* Nothing in cache */
}
else /* type == WRITE_CACHE */
{
info->write_end= info->write_end=
info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1)); info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1));
info->write_pos = info->buffer; else
} info->read_end=info->buffer; /* Nothing in cache */
/* end_of_file may be changed by user later */
info->end_of_file= ((type == READ_NET || type == READ_FIFO ) ? 0 /* End_of_file may be changed by user later */
: ~(my_off_t) 0); info->end_of_file= end_of_file;
info->type=type;
info->error=0; info->error=0;
init_read_function(info,type); init_functions(info,type);
init_write_function(info,type);
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
if (use_async_io && ! my_disable_async_io) if (use_async_io && ! my_disable_async_io)
{ {
...@@ -236,8 +241,13 @@ static void my_aiowait(my_aio_result *result) ...@@ -236,8 +241,13 @@ static void my_aiowait(my_aio_result *result)
} }
#endif #endif
/* Use this to reset cache to start or other type */
/* Some simple optimizing is done when reinit in current buffer */ /*
Use this to reset cache to re-start reading or to change the type
between READ_CACHE <-> WRITE_CACHE
If we are doing a reinit of a cache where we have the start of the file
in the cache, we are reusing this memory without flushing it to disk.
*/
my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
my_off_t seek_offset, my_off_t seek_offset,
...@@ -245,33 +255,37 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, ...@@ -245,33 +255,37 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
pbool clear_cache) pbool clear_cache)
{ {
DBUG_ENTER("reinit_io_cache"); DBUG_ENTER("reinit_io_cache");
DBUG_PRINT("enter",("type: %d seek_offset: %lu clear_cache: %d",
type, (ulong) seek_offset, (int) clear_cache));
info->seek_not_done= test(info->file >= 0); /* Seek not done */ /* One can't do reinit with the following types */
DBUG_ASSERT(type != READ_NET && info->type != READ_NET &&
type != WRITE_NET && info->type != WRITE_NET &&
type != SEQ_READ_APPEND && info->type != SEQ_READ_APPEND);
/* If the whole file is in memory, avoid flushing to disk */ /* If the whole file is in memory, avoid flushing to disk */
if (! clear_cache && if (! clear_cache &&
seek_offset >= info->pos_in_file && seek_offset >= info->pos_in_file &&
seek_offset <= info->pos_in_file + seek_offset <= my_b_tell(info))
(uint) (info->rc_end - info->rc_request_pos)) {
{ /* use current buffer */ /* Reuse current buffer without flushing it to disk */
byte *pos;
if (info->type == WRITE_CACHE && type == READ_CACHE) if (info->type == WRITE_CACHE && type == READ_CACHE)
{ {
info->rc_end=info->write_pos; info->read_end=info->write_pos;
info->end_of_file=my_b_tell(info); info->end_of_file=my_b_tell(info);
} }
else if (type == WRITE_CACHE) else if (type == WRITE_CACHE)
{ {
if (info->type == READ_CACHE) if (info->type == READ_CACHE)
{ info->write_end=info->write_buffer+info->buffer_length;
info->write_end=info->buffer+info->buffer_length;
info->write_pos=info->rc_pos;
}
info->end_of_file = ~(my_off_t) 0; info->end_of_file = ~(my_off_t) 0;
} }
pos=info->request_pos+(seek_offset-info->pos_in_file);
if (type == WRITE_CACHE) if (type == WRITE_CACHE)
info->write_pos=info->rc_request_pos+(seek_offset-info->pos_in_file); info->write_pos=pos;
else else
info->rc_pos=info->rc_request_pos+(seek_offset-info->pos_in_file); info->read_pos= pos;
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
my_aiowait(&info->aio_result); /* Wait for outstanding req */ my_aiowait(&info->aio_result); /* Wait for outstanding req */
#endif #endif
...@@ -284,50 +298,35 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, ...@@ -284,50 +298,35 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
*/ */
if (info->type == WRITE_CACHE && type == READ_CACHE) if (info->type == WRITE_CACHE && type == READ_CACHE)
info->end_of_file=my_b_tell(info); info->end_of_file=my_b_tell(info);
/* No need to flush cache if we want to reuse it */ /* flush cache if we want to reuse it */
if ((type != WRITE_CACHE || !clear_cache) && flush_io_cache(info)) if (!clear_cache && flush_io_cache(info))
DBUG_RETURN(1); DBUG_RETURN(1);
if (info->pos_in_file != seek_offset) info->pos_in_file=seek_offset;
{ /* Better to do always do a seek */
info->pos_in_file=seek_offset; info->seek_not_done=1;
info->seek_not_done=1; info->request_pos=info->read_pos=info->write_pos=info->buffer;
} if (type == READ_CACHE)
info->rc_request_pos=info->rc_pos=info->buffer;
if (type == READ_CACHE || type == READ_NET || type == READ_FIFO)
{ {
info->rc_end=info->buffer; /* Nothing in cache */ info->read_end=info->buffer; /* Nothing in cache */
} }
else else
{ {
info->rc_end=info->buffer+info->buffer_length- info->write_end=(info->buffer + info->buffer_length -
(seek_offset & (IO_SIZE-1)); (seek_offset & (IO_SIZE-1)));
info->end_of_file= ((type == READ_NET || type == READ_FIFO) ? 0 : info->end_of_file= ~(my_off_t) 0;
~(my_off_t) 0);
} }
} }
if (info->type == SEQ_READ_APPEND)
{
info->append_read_pos = info->write_pos = info->append_buffer;
}
if (!info->write_pos)
info->write_pos = info->buffer;
if (!info->write_end)
info->write_end = info->buffer+info->buffer_length-
(seek_offset & (IO_SIZE-1));
info->type=type; info->type=type;
info->error=0; info->error=0;
init_read_function(info,type); init_functions(info,type);
init_write_function(info,type);
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
if (type != READ_NET) if (use_async_io && ! my_disable_async_io &&
((ulong) info->buffer_length <
(ulong) (info->end_of_file - seek_offset)))
{ {
if (use_async_io && ! my_disable_async_io && info->read_length=info->buffer_length/2;
((ulong) info->buffer_length < info->read_function=_my_b_async_read;
(ulong) (info->end_of_file - seek_offset)))
{
info->read_length=info->buffer_length/2;
info->read_function=_my_b_async_read;
}
} }
info->inited=0; info->inited=0;
#endif #endif
...@@ -336,28 +335,30 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, ...@@ -336,28 +335,30 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
/* /*
Read buffered. Returns 1 if can't read requested characters Read buffered. Returns 1 if can't read requested characters
This function is only called from the my_b_read() macro This function is only called from the my_b_read() macro
when there isn't enough characters in the buffer to when there isn't enough characters in the buffer to
satisfy the request. satisfy the request.
Returns 0 we succeeded in reading all data Returns 0 we succeeded in reading all data
*/ */
int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
{ {
uint length,diff_length,left_length; uint length,diff_length,left_length;
my_off_t max_length, pos_in_file; my_off_t max_length, pos_in_file;
DBUG_ENTER("_my_b_read");
if ((left_length=(uint) (info->rc_end-info->rc_pos)))
if ((left_length=(uint) (info->read_end-info->read_pos)))
{ {
dbug_assert(Count >= left_length); /* User is not using my_b_read() */ DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */
memcpy(Buffer,info->rc_pos, (size_t) (left_length)); memcpy(Buffer,info->read_pos, (size_t) (left_length));
Buffer+=left_length; Buffer+=left_length;
Count-=left_length; Count-=left_length;
} }
/* pos_in_file always point on where info->buffer was read */ /* pos_in_file always point on where info->buffer was read */
pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer); pos_in_file=info->pos_in_file+(uint) (info->read_end - info->buffer);
if (info->seek_not_done) if (info->seek_not_done)
{ /* File touched, do seek */ { /* File touched, do seek */
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))); VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
...@@ -370,7 +371,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -370,7 +371,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
if (info->end_of_file == pos_in_file) if (info->end_of_file == pos_in_file)
{ /* End of file */ { /* End of file */
info->error=(int) left_length; info->error=(int) left_length;
return 1; DBUG_RETURN(1);
} }
length=(Count & (uint) ~(IO_SIZE-1))-diff_length; length=(Count & (uint) ~(IO_SIZE-1))-diff_length;
if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags)) if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags))
...@@ -378,7 +379,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -378,7 +379,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
{ {
info->error= read_length == (uint) -1 ? -1 : info->error= read_length == (uint) -1 ? -1 :
(int) (read_length+left_length); (int) (read_length+left_length);
return 1; DBUG_RETURN(1);
} }
Count-=length; Count-=length;
Buffer+=length; Buffer+=length;
...@@ -386,16 +387,17 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -386,16 +387,17 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
left_length+=length; left_length+=length;
diff_length=0; diff_length=0;
} }
max_length=info->read_length-diff_length; max_length=info->read_length-diff_length;
if (info->type != READ_FIFO && if (info->type != READ_FIFO &&
(info->end_of_file - pos_in_file) < max_length) max_length > (info->end_of_file - pos_in_file))
max_length = info->end_of_file - pos_in_file; max_length = info->end_of_file - pos_in_file;
if (!max_length) if (!max_length)
{ {
if (Count) if (Count)
{ {
info->error= left_length; /* We only got this many char */ info->error= left_length; /* We only got this many char */
return 1; DBUG_RETURN(1);
} }
length=0; /* Didn't read any chars */ length=0; /* Didn't read any chars */
} }
...@@ -406,20 +408,22 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -406,20 +408,22 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
if (length != (uint) -1) if (length != (uint) -1)
memcpy(Buffer,info->buffer,(size_t) length); memcpy(Buffer,info->buffer,(size_t) length);
info->error= length == (uint) -1 ? -1 : (int) (length+left_length); info->error= length == (uint) -1 ? -1 : (int) (length+left_length);
return 1; info->read_pos=info->read_end=info->buffer;
DBUG_RETURN(1);
} }
info->rc_pos=info->buffer+Count; info->read_pos=info->buffer+Count;
info->rc_end=info->buffer+length; info->read_end=info->buffer+length;
info->pos_in_file=pos_in_file; info->pos_in_file=pos_in_file;
memcpy(Buffer,info->buffer,(size_t) Count); memcpy(Buffer,info->buffer,(size_t) Count);
return 0; DBUG_RETURN(0);
} }
/* Do sequential read from the SEQ_READ_APPEND cache /*
we do this in three stages: Do sequential read from the SEQ_READ_APPEND cache
- first read from info->buffer we do this in three stages:
- then if there are still data to read, try the file descriptor - first read from info->buffer
- afterwards, if there are still data to read, try append buffer - then if there are still data to read, try the file descriptor
- afterwards, if there are still data to read, try append buffer
*/ */
int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
...@@ -427,97 +431,127 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -427,97 +431,127 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
uint length,diff_length,left_length,save_count; uint length,diff_length,left_length,save_count;
my_off_t max_length, pos_in_file; my_off_t max_length, pos_in_file;
save_count=Count; save_count=Count;
/* first, read the regular buffer */ /* first, read the regular buffer */
if ((left_length=(uint) (info->rc_end-info->rc_pos))) if ((left_length=(uint) (info->read_end-info->read_pos)))
{ {
dbug_assert(Count >= left_length); /* User is not using my_b_read() */ DBUG_ASSERT(Count > left_length); /* User is not using my_b_read() */
memcpy(Buffer,info->rc_pos, (size_t) (left_length)); memcpy(Buffer,info->read_pos, (size_t) (left_length));
Buffer+=left_length; Buffer+=left_length;
Count-=left_length; Count-=left_length;
} }
lock_append_buffer(info);
/* pos_in_file always point on where info->buffer was read */ /* pos_in_file always point on where info->buffer was read */
if ((pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer)) >= if ((pos_in_file=info->pos_in_file+(uint) (info->read_end - info->buffer)) >=
info->end_of_file) info->end_of_file)
{
info->pos_in_file=pos_in_file;
goto read_append_buffer; goto read_append_buffer;
if (info->seek_not_done)
{ /* File touched, do seek */
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
info->seek_not_done=0;
} }
/* no need to seek since the read is guaranteed to be sequential */
diff_length=(uint) (pos_in_file & (IO_SIZE-1)); diff_length=(uint) (pos_in_file & (IO_SIZE-1));
/* now the second stage begins - read from file descriptor */ /* now the second stage begins - read from file descriptor */
if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length))) if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length)))
{ /* Fill first intern buffer */ { /* Fill first intern buffer */
uint read_length; uint read_length;
if (info->end_of_file == pos_in_file)
{ /* End of file */
goto read_append_buffer;
}
length=(Count & (uint) ~(IO_SIZE-1))-diff_length; length=(Count & (uint) ~(IO_SIZE-1))-diff_length;
if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags)) if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags)) ==
!= (uint) length) (uint)-1)
{ {
if (read_length != (uint)-1) info->error= -1;
{ unlock_append_buffer(info);
Count -= read_length; return 1;
Buffer += read_length; }
} Count-=read_length;
Buffer+=read_length;
pos_in_file+=read_length;
if (read_length != (uint) length)
{
/*
We only got part of data; Read the rest of the data from the
write buffer
*/
goto read_append_buffer; goto read_append_buffer;
} }
Count-=length;
Buffer+=length;
pos_in_file+=length;
left_length+=length; left_length+=length;
diff_length=0; diff_length=0;
} }
max_length=info->read_length-diff_length; max_length=info->read_length-diff_length;
if ((info->end_of_file - pos_in_file) < max_length) if (max_length > (info->end_of_file - pos_in_file))
max_length = info->end_of_file - pos_in_file; max_length = info->end_of_file - pos_in_file;
if (!max_length) if (!max_length)
{ {
if (Count) if (Count)
{
goto read_append_buffer; goto read_append_buffer;
} length=0; /* Didn't read any more chars */
length=0; /* Didn't read any chars */
} }
else if ((length=my_read(info->file,info->buffer,(uint) max_length, else
info->myflags)) < Count ||
length == (uint) -1)
{ {
if (length != (uint) -1) length=my_read(info->file,info->buffer,(uint) max_length,
info->myflags);
if (length == (uint) -1)
{
info->error= -1;
unlock_append_buffer(info);
return 1;
}
if (length < Count)
{ {
memcpy(Buffer,info->buffer,(size_t) length); memcpy(Buffer,info->buffer,(size_t) length);
Count -= length; Count -= length;
Buffer += length; Buffer += length;
goto read_append_buffer;
} }
goto read_append_buffer;
} }
info->rc_pos=info->buffer+Count; unlock_append_buffer(info);
info->rc_end=info->buffer+length; info->read_pos=info->buffer+Count;
info->read_end=info->buffer+length;
info->pos_in_file=pos_in_file; info->pos_in_file=pos_in_file;
memcpy(Buffer,info->buffer,(size_t) Count); memcpy(Buffer,info->buffer,(size_t) Count);
return 0; return 0;
read_append_buffer: read_append_buffer:
lock_append_buffer(info);
if (!Count) return 0; /*
Read data from the current write buffer.
Count should never be == 0 here (The code will work even if count is 0)
*/
{ {
uint copy_len = (uint)(info->append_read_pos - /* First copy the data to Count */
info->write_pos); uint len_in_buff = (uint) (info->write_pos - info->append_read_pos);
dbug_assert(info->append_read_pos <= info->write_pos); uint copy_len;
if (copy_len > Count)
copy_len = Count; DBUG_ASSERT(info->append_read_pos <= info->write_pos);
memcpy(Buffer, info->append_read_pos, DBUG_ASSERT(pos_in_file == info->end_of_file);
copy_len);
copy_len=min(Count, len_in_buff);
memcpy(Buffer, info->append_read_pos, copy_len);
info->append_read_pos += copy_len; info->append_read_pos += copy_len;
Count -= copy_len; Count -= copy_len;
if (Count) if (Count)
info->error = save_count - Count; info->error = save_count - Count;
/* Fill read buffer with data from write buffer */
memcpy(info->buffer, info->append_read_pos,
(size_t) (len_in_buff - copy_len));
info->read_pos= info->buffer;
info->read_end= info->buffer+(len_in_buff - copy_len);
info->append_read_pos=info->write_pos;
info->pos_in_file+=len_in_buff;
} }
unlock_append_buffer(info); unlock_append_buffer(info);
return Count ? 1 : 0; return Count ? 1 : 0;
} }
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
...@@ -527,8 +561,8 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -527,8 +561,8 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
my_off_t next_pos_in_file; my_off_t next_pos_in_file;
byte *read_buffer; byte *read_buffer;
memcpy(Buffer,info->rc_pos, memcpy(Buffer,info->read_pos,
(size_t) (left_length=(uint) (info->rc_end-info->rc_pos))); (size_t) (left_length=(uint) (info->read_end-info->read_pos)));
Buffer+=left_length; Buffer+=left_length;
org_Count=Count; org_Count=Count;
Count-=left_length; Count-=left_length;
...@@ -555,13 +589,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -555,13 +589,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
(int) (read_length+left_length)); (int) (read_length+left_length));
return(1); return(1);
} }
info->pos_in_file+=(uint) (info->rc_end - info->rc_request_pos); info->pos_in_file+=(uint) (info->read_end - info->request_pos);
if (info->rc_request_pos != info->buffer) if (info->request_pos != info->buffer)
info->rc_request_pos=info->buffer; info->request_pos=info->buffer;
else else
info->rc_request_pos=info->buffer+info->read_length; info->request_pos=info->buffer+info->read_length;
info->rc_pos=info->rc_request_pos; info->read_pos=info->request_pos;
next_pos_in_file=info->aio_read_pos+read_length; next_pos_in_file=info->aio_read_pos+read_length;
/* Check if pos_in_file is changed /* Check if pos_in_file is changed
...@@ -578,8 +612,8 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -578,8 +612,8 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
{ {
my_off_t offset= (info->pos_in_file - info->aio_read_pos); my_off_t offset= (info->pos_in_file - info->aio_read_pos);
info->pos_in_file=info->aio_read_pos; /* Whe are here */ info->pos_in_file=info->aio_read_pos; /* Whe are here */
info->rc_pos=info->rc_request_pos+offset; info->read_pos=info->request_pos+offset;
read_length-=offset; /* Bytes left from rc_pos */ read_length-=offset; /* Bytes left from read_pos */
} }
} }
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -591,16 +625,16 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -591,16 +625,16 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
#endif #endif
/* Copy found bytes to buffer */ /* Copy found bytes to buffer */
length=min(Count,read_length); length=min(Count,read_length);
memcpy(Buffer,info->rc_pos,(size_t) length); memcpy(Buffer,info->read_pos,(size_t) length);
Buffer+=length; Buffer+=length;
Count-=length; Count-=length;
left_length+=length; left_length+=length;
info->rc_end=info->rc_pos+read_length; info->read_end=info->rc_pos+read_length;
info->rc_pos+=length; info->read_pos+=length;
} }
else else
next_pos_in_file=(info->pos_in_file+ (uint) next_pos_in_file=(info->pos_in_file+ (uint)
(info->rc_end - info->rc_request_pos)); (info->read_end - info->request_pos));
/* If reading large blocks, or first read or read with skipp */ /* If reading large blocks, or first read or read with skipp */
if (Count) if (Count)
...@@ -614,13 +648,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -614,13 +648,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
read_length=IO_SIZE*2- (uint) (next_pos_in_file & (IO_SIZE-1)); read_length=IO_SIZE*2- (uint) (next_pos_in_file & (IO_SIZE-1));
if (Count < read_length) if (Count < read_length)
{ /* Small block, read to cache */ { /* Small block, read to cache */
if ((read_length=my_read(info->file,info->rc_request_pos, if ((read_length=my_read(info->file,info->request_pos,
read_length, info->myflags)) == (uint) -1) read_length, info->myflags)) == (uint) -1)
return info->error= -1; return info->error= -1;
use_length=min(Count,read_length); use_length=min(Count,read_length);
memcpy(Buffer,info->rc_request_pos,(size_t) use_length); memcpy(Buffer,info->request_pos,(size_t) use_length);
info->rc_pos=info->rc_request_pos+Count; info->read_pos=info->request_pos+Count;
info->rc_end=info->rc_request_pos+read_length; info->read_end=info->request_pos+read_length;
info->pos_in_file=next_pos_in_file; /* Start of block in cache */ info->pos_in_file=next_pos_in_file; /* Start of block in cache */
next_pos_in_file+=read_length; next_pos_in_file+=read_length;
...@@ -641,7 +675,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -641,7 +675,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
info->error= read_length == (uint) -1 ? -1 : read_length+left_length; info->error= read_length == (uint) -1 ? -1 : read_length+left_length;
return 1; return 1;
} }
info->rc_pos=info->rc_end=info->rc_request_pos; info->read_pos=info->read_end=info->request_pos;
info->pos_in_file=(next_pos_in_file+=Count); info->pos_in_file=(next_pos_in_file+=Count);
} }
} }
...@@ -652,7 +686,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -652,7 +686,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
if (max_length > (my_off_t) info->read_length - diff_length) if (max_length > (my_off_t) info->read_length - diff_length)
max_length= (my_off_t) info->read_length - diff_length; max_length= (my_off_t) info->read_length - diff_length;
if (info->rc_request_pos != info->buffer) if (info->request_pos != info->buffer)
read_buffer=info->buffer; read_buffer=info->buffer;
else else
read_buffer=info->buffer+info->read_length; read_buffer=info->buffer+info->read_length;
...@@ -669,13 +703,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) ...@@ -669,13 +703,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
my_errno=errno; my_errno=errno;
DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped", DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped",
errno, info->aio_result.result.aio_errno)); errno, info->aio_result.result.aio_errno));
if (info->rc_request_pos != info->buffer) if (info->request_pos != info->buffer)
{ {
bmove(info->buffer,info->rc_request_pos, bmove(info->buffer,info->request_pos,
(uint) (info->rc_end - info->rc_pos)); (uint) (info->read_end - info->read_pos));
info->rc_request_pos=info->buffer; info->request_pos=info->buffer;
info->rc_pos-=info->read_length; info->read_pos-=info->read_length;
info->rc_end-=info->read_length; info->read_end-=info->read_length;
} }
info->read_length=info->buffer_length; /* Use hole buffer */ info->read_length=info->buffer_length; /* Use hole buffer */
info->read_function=_my_b_read; /* Use normal IO_READ next */ info->read_function=_my_b_read; /* Use normal IO_READ next */
...@@ -709,16 +743,17 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) ...@@ -709,16 +743,17 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
{ {
uint rest_length,length; uint rest_length,length;
if (info->pos_in_file+info->buffer_length > info->end_of_file)
{
my_errno=errno=EFBIG;
return info->error = -1;
}
rest_length=(uint) (info->write_end - info->write_pos); rest_length=(uint) (info->write_end - info->write_pos);
memcpy(info->write_pos,Buffer,(size_t) rest_length); memcpy(info->write_pos,Buffer,(size_t) rest_length);
Buffer+=rest_length; Buffer+=rest_length;
Count-=rest_length; Count-=rest_length;
info->write_pos+=rest_length; info->write_pos+=rest_length;
if (info->pos_in_file+info->buffer_length > info->end_of_file)
{
my_errno=errno=EFBIG;
return info->error = -1;
}
if (flush_io_cache(info)) if (flush_io_cache(info))
return 1; return 1;
if (Count >= IO_SIZE) if (Count >= IO_SIZE)
...@@ -740,12 +775,21 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) ...@@ -740,12 +775,21 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
return 0; return 0;
} }
int _my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count)
/*
Append a block to the write buffer.
This is done with the buffer locked to ensure that we don't read from
the write buffer before we are ready with it.
*/
int my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count)
{ {
uint rest_length,length; uint rest_length,length;
rest_length=(uint) (info->append_end - lock_append_buffer(info);
info->write_pos); rest_length=(uint) (info->write_end - info->write_pos);
if (Count <= rest_length)
goto end;
memcpy(info->write_pos,Buffer,(size_t) rest_length); memcpy(info->write_pos,Buffer,(size_t) rest_length);
Buffer+=rest_length; Buffer+=rest_length;
Count-=rest_length; Count-=rest_length;
...@@ -760,8 +804,11 @@ int _my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count) ...@@ -760,8 +804,11 @@ int _my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count)
Count-=length; Count-=length;
Buffer+=length; Buffer+=length;
} }
end:
memcpy(info->write_pos,Buffer,(size_t) Count); memcpy(info->write_pos,Buffer,(size_t) Count);
info->write_pos+=Count; info->write_pos+=Count;
unlock_append_buffer(info);
return 0; return 0;
} }
...@@ -791,10 +838,13 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, ...@@ -791,10 +838,13 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
Buffer+=length; Buffer+=length;
pos+= length; pos+= length;
Count-= length; Count-= length;
#ifndef HAVE_PREAD
info->seek_not_done=1;
#endif
} }
/* Check if we want to write inside the used part of the buffer.*/ /* Check if we want to write inside the used part of the buffer.*/
length= (uint) (info->rc_end - info->buffer); length= (uint) (info->write_end - info->buffer);
if (pos < info->pos_in_file + length) if (pos < info->pos_in_file + length)
{ {
uint offset= (uint) (pos - info->pos_in_file); uint offset= (uint) (pos - info->pos_in_file);
...@@ -816,20 +866,16 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, ...@@ -816,20 +866,16 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
return error; return error;
} }
/* avoid warning about empty if body */
#ifdef THREAD
#define IF_APPEND_CACHE if (append_cache)
#else
#define IF_APPEND_CACHE
#endif
/* Flush write cache */ /* Flush write cache */
int flush_io_cache(IO_CACHE *info) int flush_io_cache(IO_CACHE *info)
{ {
uint length; uint length;
int append_cache; my_bool append_cache;
my_off_t pos_in_file;
DBUG_ENTER("flush_io_cache"); DBUG_ENTER("flush_io_cache");
append_cache = (info->type == SEQ_READ_APPEND); append_cache = (info->type == SEQ_READ_APPEND);
if (info->type == WRITE_CACHE || append_cache) if (info->type == WRITE_CACHE || append_cache)
{ {
...@@ -838,44 +884,45 @@ int flush_io_cache(IO_CACHE *info) ...@@ -838,44 +884,45 @@ int flush_io_cache(IO_CACHE *info)
if (real_open_cached_file(info)) if (real_open_cached_file(info))
DBUG_RETURN((info->error= -1)); DBUG_RETURN((info->error= -1));
} }
IF_APPEND_CACHE if ((length=(uint) (info->write_pos - info->write_buffer)))
lock_append_buffer(info);
if (info->write_pos != info->buffer)
{ {
length=(uint) (info->write_pos - info->buffer); pos_in_file=info->pos_in_file;
if (append_cache)
{
pos_in_file=info->end_of_file;
info->seek_not_done=1;
}
if (info->seek_not_done) if (info->seek_not_done)
{ /* File touched, do seek */ { /* File touched, do seek */
if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)) == if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) ==
MY_FILEPOS_ERROR) MY_FILEPOS_ERROR)
{ {
IF_APPEND_CACHE
unlock_append_buffer(info);
DBUG_RETURN((info->error= -1)); DBUG_RETURN((info->error= -1));
} }
info->seek_not_done=0; if (!append_cache)
} info->seek_not_done=0;
info->write_pos=info->buffer;
info->pos_in_file+=length;
info->write_end=(info->buffer+info->buffer_length-
(info->pos_in_file & (IO_SIZE-1)));
if (append_cache)
{
info->append_read_pos = info->buffer;
info->append_end = info->write_end;
} }
if (my_write(info->file,info->buffer,length,info->myflags | MY_NABP)) info->write_pos= info->write_buffer;
info->error= -1; if (!append_cache)
info->pos_in_file+=length;
info->write_end= (info->write_buffer+info->buffer_length-
((pos_in_file+length) & (IO_SIZE-1)));
/* Set this to be used if we are using SEQ_READ_APPEND */
info->append_read_pos = info->write_buffer;
if (my_write(info->file,info->write_buffer,length,
info->myflags | MY_NABP))
info->error= -1;
else else
info->error= 0; info->error= 0;
IF_APPEND_CACHE set_if_bigger(info->end_of_file,(pos_in_file+length));
unlock_append_buffer(info);
DBUG_RETURN(info->error); DBUG_RETURN(info->error);
} }
} }
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
else if (info->type != READ_NET) else if (info->type != READ_NET)
{ {
my_aiowait(&info->aio_result); /* Wait for outstanding req */ my_aiowait(&info->aio_result); /* Wait for outstanding req */
info->inited=0; info->inited=0;
} }
#endif #endif
...@@ -888,7 +935,8 @@ int end_io_cache(IO_CACHE *info) ...@@ -888,7 +935,8 @@ int end_io_cache(IO_CACHE *info)
int error=0; int error=0;
IO_CACHE_CALLBACK pre_close; IO_CACHE_CALLBACK pre_close;
DBUG_ENTER("end_io_cache"); DBUG_ENTER("end_io_cache");
if((pre_close=info->pre_close))
if ((pre_close=info->pre_close))
(*pre_close)(info); (*pre_close)(info);
if (info->alloced_buffer) if (info->alloced_buffer)
{ {
...@@ -896,13 +944,28 @@ int end_io_cache(IO_CACHE *info) ...@@ -896,13 +944,28 @@ int end_io_cache(IO_CACHE *info)
if (info->file != -1) /* File doesn't exist */ if (info->file != -1) /* File doesn't exist */
error=flush_io_cache(info); error=flush_io_cache(info);
my_free((gptr) info->buffer,MYF(MY_WME)); my_free((gptr) info->buffer,MYF(MY_WME));
info->buffer=info->rc_pos=(byte*) 0; info->buffer=info->read_pos=(byte*) 0;
info->alloced_buffer = 0; }
if (info->type == SEQ_READ_APPEND)
{
/* Destroy allocated mutex */
info->type=0;
#ifdef THREAD
pthread_mutex_destroy(&info->append_buffer_lock);
#endif
} }
DBUG_RETURN(error); DBUG_RETURN(error);
} /* end_io_cache */ } /* end_io_cache */
/**********************************************************************
Testing of MF_IOCACHE
**********************************************************************/
#ifdef MAIN #ifdef MAIN
#include <my_dir.h>
void die(const char* fmt, ...) void die(const char* fmt, ...)
{ {
va_list va_args; va_list va_args;
...@@ -916,7 +979,7 @@ void die(const char* fmt, ...) ...@@ -916,7 +979,7 @@ void die(const char* fmt, ...)
int open_file(const char* fname, IO_CACHE* info, int cache_size) int open_file(const char* fname, IO_CACHE* info, int cache_size)
{ {
int fd; int fd;
if ((fd=my_open(fname,O_CREAT|O_APPEND|O_RDWR,MYF(MY_WME))) < 0) if ((fd=my_open(fname,O_CREAT | O_RDWR,MYF(MY_WME))) < 0)
die("Could not open %s", fname); die("Could not open %s", fname);
if (init_io_cache(info, fd, cache_size, SEQ_READ_APPEND, 0,0,MYF(MY_WME))) if (init_io_cache(info, fd, cache_size, SEQ_READ_APPEND, 0,0,MYF(MY_WME)))
die("failed in init_io_cache()"); die("failed in init_io_cache()");
...@@ -960,8 +1023,8 @@ int main(int argc, char** argv) ...@@ -960,8 +1023,8 @@ int main(int argc, char** argv)
char buf[4]; char buf[4];
int block_size = abs(rand() % max_block); int block_size = abs(rand() % max_block);
int4store(buf, block_size); int4store(buf, block_size);
if (my_b_write(&sra_cache,buf,4) || if (my_b_append(&sra_cache,buf,4) ||
my_b_write(&sra_cache, block, block_size)) my_b_append(&sra_cache, block, block_size))
die("write failed"); die("write failed");
total_bytes += 4+block_size; total_bytes += 4+block_size;
} }
...@@ -985,6 +1048,3 @@ supposedly written\n"); ...@@ -985,6 +1048,3 @@ supposedly written\n");
return 0; return 0;
} }
#endif #endif
...@@ -26,22 +26,42 @@ ...@@ -26,22 +26,42 @@
#include <m_ctype.h> #include <m_ctype.h>
/* /*
** Fix that next read will be made at certain position Fix that next read will be made at certain position
** For write cache, make next write happen at a certain position For write cache, make next write happen at a certain position
*/ */
void my_b_seek(IO_CACHE *info,my_off_t pos) void my_b_seek(IO_CACHE *info,my_off_t pos)
{ {
DBUG_ENTER("my_b_seek");
DBUG_PRINT("enter",("pos: %lu", (ulong) pos));
if (info->type == READ_CACHE) if (info->type == READ_CACHE)
{ {
info->rc_pos=info->rc_end=info->buffer; byte* try_pos=info->read_pos + (pos - info->pos_in_file);
if (try_pos >= info->buffer &&
try_pos <= info->read_end)
{
/* The position is in the current buffer; Reuse it */
info->read_pos = try_pos;
DBUG_VOID_RETURN;
}
else
{
/* Force a new read on next my_b_read */
info->read_pos=info->read_end=info->buffer;
}
} }
else if (info->type == WRITE_CACHE) else if (info->type == WRITE_CACHE)
{ {
byte* try_write_pos; byte* try_pos;
try_write_pos = info->write_pos + (pos - info->pos_in_file); /* If write is in current buffer, reuse it */
if (try_write_pos >= info->buffer && try_write_pos <= info->write_end) try_pos = info->write_pos + (pos - info->pos_in_file);
info->write_pos = try_write_pos; if (try_pos >= info->write_buffer &&
try_pos <= info->write_end)
{
info->write_pos = try_pos;
DBUG_VOID_RETURN;
}
else else
flush_io_cache(info); flush_io_cache(info);
} }
...@@ -51,14 +71,15 @@ void my_b_seek(IO_CACHE *info,my_off_t pos) ...@@ -51,14 +71,15 @@ void my_b_seek(IO_CACHE *info,my_off_t pos)
/* /*
** Fill buffer. Note that this assumes that you have already used ** Fill buffer. Note that this assumes that you have already used
** all characters in the CACHE, independent of the rc_pos value! ** all characters in the CACHE, independent of the read_pos value!
** return: 0 on error or EOF (info->error = -1 on error) ** return: 0 on error or EOF (info->error = -1 on error)
** number of characters ** number of characters
*/ */
uint my_b_fill(IO_CACHE *info) uint my_b_fill(IO_CACHE *info)
{ {
my_off_t pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer); my_off_t pos_in_file=(info->pos_in_file+
(uint) (info->read_end - info->buffer));
my_off_t max_length; my_off_t max_length;
uint diff_length,length; uint diff_length,length;
if (info->seek_not_done) if (info->seek_not_done)
...@@ -86,8 +107,8 @@ uint my_b_fill(IO_CACHE *info) ...@@ -86,8 +107,8 @@ uint my_b_fill(IO_CACHE *info)
info->error= -1; info->error= -1;
return 0; return 0;
} }
info->rc_pos=info->buffer; info->read_pos=info->buffer;
info->rc_end=info->buffer+length; info->read_end=info->buffer+length;
info->pos_in_file=pos_in_file; info->pos_in_file=pos_in_file;
return length; return length;
} }
...@@ -113,11 +134,11 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length) ...@@ -113,11 +134,11 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
char *pos,*end; char *pos,*end;
if (length > max_length) if (length > max_length)
length=max_length; length=max_length;
for (pos=info->rc_pos,end=pos+length ; pos < end ;) for (pos=info->read_pos,end=pos+length ; pos < end ;)
{ {
if ((*to++ = *pos++) == '\n') if ((*to++ = *pos++) == '\n')
{ {
info->rc_pos=pos; info->read_pos=pos;
*to='\0'; *to='\0';
return (uint) (to-start); return (uint) (to-start);
} }
...@@ -125,7 +146,7 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length) ...@@ -125,7 +146,7 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
if (!(max_length-=length)) if (!(max_length-=length))
{ {
/* Found enough charcters; Return found string */ /* Found enough charcters; Return found string */
info->rc_pos=pos; info->read_pos=pos;
*to='\0'; *to='\0';
return (uint) (to-start); return (uint) (to-start);
} }
......
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
#include <my_global.h> #include <my_global.h>
#include <my_sys.h> #include <my_sys.h>
#include <m_string.h> #include <m_string.h>
#undef EXTRA_DEBUG
#define EXTRA_DEBUG #define EXTRA_DEBUG
void init_alloc_root(MEM_ROOT *mem_root, uint block_size, uint pre_alloc_size) void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused)))
{ {
mem_root->free=mem_root->used=0; mem_root->free=mem_root->used=0;
mem_root->min_malloc=32; mem_root->min_malloc=32;
......
...@@ -32,7 +32,7 @@ my_bool bitmap_init(MY_BITMAP *map, uint bitmap_size) ...@@ -32,7 +32,7 @@ my_bool bitmap_init(MY_BITMAP *map, uint bitmap_size)
if (!(map->bitmap=(uchar*) my_malloc((bitmap_size+7)/8, if (!(map->bitmap=(uchar*) my_malloc((bitmap_size+7)/8,
MYF(MY_WME | MY_ZEROFILL)))) MYF(MY_WME | MY_ZEROFILL))))
return 1; return 1;
dbug_assert(bitmap_size != ~(uint) 0); DBUG_ASSERT(bitmap_size != ~(uint) 0);
#ifdef THREAD #ifdef THREAD
pthread_mutex_init(&map->mutex, MY_MUTEX_INIT_FAST); pthread_mutex_init(&map->mutex, MY_MUTEX_INIT_FAST);
#endif #endif
......
...@@ -424,7 +424,7 @@ struct hostent *my_gethostbyname_r(const char *name, ...@@ -424,7 +424,7 @@ struct hostent *my_gethostbyname_r(const char *name,
int buflen, int *h_errnop) int buflen, int *h_errnop)
{ {
struct hostent *hp; struct hostent *hp;
dbug_assert((size_t) buflen >= sizeof(*result)); DBUG_ASSERT((size_t) buflen >= sizeof(*result));
if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop)) if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop))
return 0; return 0;
return hp; return hp;
...@@ -436,7 +436,7 @@ struct hostent *my_gethostbyname_r(const char *name, ...@@ -436,7 +436,7 @@ struct hostent *my_gethostbyname_r(const char *name,
struct hostent *result, char *buffer, struct hostent *result, char *buffer,
int buflen, int *h_errnop) int buflen, int *h_errnop)
{ {
dbug_assert(buflen >= sizeof(struct hostent_data)); DBUG_ASSERT(buflen >= sizeof(struct hostent_data));
if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1) if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1)
{ {
*h_errnop= errno; *h_errnop= errno;
...@@ -452,7 +452,7 @@ struct hostent *my_gethostbyname_r(const char *name, ...@@ -452,7 +452,7 @@ struct hostent *my_gethostbyname_r(const char *name,
int buflen, int *h_errnop) int buflen, int *h_errnop)
{ {
struct hostent *hp; struct hostent *hp;
dbug_assert(buflen >= sizeof(struct hostent_data)); DBUG_ASSERT(buflen >= sizeof(struct hostent_data));
hp= gethostbyname_r(name,result,(struct hostent_data *) buffer); hp= gethostbyname_r(name,result,(struct hostent_data *) buffer);
*h_errnop= errno; *h_errnop= errno;
return hp; return hp;
......
...@@ -26,7 +26,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, ...@@ -26,7 +26,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
reg1 os_off_t newpos; reg1 os_off_t newpos;
DBUG_ENTER("my_seek"); DBUG_ENTER("my_seek");
DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d", DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d",
fd, ((ulonglong) pos) >> 32, (ulong) pos, whence, MyFlags)); fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos,
whence, MyFlags));
newpos=lseek(fd, pos, whence); newpos=lseek(fd, pos, whence);
if (newpos == (os_off_t) -1) if (newpos == (os_off_t) -1)
{ {
...@@ -34,6 +35,10 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, ...@@ -34,6 +35,10 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
DBUG_PRINT("error",("lseek: %lu, errno: %d",newpos,errno)); DBUG_PRINT("error",("lseek: %lu, errno: %d",newpos,errno));
DBUG_RETURN(MY_FILEPOS_ERROR); DBUG_RETURN(MY_FILEPOS_ERROR);
} }
if (newpos != pos)
{
DBUG_PRINT("exit",("pos: %lu", (ulong) newpos));
}
DBUG_RETURN((my_off_t) newpos); DBUG_RETURN((my_off_t) newpos);
} /* my_seek */ } /* my_seek */
...@@ -53,6 +58,6 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused))) ...@@ -53,6 +58,6 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused)))
#endif #endif
if (pos == (os_off_t) -1) if (pos == (os_off_t) -1)
my_errno=errno; my_errno=errno;
DBUG_PRINT("exit",("pos: %lu",pos)); DBUG_PRINT("exit",("pos: %lu", (ulong) pos));
DBUG_RETURN((my_off_t) pos); DBUG_RETURN((my_off_t) pos);
} /* my_tell */ } /* my_tell */
...@@ -1045,7 +1045,7 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map changed_keys, ...@@ -1045,7 +1045,7 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map changed_keys,
} }
err: err:
dbug_assert(error != DB_KEYEXIST); DBUG_ASSERT(error != DB_KEYEXIST);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -1187,7 +1187,7 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record, ...@@ -1187,7 +1187,7 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record,
((table->key_info[keynr].flags & (HA_NOSAME | HA_NULL_PART_KEY)) == ((table->key_info[keynr].flags & (HA_NOSAME | HA_NULL_PART_KEY)) ==
HA_NOSAME)) HA_NOSAME))
{ // Unique key { // Unique key
dbug_assert(keynr == primary_key || prim_key->data != key_buff2); DBUG_ASSERT(keynr == primary_key || prim_key->data != key_buff2);
error=key_file[keynr]->del(key_file[keynr], trans, error=key_file[keynr]->del(key_file[keynr], trans,
keynr == primary_key ? keynr == primary_key ?
prim_key : prim_key :
...@@ -1201,7 +1201,7 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record, ...@@ -1201,7 +1201,7 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record,
row to find the key to be delete and delete it. row to find the key to be delete and delete it.
We will never come here with keynr = primary_key We will never come here with keynr = primary_key
*/ */
dbug_assert(keynr != primary_key && prim_key->data != key_buff2); DBUG_ASSERT(keynr != primary_key && prim_key->data != key_buff2);
DBC *tmp_cursor; DBC *tmp_cursor;
if (!(error=key_file[keynr]->cursor(key_file[keynr], trans, if (!(error=key_file[keynr]->cursor(key_file[keynr], trans,
&tmp_cursor, 0))) &tmp_cursor, 0)))
......
...@@ -196,7 +196,7 @@ convert_error_code_to_mysql( ...@@ -196,7 +196,7 @@ convert_error_code_to_mysql(
return(HA_ERR_TO_BIG_ROW); return(HA_ERR_TO_BIG_ROW);
} else { } else {
dbug_assert(0); DBUG_ASSERT(0);
return(-1); // Unknown error return(-1); // Unknown error
} }
...@@ -259,7 +259,7 @@ check_trx_exists( ...@@ -259,7 +259,7 @@ check_trx_exists(
trx = (trx_t*) thd->transaction.all.innobase_tid; trx = (trx_t*) thd->transaction.all.innobase_tid;
if (trx == NULL) { if (trx == NULL) {
dbug_assert(thd != NULL); DBUG_ASSERT(thd != NULL);
trx = trx_allocate_for_mysql(); trx = trx_allocate_for_mysql();
trx->mysql_thd = thd; trx->mysql_thd = thd;
...@@ -852,7 +852,7 @@ normalize_table_name( ...@@ -852,7 +852,7 @@ normalize_table_name(
name_ptr = ptr + 1; name_ptr = ptr + 1;
dbug_assert(ptr > name); DBUG_ASSERT(ptr > name);
ptr--; ptr--;
...@@ -975,7 +975,7 @@ ha_innobase::open( ...@@ -975,7 +975,7 @@ ha_innobase::open(
ref_length = DATA_ROW_ID_LEN + 10; ref_length = DATA_ROW_ID_LEN + 10;
dbug_assert(key_used_on_scan == MAX_KEY); DBUG_ASSERT(key_used_on_scan == MAX_KEY);
} }
auto_inc_counter_for_this_stat = 0; auto_inc_counter_for_this_stat = 0;
...@@ -1119,8 +1119,8 @@ innobase_mysql_cmp( ...@@ -1119,8 +1119,8 @@ innobase_mysql_cmp(
enum_field_types mysql_tp; enum_field_types mysql_tp;
int ret; int ret;
dbug_assert(a_length != UNIV_SQL_NULL); DBUG_ASSERT(a_length != UNIV_SQL_NULL);
dbug_assert(b_length != UNIV_SQL_NULL); DBUG_ASSERT(b_length != UNIV_SQL_NULL);
mysql_tp = (enum_field_types) mysql_type; mysql_tp = (enum_field_types) mysql_type;
...@@ -1158,11 +1158,11 @@ get_innobase_type_from_mysql_type( ...@@ -1158,11 +1158,11 @@ get_innobase_type_from_mysql_type(
8 bits: this is used in ibuf and also when DATA_NOT_NULL is 8 bits: this is used in ibuf and also when DATA_NOT_NULL is
ORed to the type */ ORed to the type */
dbug_assert((ulint)FIELD_TYPE_STRING < 256); DBUG_ASSERT((ulint)FIELD_TYPE_STRING < 256);
dbug_assert((ulint)FIELD_TYPE_VAR_STRING < 256); DBUG_ASSERT((ulint)FIELD_TYPE_VAR_STRING < 256);
dbug_assert((ulint)FIELD_TYPE_DOUBLE < 256); DBUG_ASSERT((ulint)FIELD_TYPE_DOUBLE < 256);
dbug_assert((ulint)FIELD_TYPE_FLOAT < 256); DBUG_ASSERT((ulint)FIELD_TYPE_FLOAT < 256);
dbug_assert((ulint)FIELD_TYPE_DECIMAL < 256); DBUG_ASSERT((ulint)FIELD_TYPE_DECIMAL < 256);
switch (field->type()) { switch (field->type()) {
case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) { case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) {
...@@ -2368,7 +2368,7 @@ ha_innobase::position( ...@@ -2368,7 +2368,7 @@ ha_innobase::position(
len = store_key_val_for_row(primary_key, (char*) ref, record); len = store_key_val_for_row(primary_key, (char*) ref, record);
} }
dbug_assert(len <= ref_length); DBUG_ASSERT(len <= ref_length);
ref_stored_len = len; ref_stored_len = len;
} }
......
...@@ -774,13 +774,13 @@ bool MYSQL_LOG::write(IO_CACHE *cache) ...@@ -774,13 +774,13 @@ bool MYSQL_LOG::write(IO_CACHE *cache)
length=my_b_bytes_in_cache(cache); length=my_b_bytes_in_cache(cache);
do do
{ {
if (my_b_write(&log_file, cache->rc_pos, length)) if (my_b_write(&log_file, cache->read_pos, length))
{ {
if (!write_error) if (!write_error)
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
goto err; goto err;
} }
cache->rc_pos=cache->rc_end; // Mark buffer used up cache->read_pos=cache->read_end; // Mark buffer used up
} while ((length=my_b_fill(cache))); } while ((length=my_b_fill(cache)));
if (flush_io_cache(&log_file)) if (flush_io_cache(&log_file))
{ {
......
...@@ -52,26 +52,32 @@ int _my_b_net_read(register IO_CACHE *info, byte *Buffer, ...@@ -52,26 +52,32 @@ int _my_b_net_read(register IO_CACHE *info, byte *Buffer,
{ {
int read_length; int read_length;
NET *net= &(current_thd)->net; NET *net= &(current_thd)->net;
DBUG_ENTER("_my_b_net_read");
if (info->end_of_file) if (!info->end_of_file)
return 1; /* because my_b_get (no _) takes 1 byte at a time */ DBUG_RETURN(1); /* because my_b_get (no _) takes 1 byte at a time */
read_length=my_net_read(net); read_length=my_net_read(net);
if (read_length == (int) packet_error) if (read_length == (int) packet_error)
{ {
info->error= -1; info->error= -1;
return 1; DBUG_RETURN(1);
} }
if (read_length == 0) if (read_length == 0)
{ {
/* End of file from client */ info->end_of_file= 0; /* End of file from client */
info->end_of_file = 1; return 1; DBUG_RETURN(1);
} }
/* to set up stuff for my_b_get (no _) */ /* to set up stuff for my_b_get (no _) */
info->rc_end = (info->rc_pos = (byte*) net->read_pos) + read_length; info->read_end = (info->read_pos = (byte*) net->read_pos) + read_length;
Buffer[0] = info->rc_pos[0]; /* length is always 1 */ Buffer[0] = info->read_pos[0]; /* length is always 1 */
info->rc_pos++; info->read_pos++;
info->buffer = info->rc_pos;
return 0; /*
info->request_pos is used by log_loaded_block() to know the size
of the current block
*/
info->request_pos=info->read_pos;
DBUG_RETURN(0);
} }
} /* extern "C" */ } /* extern "C" */
...@@ -2614,7 +2614,7 @@ int QUICK_SELECT_DESC::get_next() ...@@ -2614,7 +2614,7 @@ int QUICK_SELECT_DESC::get_next()
} }
else else
{ {
dbug_assert(range->flag & NEAR_MAX || range_reads_after_key(range)); DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
/* Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will /* Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will
* do the right thing - go past all keys which match the prefix */ * do the right thing - go past all keys which match the prefix */
result=file->index_read(record, (byte*) range->max_key, result=file->index_read(record, (byte*) range->max_key,
......
...@@ -882,7 +882,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -882,7 +882,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->outer_join=table->null_row=table->maybe_null=0; table->outer_join=table->null_row=table->maybe_null=0;
table->status=STATUS_NO_RECORD; table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query=table->used_keys= table->keys_in_use; table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
dbug_assert(table->key_read == 0); DBUG_ASSERT(table->key_read == 0);
DBUG_RETURN(table); DBUG_RETURN(table);
} }
......
...@@ -126,7 +126,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -126,7 +126,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
mode=RNEXT; mode=RNEXT;
break; break;
case RLAST: case RLAST:
dbug_assert(keyname != 0); DBUG_ASSERT(keyname != 0);
err=table->file->index_last(table->record[0]); err=table->file->index_last(table->record[0]);
mode=RPREV; mode=RPREV;
break; break;
...@@ -136,12 +136,12 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -136,12 +136,12 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
table->file->rnd_next(table->record[0]); table->file->rnd_next(table->record[0]);
break; break;
case RPREV: case RPREV:
dbug_assert(keyname != 0); DBUG_ASSERT(keyname != 0);
err=table->file->index_prev(table->record[0]); err=table->file->index_prev(table->record[0]);
break; break;
case RKEY: case RKEY:
{ {
dbug_assert(keyname != 0); DBUG_ASSERT(keyname != 0);
KEY *keyinfo=table->key_info+keyno; KEY *keyinfo=table->key_info+keyno;
KEY_PART_INFO *key_part=keyinfo->key_part; KEY_PART_INFO *key_part=keyinfo->key_part;
uint key_len; uint key_len;
......
...@@ -551,7 +551,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term, ...@@ -551,7 +551,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term,
need_end_io_cache = 1; need_end_io_cache = 1;
if (!opt_old_rpl_compat && mysql_bin_log.is_open()) if (!opt_old_rpl_compat && mysql_bin_log.is_open())
cache.pre_read = cache.pre_close = cache.pre_read = cache.pre_close =
(IO_CACHE_CALLBACK)log_loaded_block; (IO_CACHE_CALLBACK) log_loaded_block;
} }
} }
} }
......
...@@ -288,7 +288,7 @@ static void decrease_user_connections(const char *user, const char *host) ...@@ -288,7 +288,7 @@ static void decrease_user_connections(const char *user, const char *host)
uc = (struct user_conn *) hash_search(&hash_user_connections, uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len); (byte*) temp_user, temp_len);
dbug_assert(uc != 0); // We should always find the user DBUG_ASSERT(uc != 0); // We should always find the user
if (!uc) if (!uc)
goto end; // Safety; Something went wrong goto end; // Safety; Something went wrong
if (! --uc->connections) if (! --uc->connections)
......
...@@ -137,7 +137,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name, ...@@ -137,7 +137,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 || if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 ||
init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0, init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
MYF(MY_WME))) MYF(MY_WME | MY_DONT_CHECK_FILESIZE)))
{ {
*errmsg = "Could not open log file"; // This will not be sent *errmsg = "Could not open log file"; // This will not be sent
goto err; goto err;
...@@ -1024,8 +1024,10 @@ int log_loaded_block(IO_CACHE* file) ...@@ -1024,8 +1024,10 @@ int log_loaded_block(IO_CACHE* file)
{ {
LOAD_FILE_INFO* lf_info; LOAD_FILE_INFO* lf_info;
uint block_len ; uint block_len ;
char* buffer = (char*)file->buffer;
if (!(block_len = file->rc_end - buffer)) /* file->request_pos contains position where we started last read */
char* buffer = (char*) file->request_pos;
if (!(block_len = file->read_end - buffer))
return 0; return 0;
lf_info = (LOAD_FILE_INFO*)file->arg; lf_info = (LOAD_FILE_INFO*)file->arg;
if (lf_info->last_pos_in_file != HA_POS_ERROR && if (lf_info->last_pos_in_file != HA_POS_ERROR &&
......
...@@ -2680,7 +2680,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab) ...@@ -2680,7 +2680,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
if (order) if (order)
{ {
found++; found++;
dbug_assert(!(order->used & map)); DBUG_ASSERT(!(order->used & map));
order->used|=map; order->used|=map;
continue; // Used in ORDER BY continue; // Used in ORDER BY
} }
......
...@@ -1687,7 +1687,7 @@ static void init_pid_file() ...@@ -1687,7 +1687,7 @@ static void init_pid_file()
if (!fp) if (!fp)
die("Could not open pid file %s", pid_file); die("Could not open pid file %s", pid_file);
created_pid_file=1; created_pid_file=1;
fprintf(fp, "%d\n", getpid()); fprintf(fp, "%d\n", (int) getpid());
fclose(fp); fclose(fp);
} }
......
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