diff options
Diffstat (limited to 'isam')
-rw-r--r-- | isam/.cvsignore | 10 | ||||
-rw-r--r-- | isam/ChangeLog | 186 | ||||
-rw-r--r-- | isam/Makefile.am | 45 | ||||
-rw-r--r-- | isam/_cache.c | 92 | ||||
-rw-r--r-- | isam/_dbug.c | 132 | ||||
-rw-r--r-- | isam/_dynrec.c | 1247 | ||||
-rw-r--r-- | isam/_key.c | 238 | ||||
-rw-r--r-- | isam/_locking.c | 345 | ||||
-rw-r--r-- | isam/_packrec.c | 1184 | ||||
-rw-r--r-- | isam/_page.c | 143 | ||||
-rw-r--r-- | isam/_search.c | 889 | ||||
-rw-r--r-- | isam/_statrec.c | 265 | ||||
-rw-r--r-- | isam/changed.c | 35 | ||||
-rw-r--r-- | isam/close.c | 92 | ||||
-rw-r--r-- | isam/create.c | 328 | ||||
-rw-r--r-- | isam/delete.c | 615 | ||||
-rw-r--r-- | isam/extra.c | 271 | ||||
-rw-r--r-- | isam/info.c | 77 | ||||
-rw-r--r-- | isam/isamchk.c | 3424 | ||||
-rw-r--r-- | isam/isamdef.h | 418 | ||||
-rw-r--r-- | isam/isamlog.c | 853 | ||||
-rw-r--r-- | isam/log.c | 156 | ||||
-rwxr-xr-x | isam/make-ccc | 3 | ||||
-rw-r--r-- | isam/open.c | 477 | ||||
-rw-r--r-- | isam/pack_isam.c | 2042 | ||||
-rw-r--r-- | isam/panic.c | 135 | ||||
-rw-r--r-- | isam/range.c | 191 | ||||
-rw-r--r-- | isam/rfirst.c | 34 | ||||
-rw-r--r-- | isam/rkey.c | 63 | ||||
-rw-r--r-- | isam/rlast.c | 34 | ||||
-rw-r--r-- | isam/rnext.c | 67 | ||||
-rw-r--r-- | isam/rprev.c | 64 | ||||
-rw-r--r-- | isam/rrnd.c | 55 | ||||
-rw-r--r-- | isam/rsame.c | 70 | ||||
-rw-r--r-- | isam/rsamepos.c | 59 | ||||
-rw-r--r-- | isam/sort.c | 558 | ||||
-rw-r--r-- | isam/static.c | 45 | ||||
-rw-r--r-- | isam/test1.c | 179 | ||||
-rw-r--r-- | isam/test2.c | 841 | ||||
-rw-r--r-- | isam/test3.c | 494 | ||||
-rwxr-xr-x | isam/test_all | 30 | ||||
-rw-r--r-- | isam/test_all.res | 30 | ||||
-rw-r--r-- | isam/update.c | 117 | ||||
-rw-r--r-- | isam/write.c | 840 |
44 files changed, 0 insertions, 17473 deletions
diff --git a/isam/.cvsignore b/isam/.cvsignore deleted file mode 100644 index dc55807a96b..00000000000 --- a/isam/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -isamchk -isamlog -pack_isam -test1 -test2 -test3 diff --git a/isam/ChangeLog b/isam/ChangeLog deleted file mode 100644 index 4a9e3e03954..00000000000 --- a/isam/ChangeLog +++ /dev/null @@ -1,186 +0,0 @@ -2000-04-26 Michael Widenius <monty@mysql.com> - -* Fixed bug when doing read_next after a delete/insert which balanced key - pages (In this case one internal buffer was wrongly reused) - -1999-11-23 Michael Widenius <monty@monty.pp.sci.fi> - -* Changed prefix from ni_ to nisam_ to avoid problems on MacOS X. - -1999-08-17 Michael Widenius <monty@tik.pp.sci.fi> - -* Changed last parameter to mi_open() to be a bit flag instead of an int. - -1998-10-01 Michael Widenius <monty@monty.pp.sci.fi> - -* Fixed bug in key packing when using some USE_STRCOLL character sets. - -Thu Aug 20 23:17:41 1998 Michael Widenius <monty@bitch.pp.sci.fi> - -* isamchk.c: Sometimes isamchk --sort-table caused isamchk to die. - -1998-06-28 Michael Widenius <monty@monty.pp.sci.fi> - -* Fixed some possible race conditions when using with MySQL and - many reopen/close of the same tables under heavy load! -* Changed isamchk to re-pack records when doing a repair to make it more safer. - -Thu Mar 12 21:44:08 1998 Michael Widenius <monty@monty.pp.sci.fi> - -* Added a safty test to _ni_rec_unpack. - -Wed Nov 26 01:52:55 1997 <monty@monty.pp.sci.fi> - -* Fixed small problem when reading delete-marked records with rkey, rnext and - rprev. In normal applications this should never happen. - -Thu Nov 20 14:01:21 1997 <monty@monty.pp.sci.fi> - -* Fixed range key bug when using compressed key where the first part wasn't - compressed. -* Converted everything to use prototypes. - -Mon Sep 29 13:16:27 1997 <monty@monty.pp.sci.fi> - -* Fixed problem with isamchk and compressed records files with record_reflength - < 4 (Gave wrong key when using isamchk -rq). - -Fri Sep 26 16:06:37 1997 <monty@monty.pp.sci.fi> - -* Fixed bug in range calculation. - -Thu Aug 14 14:44:33 1997 <monty@monty.pp.sci.fi> - -* Removed a couple of unnecessary seeks from 'delete static record' - -Tue Jul 1 22:04:16 1997 <monty@monty.pp.sci.fi> - -* Added checking of 'wrong packed records' when using 'isamchk -e' or - isamchk -ro. - -Fri Feb 7 22:22:28 1997 Michael Widenius <monty@bitch.sci.fi> - -* Fixed use of packed tables with threads (One static variable left) - -Thu Jan 23 09:05:22 1997 Michael Widenius <monty@bitch.sci.fi> - -* Changed create to detect keys > 127 and not pack them. Now one can - define keys with a length of up to (nisam_block_size-18)/2 - by changeing N_MAX_KEY_LENGTH. - -Fri Jan 10 21:01:44 1997 Michael Widenius <monty@bitch.sci.fi> - -* added signed chars as key type. - -Fri Apr 26 14:31:05 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)> - -* create.c: All keyfile blocks are now IO_SIZE big (for better keycashing). - -Tue Mar 12 22:42:52 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)> - -* isamchk.c: Changed to print info if system table -* write.c: Don't allow more than 1 record in system table. - -Fri Feb 2 16:40:32 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)> - -* isamchk.c; Check that delete-link-chain is ok before trying to delete with 'q'. - -Thu Jan 11 13:21:23 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)> - -* All same isam files now shares a structure to allow many opens off the same - file - -Sat Nov 25 12:33:53 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)> - -* All functions now used my_errno instead of errno - -Mon Oct 23 12:32:02 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)> - -* isamchk.c: Don't print that database should be fixed on automatic rep. - -Sun Aug 27 20:13:56 1995 Michael Widenius <monty@bitch.analytikerna.se (Michael Widenius)> - -* _dynrec.c added flush_io_cash() if someone did a read when using - WRITE CASHING. - -Thu Apr 20 01:41:24 1995 Michael Widenius (monty@bitch) - -* fixed errno when got error of 'key-not-found' when updateing or - deleting record. - -Tue Jan 17 19:37:48 1995 Michael Widenius (monty@bitch) - -* isamchk can now unpack databases. -* prolinted all files. - -Fri May 27 15:01:06 1994 Michael Widenius (monty@bitch) - -* Don't lock packed databases. - -Sat Apr 16 22:41:23 1994 Michael Widenius (monty@bitch) - -* Added new function read_rsame_with_pos. - -Wed Mar 30 15:52:19 1994 Michael Widenius (monty@bitch) - -* Added creation and recover date to indexfile and isamchk. - -Sat Mar 26 15:03:37 1994 Michael Widenius (monty@bitch) - -* change is_panic() to close all files on ha_panic(write) on systems - (VMS) with can't open one file twice. - -Fri Feb 4 21:09:56 1994 Michael Widenius (monty@bitch) - -* READ_CASH on packed files now makes them mem-mapped if possibly - -Sat Sep 18 14:56:32 1993 Michael Widenius (monty at bitch) - -* changed _search to use pointer to buffer when reading keys. - -Mon Aug 16 19:45:29 1993 Michael Widenius (monty at bitch) - -* isamchk and packisam resolves symbolic links before file is used. - This forces temp-files on same disk as orginal file and rename - of temp-files dosen't destroy symbolic links. - -Mon May 31 18:26:08 1993 Michael Widenius (monty at bitch) - -* Added crc-check of records when packing for safe test if pack ok. - -Tue Mar 2 19:16:00 1993 Michael Widenius (monty@bitch) - -* Added logging of records with ni_log(). - -Fri Jan 29 00:56:58 1993 Michael Widenius (monty@bitch) - -* Fixed bug in _read_rnd_static_record ; A lock was made for - each record even if it was in cash. - -Sun Nov 15 12:51:36 1992 Michael Widenius (monty@bitch) - -* last change breaked _dynrec, when not compileing with dbug. - -Fri Nov 6 03:46:38 1992 Michael Widenius (monty@bitch) - -* Fixed bugg when using packed records and reclength < 8 byte. - -Wed Oct 28 22:23:32 1992 Michael Widenius (monty@bitch) - -* Changed _cash.c to use io_cash to allow use of aioread. - -Fri Oct 23 00:45:53 1992 Michael Widenius (monty@bitch) - -* Added MY_WAIT_IF_FULL to pack_isam. - -Sat Oct 17 14:51:15 1992 Michael Widenius (monty@bitch) - -* Added use of subset of keys (isamchk -k#) - -Mon Oct 5 21:53:18 1992 Michael Widenius (monty@bitch) - -* Remove reloc of database ; Gives only problems with isamchk. - -Mon Aug 17 03:17:09 1992 Michael Widenius (monty@bitch) - -* Changed isam to use io_cash instead of rec_cash diff --git a/isam/Makefile.am b/isam/Makefile.am deleted file mode 100644 index 6d9e4176d43..00000000000 --- a/isam/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2000 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 - -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include -LDADD = @CLIENT_EXTRA_LDFLAGS@ libnisam.a ../mysys/libmysys.a \ - ../dbug/libdbug.a ../strings/libmystrings.a -pkglib_LIBRARIES = libnisam.a -bin_PROGRAMS = isamchk isamlog pack_isam -isamchk_DEPENDENCIES= $(LIBRARIES) -isamlog_DEPENDENCIES= $(LIBRARIES) -pack_isam_DEPENDENCIES= $(LIBRARIES) -noinst_PROGRAMS = test1 test2 test3 -noinst_HEADERS = isamdef.h -test1_DEPENDENCIES= $(LIBRARIES) -test2_DEPENDENCIES= $(LIBRARIES) -test3_DEPENDENCIES= $(LIBRARIES) -libnisam_a_SOURCES = open.c extra.c info.c rkey.c rnext.c \ - _search.c _page.c _key.c _locking.c \ - rrnd.c _cache.c _statrec.c _packrec.c \ - _dynrec.c update.c write.c delete.c \ - rprev.c rfirst.c rlast.c rsame.c rsamepos.c \ - panic.c close.c create.c range.c _dbug.c \ - log.c changed.c static.c -isamchk_SOURCES = isamchk.c sort.c -CLEANFILES = test?.IS? isam.log - -# Move to automake rules ? -prolint:; plparse -b -u -hF1 "-width(0,0)" "-format=%f:%l:\s%t:%n\s%m" \ - "-elib(????)" "+elib(?3??)" my.lnt $(nisam_SOURCES) - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/isam/_cache.c b/isam/_cache.c deleted file mode 100644 index bca9a699a85..00000000000 --- a/isam/_cache.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Functions for read record cacheing with nisam */ -/* Used instead of my_b_read() to allow for no-cacheed seeks */ - -#include "isamdef.h" - -#define READING_NEXT 1 -#define READING_HEADER 2 - - /* Copy block from cache if it`s in it. If re_read_if_possibly is */ - /* set read to cache (if after current file-position) else read to */ - /* buff */ - -int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length, - int flag) -{ - uint read_length,in_buff_length; - ulong offset; - char *in_buff_pos; - - if (pos < info->pos_in_file) - { - read_length= (uint) min((ulong) length,(ulong) (info->pos_in_file-pos)); - info->seek_not_done=1; - VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0))); - if (my_read(info->file,buff,read_length,MYF(MY_NABP))) - return 1; - if (!(length-=read_length)) - return 0; - pos+=read_length; - buff+=read_length; - } - if ((offset=pos - (ulong) info->pos_in_file) < - (ulong) (info->read_end - info->request_pos)) - { - in_buff_pos=info->request_pos+(uint) offset; - in_buff_length= min(length,(uint) (info->read_end-in_buff_pos)); - memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length); - if (!(length-=in_buff_length)) - return 0; - pos+=in_buff_length; - buff+=in_buff_length; - } - else - in_buff_length=0; - if (flag & READING_NEXT) - { - if (pos != ((info)->pos_in_file + - (uint) ((info)->read_end - (info)->request_pos))) - { - info->pos_in_file=pos; /* Force start here */ - info->read_pos=info->read_end=info->request_pos; /* Everything used */ - info->seek_not_done=1; - } - else - info->read_pos=info->read_end; /* All block used */ - if (!(*info->read_function)(info,buff,length)) - return 0; - if (!(flag & READING_HEADER) || info->error == -1 || - (uint) info->error+in_buff_length < 3) - return 1; - if (BLOCK_INFO_HEADER_LENGTH < in_buff_length + (uint) info->error) - bzero(buff+info->error,BLOCK_INFO_HEADER_LENGTH - in_buff_length - - (uint) info->error); - return 0; - } - info->seek_not_done=1; - VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0))); - if ((read_length=my_read(info->file,buff,length,MYF(0))) == length) - return 0; - if (!(flag & READING_HEADER) || (int) read_length == -1 || - read_length+in_buff_length < 3) - return 1; - bzero(buff+read_length,BLOCK_INFO_HEADER_LENGTH - in_buff_length - - read_length); - return 0; -} /* _nisam_read_cache */ diff --git a/isam/_dbug.c b/isam/_dbug.c deleted file mode 100644 index 0a52dbbc916..00000000000 --- a/isam/_dbug.c +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Support rutiner with are using with dbug */ - -#include "isamdef.h" - - /* Print a key in user understandable format */ - -void _nisam_print_key(FILE *stream, register N_KEYSEG *keyseg, const uchar *key) -{ - int flag; - short int s_1; - long int l_1; - float f_1; - double d_1; - uchar *end; - - VOID(fputs("Key: \"",stream)); - flag=0; - for (; keyseg->base.type ;keyseg++) - { - if (flag++) - VOID(putc('-',stream)); - end= (uchar*) key+ keyseg->base.length; - switch (keyseg->base.type) { - case HA_KEYTYPE_BINARY: - if (!(keyseg->base.flag & HA_SPACE_PACK) && keyseg->base.length == 1) - { /* packed binary digit */ - VOID(fprintf(stream,"%d",(uint) *key++)); - break; - } - /* fall through */ - case HA_KEYTYPE_TEXT: - case HA_KEYTYPE_NUM: - if (keyseg->base.flag & HA_SPACE_PACK) - { - VOID(fprintf(stream,"%.*s",(int) *key,key+1)); - key+= (int) *key+1; - } - else - { - VOID(fprintf(stream,"%.*s",(int) keyseg->base.length,key)); - key=end; - } - break; - case HA_KEYTYPE_INT8: - VOID(fprintf(stream,"%d",(int) *((signed char*) key))); - key=end; - break; - case HA_KEYTYPE_SHORT_INT: - shortget(s_1,key); - VOID(fprintf(stream,"%d",(int) s_1)); - key=end; - break; - case HA_KEYTYPE_USHORT_INT: - { - ushort u_1; - ushortget(u_1,key); - VOID(fprintf(stream,"%u",(uint) u_1)); - key=end; - break; - } - case HA_KEYTYPE_LONG_INT: - longget(l_1,key); - VOID(fprintf(stream,"%ld",l_1)); - key=end; - break; - case HA_KEYTYPE_ULONG_INT: - longget(l_1,key); - VOID(fprintf(stream,"%lu",(ulong) l_1)); - key=end; - break; - case HA_KEYTYPE_INT24: - VOID(fprintf(stream,"%ld",(long) sint3korr(key))); - key=end; - break; - case HA_KEYTYPE_UINT24: - VOID(fprintf(stream,"%ld",(long) uint3korr(key))); - key=end; - break; - case HA_KEYTYPE_FLOAT: - bmove((byte*) &f_1,(byte*) key,(int) sizeof(float)); - VOID(fprintf(stream,"%g",(double) f_1)); - key=end; - break; - case HA_KEYTYPE_DOUBLE: - doubleget(d_1,key); - VOID(fprintf(stream,"%g",d_1)); - key=end; - break; -#ifdef HAVE_LONG_LONG - case HA_KEYTYPE_LONGLONG: - { - char buff[21]; - longlong tmp; - longlongget(tmp,key); - longlong2str(tmp,buff,-10); - VOID(fprintf(stream,"%s",buff)); - key=end; - break; - } - case HA_KEYTYPE_ULONGLONG: - { - char buff[21]; - longlong tmp; - longlongget(tmp,key); - longlong2str(tmp,buff,10); - VOID(fprintf(stream,"%s",buff)); - key=end; - break; - } -#endif - default: break; /* This never happens */ - } - } - VOID(fputs("\n",stream)); - return; -} /* print_key */ diff --git a/isam/_dynrec.c b/isam/_dynrec.c deleted file mode 100644 index 25fe01e23f2..00000000000 --- a/isam/_dynrec.c +++ /dev/null @@ -1,1247 +0,0 @@ -/* Copyright (C) 2000 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 */ - - /* Functions to handle space-packed-records and blobs */ - -#include "isamdef.h" - -/* Enough for comparing if number is zero */ -static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -static int write_dynamic_record(N_INFO *info,const byte *record, - uint reclength); -static int _nisam_find_writepos(N_INFO *info,uint reclength,ulong *filepos, - uint *length); -static int update_dynamic_record(N_INFO *info,ulong filepos,byte *record, - uint reclength); -static int delete_dynamic_record(N_INFO *info,ulong filepos, - uint second_read); -static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos, - uint length); - -#ifdef THREAD -/* Play it safe; We have a small stack when using threads */ -#undef my_alloca -#undef my_afree -#define my_alloca(A) my_malloc((A),MYF(0)) -#define my_afree(A) my_free((A),MYF(0)) -#endif - - /* Interface function from N_INFO */ - -int _nisam_write_dynamic_record(N_INFO *info, const byte *record) -{ - uint reclength=_nisam_rec_pack(info,info->rec_buff,record); - return (write_dynamic_record(info,info->rec_buff,reclength)); -} - -int _nisam_update_dynamic_record(N_INFO *info, ulong pos, const byte *record) -{ - uint length=_nisam_rec_pack(info,info->rec_buff,record); - return (update_dynamic_record(info,pos,info->rec_buff,length)); -} - -int _nisam_write_blob_record(N_INFO *info, const byte *record) -{ - byte *rec_buff; - int error; - uint reclength,extra; - - extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+ - DYN_DELETE_BLOCK_HEADER; - if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+ - _calc_total_blob_length(info,record)+ - extra))) - return(-1); - reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER), - record); - error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER), - reclength); - my_afree(rec_buff); - return(error); -} - - -int _nisam_update_blob_record(N_INFO *info, ulong pos, const byte *record) -{ - byte *rec_buff; - int error; - uint reclength,extra; - - extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+ - DYN_DELETE_BLOCK_HEADER; - if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+ - _calc_total_blob_length(info,record)+ - extra))) - return(-1); - reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER), - record); - error=update_dynamic_record(info,pos, - rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER), - reclength); - my_afree(rec_buff); - return(error); -} - -int _nisam_delete_dynamic_record(N_INFO *info) -{ - return delete_dynamic_record(info,info->lastpos,0); -} - - - /* Write record to data-file */ - -static int write_dynamic_record(N_INFO *info, const byte *record, - uint reclength) -{ - int flag; - uint length; - ulong filepos; - DBUG_ENTER("write_dynamic_record"); - - flag=0; - while (reclength) - { - if (_nisam_find_writepos(info,reclength,&filepos,&length)) - goto err; - if (_nisam_write_part_record(info,filepos,length,info->s->state.dellink, - (byte**) &record,&reclength,&flag)) - goto err; - } - - DBUG_RETURN(0); - err: - DBUG_RETURN(1); -} - - - /* Get a block for data ; The given data-area must be used !! */ - -static int _nisam_find_writepos(N_INFO *info, - uint reclength, /* record length */ - ulong *filepos, /* Return file pos */ - uint *length) /* length of block at filepos */ -{ - BLOCK_INFO block_info; - DBUG_ENTER("_nisam_find_writepos"); - - if (info->s->state.dellink != NI_POS_ERROR) - { - *filepos=info->s->state.dellink; - block_info.second_read=0; - info->rec_cache.seek_not_done=1; - - if (!(_nisam_get_block_info(&block_info,info->dfile, - info->s->state.dellink) & BLOCK_DELETED)) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - DBUG_RETURN(-1); - } - info->s->state.dellink=block_info.next_filepos; - info->s->state.del--; - info->s->state.empty-= block_info.block_len; - *length= block_info.block_len; - } - else - { - if (info->s->state.data_file_length > info->s->base.max_data_file_length) - { - my_errno=HA_ERR_RECORD_FILE_FULL; - DBUG_RETURN(-1); - } - *filepos=info->s->state.data_file_length; /* New block last */ - if ((*length=reclength+3 + test(reclength > 65532)) < - info->s->base.min_block_length) - *length=info->s->base.min_block_length; - info->s->state.data_file_length+= *length; - info->s->state.splitt++; - info->update|=HA_STATE_WRITE_AT_END; - } - DBUG_RETURN(0); -} /* _nisam_find_writepos */ - - - /* Write a block to datafile */ - -int _nisam_write_part_record(N_INFO *info, - ulong filepos, /* points at empty block */ - uint length, /* length of block */ - ulong next_filepos, /* Next empty block */ - byte **record, /* pointer to record ptr */ - uint *reclength, /* length of *record */ - int *flag) /* *flag == 0 if header */ -{ - uint head_length,res_length,extra_length,long_block,del_length; - byte *pos,*record_end; - uchar temp[N_SPLITT_LENGTH+DYN_DELETE_BLOCK_HEADER]; - DBUG_ENTER("_nisam_write_part_record"); - - res_length=extra_length=0; - if (length > *reclength + N_SPLITT_LENGTH) - { /* Splitt big block */ - res_length=length- *reclength - 3 - N_EXTEND_BLOCK_LENGTH; - length-= res_length; /* Use this for first part */ - } - long_block= (length < 65535L && *reclength < 65535L) ? 0 : 1; - if (length-long_block == *reclength+3 || length == *reclength + 4) - { /* Exact what we need */ - temp[0]=(uchar) (1+ *flag); /* 1, or 9 */ - if (long_block) - { - int3store(temp+1,*reclength); - } - else - { - int2store(temp+1,*reclength); - } - head_length=3+long_block; - if (length-long_block == *reclength+4) - { - length--; - temp[0]++; /* 2 or 10 */ - extra_length++; /* One empty */ - } - } - else if (length-long_block*2 < *reclength+5) - { /* To short block */ - if (next_filepos == NI_POS_ERROR) - next_filepos=info->s->state.dellink != NI_POS_ERROR ? - info->s->state.dellink : info->s->state.data_file_length; - if (*flag == 0) /* First block */ - { - head_length=5+4+long_block*2; - temp[0]=4; - if (long_block) - { - int3store(temp+1,*reclength); - int3store(temp+4,length-head_length); - int4store((byte*) temp+7,next_filepos); - } - else - { - int2store(temp+1,*reclength); - int2store(temp+3,length-head_length); - int4store((byte*) temp+5,next_filepos); - } - } - else - { - head_length=3+4+long_block; - temp[0]=12; - if (long_block) - { - int3store(temp+1,length-head_length); - int4store((byte*) temp+4,next_filepos); - } - else - { - int2store(temp+1,length-head_length); - int4store((byte*) temp+3,next_filepos); - } - } - } - else - { /* Block with empty info last */ - head_length=5+long_block*2; - temp[0]= (uchar) (3+ *flag); /* 3 or 11 */ - if (long_block) - { - int3store(temp+1,*reclength); - int3store(temp+4,length-7); - } - else - { - int2store(temp+1,*reclength); - int2store(temp+3,length-5); - } - extra_length= length- *reclength-head_length; - length= *reclength+head_length; /* Write only what is needed */ - } - temp[0]+=(uchar) (long_block*4); - DBUG_DUMP("header",(byte*) temp,head_length); - - /* Make a long block for one write */ - record_end= *record+length-head_length; - del_length=(res_length ? DYN_DELETE_BLOCK_HEADER : 0); - bmove((byte*) (*record-head_length),(byte*) temp,head_length); - memcpy(temp,record_end,(size_t) (extra_length+del_length)); - bzero((byte*) record_end,extra_length); - if (res_length) - { - pos=record_end+extra_length; - pos[0]= '\0'; - int3store(pos+1,res_length); - int4store(pos+4,info->s->state.dellink); - info->s->state.dellink= filepos+length+extra_length; - info->s->state.del++; - info->s->state.empty+=res_length; - info->s->state.splitt++; - } - if (info->opt_flag & WRITE_CACHE_USED && info->update & HA_STATE_WRITE_AT_END) - { - if (my_b_write(&info->rec_cache,(byte*) *record-head_length, - length+extra_length+del_length)) - goto err; - } - else - { - info->rec_cache.seek_not_done=1; - if (my_pwrite(info->dfile,(byte*) *record-head_length,length+extra_length+ - del_length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL))) - goto err; - } - memcpy(record_end,temp,(size_t) (extra_length+del_length)); - *record=record_end; - *reclength-=(length-head_length); - *flag=8; - - DBUG_RETURN(0); -err: - DBUG_PRINT("exit",("errno: %d",my_errno)); - DBUG_RETURN(1); -} /*_nisam_write_part_record */ - - - /* update record from datafile */ - -static int update_dynamic_record(N_INFO *info, ulong filepos, byte *record, uint reclength) -{ - int flag; - uint error,length; - BLOCK_INFO block_info; - DBUG_ENTER("update_dynamic_record"); - - flag=block_info.second_read=0; - while (reclength > 0) - { - if (filepos != info->s->state.dellink) - { - block_info.next_filepos= NI_POS_ERROR; - if ((error=_nisam_get_block_info(&block_info,info->dfile,filepos)) - & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | - BLOCK_FATAL_ERROR)) - { - if (!(error & BLOCK_FATAL_ERROR)) - my_errno=HA_ERR_WRONG_IN_RECORD; - goto err; - } - length=(uint) (block_info.filepos-filepos) + block_info.block_len; - } - else - { - if (_nisam_find_writepos(info,reclength,&filepos,&length)) - goto err; - } - if (_nisam_write_part_record(info,filepos,length,block_info.next_filepos, - &record,&reclength,&flag)) - goto err; - if ((filepos=block_info.next_filepos) == NI_POS_ERROR) - filepos=info->s->state.dellink; - } - - if (block_info.next_filepos != NI_POS_ERROR) - if (delete_dynamic_record(info,block_info.next_filepos,1)) - goto err; - DBUG_RETURN(0); -err: - DBUG_RETURN(1); -} - - /* Delete datarecord from database */ - /* info->rec_cache.seek_not_done is updated in cmp_record */ - -static int delete_dynamic_record(N_INFO *info, ulong filepos, uint second_read) -{ - uint length,b_type; - BLOCK_INFO block_info; - DBUG_ENTER("delete_dynamic_record"); - - block_info.second_read=second_read; - do - { - if ((b_type=_nisam_get_block_info(&block_info,info->dfile,filepos)) - & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | - BLOCK_FATAL_ERROR) || - (length=(uint) (block_info.filepos-filepos) +block_info.block_len) < - N_MIN_BLOCK_LENGTH) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - DBUG_RETURN(1); - } - block_info.header[0]=0; - length=(uint) (block_info.filepos-filepos) +block_info.block_len; - int3store(block_info.header+1,length); - int4store(block_info.header+4,info->s->state.dellink); - if (my_pwrite(info->dfile,(byte*) block_info.header,8,filepos, - MYF(MY_NABP))) - DBUG_RETURN(1); - info->s->state.dellink = filepos; - info->s->state.del++; - info->s->state.empty+=length; - filepos=block_info.next_filepos; - } while (!(b_type & BLOCK_LAST)); - DBUG_RETURN(0); -} - - - /* Pack a record. Return new reclength */ - -uint _nisam_rec_pack(N_INFO *info, register byte *to, register const byte *from) -{ - uint length,new_length,flag,bit,i; - char *pos,*end,*startpos,*packpos; - enum en_fieldtype type; - reg3 N_RECINFO *rec; - N_BLOB *blob; - DBUG_ENTER("_nisam_rec_pack"); - - flag=0 ; bit=1; - startpos=packpos=to; to+= info->s->base.pack_bits; blob=info->blobs; - rec=info->s->rec; - - for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length) - { - length=(uint) rec->base.length; - if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL) - { - if (type == FIELD_BLOB) - { - if (!blob->length) - flag|=bit; - else - { - char *temp_pos; - memcpy((byte*) to,from,(size_t) length); - memcpy_fixed(&temp_pos,from+length,sizeof(char*)); - memcpy(to+length,temp_pos,(size_t) blob->length); - to+=length+blob->length; - } - blob++; - from+=sizeof(char*); /* Skip blob-pointer */ - } - else if (type == FIELD_SKIP_ZERO) - { - if (memcmp((byte*) from,zero_string,length) == 0) - flag|=bit; - else - { - memcpy((byte*) to,from,(size_t) length); to+=length; - } - } - else if (type == FIELD_SKIP_ENDSPACE || - type == FIELD_SKIP_PRESPACE) - { - pos= (byte*) from; end= (byte*) from + length; - if (type == FIELD_SKIP_ENDSPACE) - { /* Pack trailing spaces */ - while (end > from && *(end-1) == ' ') - end--; - } - else - { /* Pack pref-spaces */ - while (pos < end && *pos == ' ') - pos++; - } - new_length=(uint) (end-pos); - if (new_length +1 + test(rec->base.length > 255 && new_length > 127) - < length) - { - if (rec->base.length > 255 && new_length > 127) - { - to[0]=(char) ((new_length & 127)+128); - to[1]=(char) (new_length >> 7); - to+=2; - } - else - *to++= (char) new_length; - memcpy((byte*) to,pos,(size_t) new_length); to+=new_length; - flag|=bit; - } - else - { - memcpy(to,from,(size_t) length); to+=length; - } - } - else if (type == FIELD_ZERO) - continue; /* Don't store this */ - else - { - memcpy(to,from,(size_t) length); to+=length; - continue; /* Normal field */ - } - if ((bit= bit << 1) >= 256) - { - *packpos++ = (char) (uchar) flag; - bit=1; flag=0; - } - } - else - { - memcpy(to,from,(size_t) length); to+=length; - } - } - if (bit != 1) - *packpos= (char) (uchar) flag; - DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos))); - DBUG_RETURN((uint) (to-startpos)); -} /* _nisam_rec_pack */ - - - -/* -** Check if a record was correctly packed. Used only by isamchk -** Returns 0 if record is ok. -*/ - -my_bool _nisam_rec_check(N_INFO *info,const char *from) -{ - uint length,new_length,flag,bit,i; - char *pos,*end,*packpos,*to; - enum en_fieldtype type; - reg3 N_RECINFO *rec; - DBUG_ENTER("_nisam_rec_check"); - - packpos=info->rec_buff; to= info->rec_buff+info->s->base.pack_bits; - rec=info->s->rec; - flag= *packpos; bit=1; - - for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length) - { - length=(uint) rec->base.length; - if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL) - { - if (type == FIELD_BLOB) - { - uint blob_length= _calc_blob_length(length,from); - if (!blob_length && !(flag & bit)) - goto err; - if (blob_length) - to+=length+ blob_length; - from+=sizeof(char*); - } - else if (type == FIELD_SKIP_ZERO) - { - if (memcmp((byte*) from,zero_string,length) == 0) - { - if (!(flag & bit)) - goto err; - } - else - to+=length; - } - else if (type == FIELD_SKIP_ENDSPACE || - type == FIELD_SKIP_PRESPACE) - { - pos= (byte*) from; end= (byte*) from + length; - if (type == FIELD_SKIP_ENDSPACE) - { /* Pack trailing spaces */ - while (end > from && *(end-1) == ' ') - end--; - } - else - { /* Pack pre-spaces */ - while (pos < end && *pos == ' ') - pos++; - } - new_length=(uint) (end-pos); - if (new_length +1 + test(rec->base.length > 255 && new_length > 127) - < length) - { - if (!(flag & bit)) - goto err; - if (rec->base.length > 255 && new_length > 127) - { - if (to[0] != (char) ((new_length & 127)+128) || - to[1] != (char) (new_length >> 7)) - goto err; - to+=2; - } - else if (*to++ != (char) new_length) - goto err; - to+=new_length; - } - else - to+=length; - } - else - { - if (type != FIELD_ZERO) - to+=length; /* Not packed field */ - continue; - } - if ((bit= bit << 1) >= 256) - { - flag= *++packpos; - bit=1; - } - } - else - { - to+=length; - } - } - if (bit != 1) - *packpos= (char) (uchar) flag; - if (info->packed_length == (uint) (to - info->rec_buff) && - (bit == 1 || !(flag & ~(bit - 1)))) - DBUG_RETURN(0); - - err: - DBUG_RETURN(1); -} - - - - /* Unpacks a record */ - /* Returns -1 and my_errno =HA_ERR_RECORD_DELETED if reclength isn't */ - /* right. Returns reclength (>0) if ok */ - -uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from, - uint found_length) -{ - uint flag,bit,length,rec_length,min_pack_length; - enum en_fieldtype type; - byte *from_end,*to_end,*packpos; - reg3 N_RECINFO *rec,*end_field; - DBUG_ENTER("_nisam_rec_unpack"); - - to_end=to + info->s->base.reclength; - from_end=from+found_length; - flag= (uchar) *from; bit=1; packpos=from; - if (found_length < info->s->base.min_pack_length) - goto err; - from+= info->s->base.pack_bits; - min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits; - - for (rec=info->s->rec , end_field=rec+info->s->base.fields ; - rec < end_field ; to+= rec_length, rec++) - { - rec_length=rec->base.length; - if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL) - { - if (type == FIELD_ZERO) - continue; /* Skip this */ - if (flag & bit) - { - if (type == FIELD_BLOB) - { - bzero((byte*) to,rec_length+sizeof(char*)); - to+=sizeof(char*); - } - else if (type == FIELD_SKIP_ZERO) - bzero((byte*) to,rec_length); - else if (type == FIELD_SKIP_ENDSPACE || - type == FIELD_SKIP_PRESPACE) - { - if (rec->base.length > 255 && *from & 128) - { - if (from + 1 >= from_end) - goto err; - length= (*from & 127)+ ((uint) (uchar) *(from+1) << 7); from+=2; - } - else - { - if (from == from_end) - goto err; - length= (uchar) *from++; - } - min_pack_length--; - if (length >= rec_length || - min_pack_length + length > (uint) (from_end - from)) - goto err; - if (type == FIELD_SKIP_ENDSPACE) - { - memcpy(to,(byte*) from,(size_t) length); - bfill((byte*) to+length,rec_length-length,' '); - } - else - { - bfill((byte*) to,rec_length-length,' '); - memcpy(to+rec_length-length,(byte*) from,(size_t) length); - } - from+=length; - } - } - else if (type == FIELD_BLOB) - { - ulong blob_length=_calc_blob_length(rec_length,from); - if ((ulong) (from_end-from) - rec_length < blob_length || - min_pack_length > (uint) (from_end -(from+rec_length+blob_length))) - goto err; - memcpy((byte*) to,(byte*) from,(size_t) rec_length); - from+=rec_length; - /* memcpy crasches alpha egcs 1.1.2 */ - bmove((byte*) to+rec_length,(byte*) &from,sizeof(char*)); - from+=blob_length; - to+=sizeof(char*); - } - else - { - if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE) - min_pack_length--; - if (min_pack_length + rec_length > (uint) (from_end - from)) - goto err; - memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length; - } - if ((bit= bit << 1) >= 256) - { - flag= (uchar) *++packpos; bit=1; - } - } - else - { - if (min_pack_length > (uint) (from_end - from)) - goto err; - min_pack_length-=rec_length; - memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length; - } - } - if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1)))) - DBUG_RETURN((info->packed_length=found_length)); - err: - my_errno=HA_ERR_RECORD_DELETED; - DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx", - to,to_end,from,from_end)); - DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length); - DBUG_RETURN(MY_FILE_ERROR); -} /* _nisam_rec_unpack */ - - - /* Calc length of blob. Update info in blobs->length */ - -uint _calc_total_blob_length(N_INFO *info, const byte *record) -{ - uint i,length; - N_BLOB *blob; - - for (i=length=0, blob= info->blobs; i++ < info->s->base.blobs ; blob++) - { - blob->length=_calc_blob_length(blob->pack_length,record + blob->offset); - length+=blob->length; - } - return length; -} - - -uint _calc_blob_length(uint length, const byte *pos) -{ - switch (length) { - case 1: - return (uint) (uchar) *pos; - case 2: - { - short j; shortget(j,pos); - return (uint) (unsigned short) j; - } -#ifdef MSDOS - break; /* skip microsoft warning */ -#endif - case 3: - return uint3korr(pos); - case 4: - { - long j; longget(j,pos); - return (uint) j; - } -#ifdef MSDOS - break; -#endif - default: - break; - } - return 0; /* Impossible */ -} - - /* Read record from datafile */ - /* Returns 0 if ok, -1 if error */ - -int _nisam_read_dynamic_record(N_INFO *info, ulong filepos, byte *buf) -{ - int flag; - uint b_type,left_length; - byte *to; - BLOCK_INFO block_info; - File file; - DBUG_ENTER("ni_read_dynamic_record"); - - if (filepos != NI_POS_ERROR) - { - LINT_INIT(to); - LINT_INIT(left_length); - file=info->dfile; - block_info.next_filepos=filepos; /* for easyer loop */ - flag=block_info.second_read=0; - do - { - if (info->opt_flag & WRITE_CACHE_USED && - info->rec_cache.pos_in_file <= block_info.next_filepos && - flush_io_cache(&info->rec_cache)) - goto err; - info->rec_cache.seek_not_done=1; - if ((b_type=_nisam_get_block_info(&block_info,file, - block_info.next_filepos)) - & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | - BLOCK_FATAL_ERROR)) - { - if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED)) - my_errno=HA_ERR_RECORD_DELETED; - goto err; - } - if (flag == 0) /* First block */ - { - flag=1; - if (block_info.rec_len > (uint) info->s->base.max_pack_length) - goto panic; - if (info->s->base.blobs) - { - if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len))) - goto err; - } - else - to= info->rec_buff; - left_length=block_info.rec_len; - } - if (left_length < block_info.data_len || ! block_info.data_len) - goto panic; /* Wrong linked record */ - if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos, - MYF(MY_NABP))) - goto panic; - left_length-=block_info.data_len; - to+=block_info.data_len; - } while (left_length); - - info->update|= HA_STATE_AKTIV; /* We have a aktive record */ - VOID(_nisam_writeinfo(info,0)); - DBUG_RETURN(_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) != - MY_FILE_ERROR ? 0 : -1); - } - VOID(_nisam_writeinfo(info,0)); - DBUG_RETURN(-1); /* Wrong data to read */ - -panic: - my_errno=HA_ERR_WRONG_IN_RECORD; -err: - VOID(_nisam_writeinfo(info,0)); - DBUG_RETURN(-1); -} - - -byte *fix_rec_buff_for_blob(N_INFO *info, uint length) -{ - uint extra; - if (! info->rec_buff || length > info->alloced_rec_buff_length) - { - byte *newptr; - extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+ - DYN_DELETE_BLOCK_HEADER; - if (!(newptr=(byte*) my_realloc((gptr) info->rec_alloc,length+extra, - MYF(MY_ALLOW_ZERO_PTR)))) - return newptr; - info->rec_alloc=newptr; - info->rec_buff=newptr+ALIGN_SIZE(DYN_DELETE_BLOCK_HEADER); - info->alloced_rec_buff_length=length; - } - return info->rec_buff; -} - - - /* Compare of record one disk with packed record in memory */ - -int _nisam_cmp_dynamic_record(register N_INFO *info, register const byte *record) -{ - uint flag,reclength,b_type; - ulong filepos; - byte *buffer; - BLOCK_INFO block_info; - DBUG_ENTER("_nisam_cmp_dynamic_record"); - - /* We are going to do changes; dont let anybody disturb */ - dont_break(); /* Dont allow SIGHUP or SIGINT */ - - if (info->opt_flag & WRITE_CACHE_USED) - { - info->update&= ~HA_STATE_WRITE_AT_END; - if (flush_io_cache(&info->rec_cache)) - DBUG_RETURN(-1); - } - info->rec_cache.seek_not_done=1; - - /* If nobody have touched the database we don't have to test rec */ - - buffer=info->rec_buff; - if ((info->opt_flag & READ_CHECK_USED)) - { /* If check isn't disabled */ - if (info->s->base.blobs) - { - if (!(buffer=(byte*) my_alloca(info->s->base.pack_reclength+ - _calc_total_blob_length(info,record)))) - DBUG_RETURN(-1); - } - reclength=_nisam_rec_pack(info,buffer,record); - record= buffer; - - filepos=info->lastpos; - flag=block_info.second_read=0; - block_info.next_filepos=filepos; - while (reclength > 0) - { - if ((b_type=_nisam_get_block_info(&block_info,info->dfile, - block_info.next_filepos)) - & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | - BLOCK_FATAL_ERROR)) - { - if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED)) - my_errno=HA_ERR_RECORD_CHANGED; - goto err; - } - if (flag == 0) /* First block */ - { - flag=1; - if (reclength != block_info.rec_len) - { - my_errno=HA_ERR_RECORD_CHANGED; - goto err; - } - } else if (reclength < block_info.data_len) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - goto err; - } - reclength-=block_info.data_len; - if (_nisam_cmp_buffer(info->dfile,record,block_info.filepos, - block_info.data_len)) - { - my_errno=HA_ERR_RECORD_CHANGED; - goto err; - } - flag=1; - record+=block_info.data_len; - } - } - my_errno=0; - err: - if (buffer != info->rec_buff) - my_afree((gptr) buffer); - DBUG_RETURN(my_errno); -} - - - /* Compare file to buffert */ - -static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos, uint length) -{ - uint next_length; - char temp_buff[IO_SIZE*2]; - DBUG_ENTER("_nisam_cmp_buffer"); - - VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); - next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1)); - - while (length > IO_SIZE*2) - { - if (my_read(file,temp_buff,next_length,MYF(MY_NABP))) - goto err; - if (memcmp((byte*) buff,temp_buff,next_length)) - DBUG_RETURN(1); - buff+=next_length; - length-= next_length; - next_length=IO_SIZE*2; - } - if (my_read(file,temp_buff,length,MYF(MY_NABP))) - goto err; - DBUG_RETURN(memcmp((byte*) buff,temp_buff,length)); -err: - DBUG_RETURN(1); -} - - -int _nisam_read_rnd_dynamic_record(N_INFO *info, byte *buf, register ulong filepos, int skipp_deleted_blocks) -{ - int flag,info_read,fatal_errcode; - uint left_len,b_type; - byte *to; - BLOCK_INFO block_info; - ISAM_SHARE *share=info->s; - DBUG_ENTER("_nisam_read_rnd_dynamic_record"); - - info_read=0; - fatal_errcode= -1; - LINT_INIT(to); - -#ifndef NO_LOCKING - if (info->lock_type == F_UNLCK) - { -#ifndef UNSAFE_LOCKING - if (share->r_locks == 0 && share->w_locks == 0) - { - if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF, - MYF(MY_SEEK_NOT_DONE) | info->lock_wait)) - DBUG_RETURN(fatal_errcode); - } -#else - info->tmp_lock_type=F_RDLCK; -#endif - } - else - info_read=1; /* memory-keyinfoblock is ok */ -#endif /* !NO_LOCKING */ - - flag=block_info.second_read=0; - left_len=1; - do - { - if (filepos >= share->state.data_file_length) - { -#ifndef NO_LOCKING - if (!info_read) - { /* Check if changed */ - info_read=1; - info->rec_cache.seek_not_done=1; - if (my_pread(share->kfile,(char*) &share->state.header, - share->state_length, 0L,MYF(MY_NABP))) - goto err; - } - if (filepos >= share->state.data_file_length) -#endif - { - my_errno= HA_ERR_END_OF_FILE; - goto err; - } - } - if (info->opt_flag & READ_CACHE_USED) - { - if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos, - sizeof(block_info.header), - test(!flag && skipp_deleted_blocks) | 2)) - goto err; - b_type=_nisam_get_block_info(&block_info,-1,filepos); - } - else - { - if (info->opt_flag & WRITE_CACHE_USED && - info->rec_cache.pos_in_file <= filepos && - flush_io_cache(&info->rec_cache)) - DBUG_RETURN(-1); - info->rec_cache.seek_not_done=1; - b_type=_nisam_get_block_info(&block_info,info->dfile,filepos); - } - - if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | - BLOCK_FATAL_ERROR)) - { - if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR)) - && skipp_deleted_blocks) - { - filepos=block_info.filepos+block_info.block_len; - block_info.second_read=0; - continue; /* Search after next_record */ - } - if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR)) - { - my_errno=HA_ERR_RECORD_DELETED; - info->lastpos=block_info.filepos; - info->nextpos=block_info.filepos+block_info.block_len; - fatal_errcode=1; - } - goto err; - } - if (flag == 0) /* First block */ - { - if (block_info.rec_len > (uint) share->base.max_pack_length) - goto panic; - info->lastpos=filepos; - if (share->base.blobs) - { - if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len))) - goto err; - } - else - to= info->rec_buff; - left_len=block_info.rec_len; - } - if (left_len < block_info.data_len) - goto panic; /* Wrong linked record */ - - if (info->opt_flag & READ_CACHE_USED) - { - if (_nisam_read_cache(&info->rec_cache,(byte*) to,block_info.filepos, - block_info.data_len, - test(!flag && skipp_deleted_blocks))) - goto err; - } - else - { - VOID(my_seek(info->dfile,block_info.filepos,MY_SEEK_SET,MYF(0))); - if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP))) - goto err; - } - if (flag++ == 0) - { - info->nextpos=block_info.filepos+block_info.block_len; - skipp_deleted_blocks=0; - } - left_len-=block_info.data_len; - to+=block_info.data_len; - filepos=block_info.next_filepos; - } while (left_len); - - info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; - VOID(_nisam_writeinfo(info,0)); - if (_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) != - MY_FILE_ERROR) - DBUG_RETURN(0); - DBUG_RETURN(fatal_errcode); /* Wrong record */ - -panic: - my_errno=HA_ERR_WRONG_IN_RECORD; /* Something is fatal wrong */ -err: - VOID(_nisam_writeinfo(info,0)); - DBUG_RETURN(fatal_errcode); -} - - - /* Read and process header from a dynamic-record-file */ - -uint _nisam_get_block_info(BLOCK_INFO *info, File file, ulong filepos) -{ - uint return_val=0,length; - uchar *header=info->header; - - if (file >= 0) - { - VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); - if ((length=my_read(file,(char*) header,BLOCK_INFO_HEADER_LENGTH,MYF(0))) - == MY_FILE_ERROR) - return BLOCK_FATAL_ERROR; - if (length != BLOCK_INFO_HEADER_LENGTH) - { /* Test if short block */ - if (length < 3) - { - my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */ - return BLOCK_FATAL_ERROR; - } - bzero((byte*) header+length,BLOCK_INFO_HEADER_LENGTH-length); - } - } - DBUG_DUMP("header",(byte*) header,BLOCK_INFO_HEADER_LENGTH); - if (info->second_read) - { - if (info->header[0] <= 8) - return_val=BLOCK_SYNC_ERROR; - } - else - { - if (info->header[0] > 8) - return_val=BLOCK_SYNC_ERROR; - } - info->next_filepos= (ulong) NI_POS_ERROR; /* Dummy ifall no next block */ - - switch (info->header[0]) { - case 0: - if ((info->block_len=(uint) uint3korr(header+1)) < N_MIN_BLOCK_LENGTH) - return BLOCK_FATAL_ERROR; - info->filepos=filepos; - info->next_filepos=uint4korr(header+4); - if (info->next_filepos == (uint32) ~0) /* Fix for 64 bit long */ - info->next_filepos=NI_POS_ERROR; - return return_val | BLOCK_DELETED; /* Deleted block */ - case 1: - info->rec_len=info->data_len=info->block_len=uint2korr(header+1); - info->filepos=filepos+3; - return return_val | BLOCK_FIRST | BLOCK_LAST; - case 2: - info->block_len=(info->rec_len=info->data_len=uint2korr(header+1))+1; - info->filepos=filepos+3; - return return_val | BLOCK_FIRST | BLOCK_LAST; - case 3: - info->rec_len=info->data_len=uint2korr(header+1); - info->block_len=uint2korr(header+3); - info->filepos=filepos+5; - return return_val | BLOCK_FIRST | BLOCK_LAST; - case 4: - info->rec_len=uint2korr(header+1); - info->block_len=info->data_len=uint2korr(header+3); - info->next_filepos=uint4korr(header+5); - info->second_read=1; - info->filepos=filepos+9; - return return_val | BLOCK_FIRST; -#if defined(_MSC_VER) || !defined(__WIN__) - case 5: - info->rec_len=info->data_len=info->block_len=uint3korr(header+1); - info->filepos=filepos+4; - return return_val | BLOCK_FIRST | BLOCK_LAST; - case 6: - info->block_len=(info->rec_len=info->data_len=uint3korr(header+1))+1; - info->filepos=filepos+4; - return return_val | BLOCK_FIRST | BLOCK_LAST; - case 7: - info->rec_len=info->data_len=uint3korr(header+1); - info->block_len=uint3korr(header+4); - info->filepos=filepos+7; - return return_val | BLOCK_FIRST | BLOCK_LAST; - case 8: - info->rec_len=uint3korr(header+1); - info->block_len=info->data_len=uint3korr(header+4); - info->next_filepos=uint4korr(header+7); - info->second_read=1; - info->filepos=filepos+11; - return return_val | BLOCK_FIRST; -#endif - case 9: - info->data_len=info->block_len=uint2korr(header+1); - info->filepos=filepos+3; - return return_val | BLOCK_LAST; - case 10: - info->block_len=(info->data_len=uint2korr(header+1))+1; - info->filepos=filepos+3; - return return_val | BLOCK_LAST; - case 11: - info->data_len=uint2korr(header+1); - info->block_len=uint2korr(header+3); - info->filepos=filepos+5; - return return_val | BLOCK_LAST; - case 12: - info->data_len=info->block_len=uint2korr(header+1); - info->next_filepos=uint4korr(header+3); - info->second_read=1; - info->filepos=filepos+7; - return return_val; -#if defined(_MSC_VER) || !defined(__WIN__) - case 13: - info->data_len=info->block_len=uint3korr(header+1); - info->filepos=filepos+4; - return return_val | BLOCK_LAST; - case 14: - info->block_len=(info->data_len=uint3korr(header+1))+1; - info->filepos=filepos+4; - return return_val | BLOCK_LAST; - case 15: - info->data_len=uint3korr(header+1); - info->block_len=uint3korr(header+4); - info->filepos=filepos+7; - return return_val | BLOCK_LAST; - case 16: - info->data_len=info->block_len=uint3korr(header+1); - info->next_filepos=uint4korr(header+4); - info->second_read=1; - info->filepos=filepos+8; - return return_val; -#endif - default: - my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */ - return BLOCK_ERROR; - } -} diff --git a/isam/_key.c b/isam/_key.c deleted file mode 100644 index 65d6885869e..00000000000 --- a/isam/_key.c +++ /dev/null @@ -1,238 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Functions to handle keys */ - -#include "isamdef.h" -#include "m_ctype.h" - -static void _nisam_put_key_in_record(N_INFO *info,uint keynr,byte *record); - - /* Make a intern key from a record */ - /* If ascii key convert according to sortorder */ - /* Ret: Length of key */ - -uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *record, ulong filepos) -{ - uint length; - byte *pos,*end; - uchar *start; - reg1 N_KEYSEG *keyseg; - enum ha_base_keytype type; - DBUG_ENTER("_nisam_make_key"); - - start=key; - for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++) - { - type=(enum ha_base_keytype) keyseg->base.type; - if (keyseg->base.flag & HA_SPACE_PACK) - { - pos= (byte*) record+keyseg->base.start; end=pos+keyseg->base.length; - if (type != HA_KEYTYPE_NUM) - { - while (end > pos && end[-1] == ' ') - end--; - } - else - { - while (pos < end && pos[0] == ' ') - pos++; - } - *key++= (uchar) (length=(uint) (end-pos)); - memcpy((byte*) key,(byte*) pos,(size_t) length); - if (!use_strnxfrm(default_charset_info)) - { - if (type == HA_KEYTYPE_TEXT) - my_strnxfrm(default_charset_info,(uchar*) key, length, - (uchar*) key, length); - } - key+=length; - } - else - { - memcpy((byte*) key,(byte*) record+keyseg->base.start, - (size_t) keyseg->base.length); - if (!use_strnxfrm(default_charset_info)) - { - if (type == HA_KEYTYPE_TEXT) - my_strnxfrm(default_charset_info,(uchar*) key, - (uint) keyseg->base.length, - (uchar*) key, - (uint) keyseg->base.length); - } -#ifdef NAN_TEST - else if (type == HA_KEYTYPE_FLOAT) - { - float nr; - bmove((byte*) &nr,(byte*) key,sizeof(float)); - if (nr == (float) FLT_MAX) - { - nr= (float) FLT_MAX; - bmove((byte*) key,(byte*) &nr,sizeof(float)); - } - } - else if (type == HA_KEYTYPE_DOUBLE) - { - double nr; - bmove((byte*) &nr,(byte*) key,sizeof(double)); - if (nr == DBL_MAX) - { - nr=DBL_MAX; - bmove((byte*) key,(byte*) &nr,sizeof(double)); - } - } -#endif - key+= keyseg->base.length; - } - } - _nisam_dpointer(info,key,filepos); - DBUG_PRINT("exit",("keynr: %d",keynr)); - DBUG_DUMP("key",(byte*) start,(uint) (key-start)+keyseg->base.length); - DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start);); - DBUG_RETURN((uint) (key-start)); /* Return keylength */ -} /* _nisam_make_key */ - - - /* Pack a key to intern format from given format (c_rkey) */ - /* if key_length is set returns new length of key */ - -uint _nisam_pack_key(register N_INFO *info, uint keynr, uchar *key, uchar *old, uint key_length) - - - - /* Length of used key */ -{ - int k_length; - uint length; - uchar *pos,*end; - reg1 N_KEYSEG *keyseg; - enum ha_base_keytype type; - DBUG_ENTER("_nisam_pack_key"); - - if ((k_length=(int) key_length) <= 0) - k_length=N_MAX_KEY_BUFF; - - for (keyseg=info->s->keyinfo[keynr].seg ; - keyseg->base.type && k_length >0; - k_length-=keyseg->base.length, old+=keyseg->base.length, keyseg++) - { - length=min((uint) keyseg->base.length,(uint) k_length); - type=(enum ha_base_keytype) keyseg->base.type; - if (keyseg->base.flag & HA_SPACE_PACK) - { - pos=old; end=pos+length; - if (type != HA_KEYTYPE_NUM) - { - while (end > pos && end[-1] == ' ') - end--; - } - else - { - while (pos < end && pos[0] == ' ') - pos++; - } - *key++ = (uchar) (length=(uint) (end-pos)); - memcpy((byte*) key,pos,(size_t) length); - } - else - memcpy((byte*) key,old,(size_t) length); - if (!use_strnxfrm(default_charset_info)) - { - if (type == HA_KEYTYPE_TEXT) - my_strnxfrm(default_charset_info,(uchar*) key,length, - (uchar*) key,length); - } - key+= length; - } - if (!keyseg->base.type) - { - if (k_length >= 0) /* Hole key */ - key_length=0; - } - else - { /* Part-key ; fill with null */ - length= (uint) -k_length; /* unused part of last key */ - do - { - length+= (keyseg->base.flag & HA_SPACE_PACK) ? 1 : - keyseg->base.length; - keyseg++; - } while (keyseg->base.type); - bzero((byte*) key,length); - } - DBUG_RETURN(key_length); /* Return part-keylength */ -} /* _nisam_pack_key */ - - - /* Put a key in record */ - /* Used when only-keyread is wanted */ - -static void _nisam_put_key_in_record(register N_INFO *info, uint keynr, byte *record) -{ - uint length; - reg2 byte *key; - byte *pos; - reg1 N_KEYSEG *keyseg; - DBUG_ENTER("_nisam_put_key_in_record"); - - key=(byte*) info->lastkey; - for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++) - { - if (keyseg->base.flag & HA_SPACE_PACK) - { - length= (uint) (uchar) *key++; - pos= record+keyseg->base.start; - if (keyseg->base.type != (int) HA_KEYTYPE_NUM) - { - memcpy(pos,key,(size_t) length); - bfill(pos+length,keyseg->base.length-length,' '); - } - else - { - bfill(pos,keyseg->base.length-length,' '); - memcpy(pos+keyseg->base.length-length,key,(size_t) length); - } - key+=length; - } - else - { - memcpy(record+keyseg->base.start,(byte*) key, - (size_t) keyseg->base.length); - key+= keyseg->base.length; - } - } - DBUG_VOID_RETURN; -} /* _nisam_put_key_in_record */ - - - /* Here when key reads are used */ - -int _nisam_read_key_record(N_INFO *info, ulong filepos, byte *buf) -{ - VOID(_nisam_writeinfo(info,0)); - if (filepos != NI_POS_ERROR) - { - if (info->lastinx >= 0) - { /* Read only key */ - _nisam_put_key_in_record(info,(uint) info->lastinx,buf); - info->update|= HA_STATE_AKTIV; /* We should find a record */ - return 0; - } - my_errno=HA_ERR_WRONG_INDEX; - return(-1); - } - return(-1); /* Wrong data to read */ -} diff --git a/isam/_locking.c b/isam/_locking.c deleted file mode 100644 index e19804549e5..00000000000 --- a/isam/_locking.c +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* - locking of isam-tables. - reads info from a isam-table. Must be first request before doing any furter - calls to any isamfunktion. Is used to allow many process use the same - isamdatabase. - */ - -#include "isamdef.h" -#ifdef __WIN__ -#include <errno.h> -#endif - - /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */ - -int nisam_lock_database(N_INFO *info, int lock_type) -{ - int error; - uint count; - ISAM_SHARE *share; - uint flag; - DBUG_ENTER("nisam_lock_database"); - - flag=error=0; -#ifndef NO_LOCKING - share=info->s; - if (share->base.options & HA_OPTION_READ_ONLY_DATA || - info->lock_type == lock_type) - DBUG_RETURN(0); - pthread_mutex_lock(&share->intern_lock); - switch (lock_type) { - case F_UNLCK: - if (info->lock_type == F_RDLCK) - count= --share->r_locks; - else - count= --share->w_locks; - if (info->lock_type == F_WRLCK && !share->w_locks && - flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_KEEP)) - error=my_errno; - if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) - if (end_io_cache(&info->rec_cache)) - error=my_errno; - - if (!count) - { - if (share->changed && !share->w_locks) - { - share->state.process= share->last_process=share->this_process; - share->state.loop= info->last_loop= ++info->this_loop; - share->state.uniq= info->last_uniq= info->this_uniq; - if (my_pwrite(share->kfile,(char*) &share->state.header, - share->state_length,0L,MYF(MY_NABP))) - error=my_errno; - share->changed=0; -#ifdef __WIN__ - if (nisam_flush) - { - _commit(share->kfile); - _commit(info->dfile); - } - else - share->not_flushed=1; -#endif - } - if (share->r_locks) - { /* Only read locks left */ - flag=1; - if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF, - MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error) - error=my_errno; - } - else if (!share->w_locks) - { /* No more locks */ - flag=1; - if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF, - MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error) - error=my_errno; - } - } - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - info->lock_type= F_UNLCK; - break; - case F_RDLCK: - if (info->lock_type == F_WRLCK) - { /* Change RW to READONLY */ - if (share->w_locks == 1) - { - flag=1; - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, - MYF(MY_SEEK_NOT_DONE))) - { - error=my_errno; - break; - } - } - share->w_locks--; - share->r_locks++; - info->lock_type=lock_type; - break; - } - if (!share->r_locks && !share->w_locks) - { - flag=1; -#ifdef HAVE_FCNTL - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait)) - { - error=my_errno; - break; - } - if (my_pread(share->kfile, - (char*) &share->state.header,share->state_length,0L, - MYF(MY_NABP))) - { - error=my_errno; - VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE))); - my_errno=error; - break; - } -#else - VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0))); - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait)) - { - error=my_errno; - break; - } - if (my_read(share->kfile, - (char*) &share->state.header,share->state_length, - MYF(MY_NABP))) - { - error=my_errno; - VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait)); - my_errno=error; - break; - } -#endif - } - VOID(_nisam_test_if_changed(info)); - share->r_locks++; - info->lock_type=lock_type; - break; - case F_WRLCK: - if (info->lock_type == F_RDLCK) - { /* Change RW to READONLY */ - if (share->r_locks == 1) - { - flag=1; - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, - MYF(info->lock_wait | MY_SEEK_NOT_DONE))) - { - error=my_errno; - break; - } - share->r_locks--; - share->w_locks++; - info->lock_type=lock_type; - break; - } - } - if (!(share->base.options & HA_OPTION_READ_ONLY_DATA) && !share->w_locks) - { - flag=1; - VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0))); - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait)) - { - error=my_errno; - break; - } - if (!share->r_locks) - { - if (my_read(share->kfile, - (char*) &share->state.header,share->state_length, - MYF(MY_NABP))) - { - error=my_errno; - VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait)); - my_errno=error; - break; - } - } - } - VOID(_nisam_test_if_changed(info)); - info->lock_type=lock_type; - share->w_locks++; - break; - default: - break; /* Impossible */ - } - pthread_mutex_unlock(&share->intern_lock); -#if defined(FULL_LOG) || defined(_lint) - lock_type|=(int) (flag << 8); /* Set bit to set if real lock */ - nisam_log_command(LOG_LOCK,info,(byte*) &lock_type,sizeof(lock_type), - error); -#endif -#endif - DBUG_RETURN(error); -} /* nisam_lock_database */ - - - /* Is used before access to database is granted */ - -int _nisam_readinfo(register N_INFO *info, int lock_type, int check_keybuffer) -{ - ISAM_SHARE *share; - DBUG_ENTER("_nisam_readinfo"); - - share=info->s; - if (info->lock_type == F_UNLCK) - { - if (!share->r_locks && !share->w_locks) - { -#ifndef HAVE_FCNTL - VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0))); -#endif -#ifndef NO_LOCKING -#ifdef UNSAFE_LOCKING - if ((info->tmp_lock_type=lock_type) != F_RDLCK) -#endif - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait)) - DBUG_RETURN(1); -#endif -#ifdef HAVE_FCNTL - if (my_pread(share->kfile, - (char*) &share->state.header,share->state_length,0L, - MYF(MY_NABP))) -#else - if (my_read(share->kfile, - (char*) &share->state.header,share->state_length, - MYF(MY_NABP))) -#endif - { -#ifndef NO_LOCKING - int error=my_errno; - VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF, - MYF(MY_SEEK_NOT_DONE))); - my_errno=error; -#endif - DBUG_RETURN(1); - } - } - if (check_keybuffer) - VOID(_nisam_test_if_changed(info)); - } - else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK) - { - my_errno=EACCES; /* Not allowed to change */ - DBUG_RETURN(-1); /* when have read_lock() */ - } - DBUG_RETURN(0); -} /* _nisam_readinfo */ - - - /* Every isam-function that uppdates the isam-database must! end */ - /* with this request */ - /* ARGSUSED */ - -int _nisam_writeinfo(register N_INFO *info, uint flags) -{ - int error,olderror; - ISAM_SHARE *share; - DBUG_ENTER("_nisam_writeinfo"); - - error=0; - share=info->s; - if (share->r_locks == 0 && share->w_locks == 0) - { - olderror=my_errno; /* Remember last error */ - if (flags) - { /* Two threads can't be here */ - share->state.process= share->last_process= share->this_process; - share->state.loop= info->last_loop= ++info->this_loop; - share->state.uniq= info->last_uniq= info->this_uniq; - if ((error=my_pwrite(share->kfile,(char*) &share->state.header, - share->state_length,0L,MYF(MY_NABP)) != 0)) - olderror=my_errno; -#ifdef __WIN__ - if (nisam_flush) - { - _commit(share->kfile); - _commit(info->dfile); - } -#endif - } - if (flags != 2) - { -#ifndef NO_LOCKING -#ifdef UNSAFE_LOCKING - if (info->tmp_lock_type != F_RDLCK) -#endif - { - if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF, - MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error) - DBUG_RETURN(1); - } -#endif - } - my_errno=olderror; - } - else if (flags) - share->changed= 1; /* Mark keyfile changed */ - DBUG_RETURN(error); -} /* _nisam_writeinfo */ - - - /* Test if someone has changed the database */ - /* (Should be called after readinfo) */ - -int _nisam_test_if_changed(register N_INFO *info) -{ -#ifndef NO_LOCKING - { - ISAM_SHARE *share=info->s; - if (share->state.process != share->last_process || - share->state.loop != info->last_loop || - share->state.uniq != info->last_uniq) - { /* Keyfile has changed */ - if (share->state.process != share->this_process) - VOID(flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE)); - share->last_process=share->state.process; - info->last_loop= share->state.loop; - info->last_uniq= share->state.uniq; - info->update|= HA_STATE_WRITTEN; /* Must use file on next */ - info->data_changed= 1; /* For nisam_is_changed */ - return 1; - } - } -#endif - return (!(info->update & HA_STATE_AKTIV) || - (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED | - HA_STATE_KEY_CHANGED))); -} /* _nisam_test_if_changed */ diff --git a/isam/_packrec.c b/isam/_packrec.c deleted file mode 100644 index 74a45852e63..00000000000 --- a/isam/_packrec.c +++ /dev/null @@ -1,1184 +0,0 @@ -/* Copyright (C) 2000 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 */ - - /* Functions to compressed records */ - -#include "isamdef.h" - -#define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */ - -#if INT_MAX > 65536L -#define BITS_SAVED 32 -#define MAX_QUICK_TABLE_BITS 9 /* Because we may shift in 24 bits */ -#else -#define BITS_SAVED 16 -#define MAX_QUICK_TABLE_BITS 6 -#endif - -#define get_bit(BU) ((BU)->bits ? \ - (BU)->current_byte & ((bit_type) 1 << --(BU)->bits) :\ - (fill_buffer(BU), (BU)->bits= BITS_SAVED-1,\ - (BU)->current_byte & ((bit_type) 1 << (BITS_SAVED-1)))) -#define skipp_to_next_byte(BU) ((BU)->bits&=~7) -#define get_bits(BU,count) (((BU)->bits >= count) ? (((BU)->current_byte >> ((BU)->bits-=count)) & mask[count]) : fill_and_get_bits(BU,count)) - -#define decode_bytes_test_bit(bit) \ - if (low_byte & (1 << (7-bit))) \ - pos++; \ - if (*pos & IS_CHAR) \ - { bits-=(bit+1); break; } \ - pos+= *pos - - - static void read_huff_table(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree, - uint16 **decode_table,byte **intervall_buff, - uint16 *tmp_buff); -static void make_quick_table(uint16 *to_table,uint16 *decode_table, - uint *next_free,uint value,uint bits, - uint max_bits); -static void fill_quick_table(uint16 *table,uint bits, uint max_bits, - uint value); -static uint copy_decode_table(uint16 *to_pos,uint offset, - uint16 *decode_table); -static uint find_longest_bitstream(uint16 *table); -static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *field, - BIT_BUFF *buff, - uchar *to, - uchar *end); -static void uf_zerofill_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_space_normal(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_space_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to, uchar *end); -static void uf_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_space_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_space_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to, uchar *end); -static void uf_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_space_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_zerofill_normal(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_constant(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_intervall(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_zero(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void decode_bytes(N_RECINFO *rec,BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static uint decode_pos(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree); -static void init_bit_buffer(BIT_BUFF *bit_buff,char *buffer,uint length); -static uint fill_and_get_bits(BIT_BUFF *bit_buff,uint count); -static void fill_buffer(BIT_BUFF *bit_buff); -static uint max_bit(uint value); -#ifdef HAVE_MMAP -static void _nisam_mempack_get_block_info(BLOCK_INFO *info,uint ref_length, - uchar *header); -#endif - -static uint mask[]= -{ - 0x00000000, - 0x00000001, 0x00000003, 0x00000007, 0x0000000f, - 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, - 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, - 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, -#if BITS_SAVED > 16 - 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, - 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, - 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, - 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff, -#endif - }; - - - /* Read all packed info, allocate memory and fix field structs */ - -my_bool _nisam_read_pack_info(N_INFO *info, pbool fix_keys) -{ - File file; - int diff_length; - uint i,trees,huff_tree_bits,rec_reflength,length; - uint16 *decode_table,*tmp_buff; - ulong elements,intervall_length; - char *disk_cache,*intervall_buff; - uchar header[32]; - ISAM_SHARE *share=info->s; - BIT_BUFF bit_buff; - DBUG_ENTER("_nisam_read_pack_info"); - - if (nisam_quick_table_bits < 4) - nisam_quick_table_bits=4; - else if (nisam_quick_table_bits > MAX_QUICK_TABLE_BITS) - nisam_quick_table_bits=MAX_QUICK_TABLE_BITS; - - file=info->dfile; - my_errno=0; - if (my_read(file,(byte*) header,sizeof(header),MYF(MY_NABP))) - { - if (!my_errno) - my_errno=HA_ERR_END_OF_FILE; - DBUG_RETURN(1); - } - if (memcmp((byte*) header,(byte*) nisam_pack_file_magic,4)) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - DBUG_RETURN(1); - } - share->pack.header_length=uint4korr(header+4); - share->min_pack_length=(uint) uint4korr(header+8); - share->max_pack_length=(uint) uint4korr(header+12); - set_if_bigger(share->base.pack_reclength,share->max_pack_length); - elements=uint4korr(header+16); - intervall_length=uint4korr(header+20); - trees=uint2korr(header+24); - share->pack.ref_length=header[26]; - rec_reflength=header[27]; - diff_length=(int) rec_reflength - (int) share->base.rec_reflength; - if (fix_keys) - share->rec_reflength=rec_reflength; - share->base.min_block_length=share->min_pack_length+share->pack.ref_length; - - if (!(share->decode_trees=(DECODE_TREE*) - my_malloc((uint) (trees*sizeof(DECODE_TREE)+ - intervall_length*sizeof(byte)), - MYF(MY_WME)))) - DBUG_RETURN(1); - intervall_buff=(byte*) (share->decode_trees+trees); - - length=(uint) (elements*2+trees*(1 << nisam_quick_table_bits)); - if (!(share->decode_tables=(uint16*) - my_malloc((length+512)*sizeof(uint16)+ - (uint) (share->pack.header_length+7), - MYF(MY_WME | MY_ZEROFILL)))) - { - my_free((gptr) share->decode_trees,MYF(0)); - DBUG_RETURN(1); - } - tmp_buff=share->decode_tables+length; - disk_cache=(byte*) (tmp_buff+512); - - if (my_read(file,disk_cache, - (uint) (share->pack.header_length-sizeof(header)), - MYF(MY_NABP))) - { - my_free((gptr) share->decode_trees,MYF(0)); - my_free((gptr) share->decode_tables,MYF(0)); - DBUG_RETURN(1); - } - - huff_tree_bits=max_bit(trees ? trees-1 : 0); - init_bit_buffer(&bit_buff,disk_cache, - (uint) (share->pack.header_length-sizeof(header))); - /* Read new info for each field */ - for (i=0 ; i < share->base.fields ; i++) - { - share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,4); - share->rec[i].pack_type=(uint) get_bits(&bit_buff,4); - share->rec[i].space_length_bits=get_bits(&bit_buff,4); - share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff, - huff_tree_bits); - share->rec[i].unpack=get_unpack_function(share->rec+i); - } - skipp_to_next_byte(&bit_buff); - decode_table=share->decode_tables; - for (i=0 ; i < trees ; i++) - read_huff_table(&bit_buff,share->decode_trees+i,&decode_table, - &intervall_buff,tmp_buff); - decode_table=(uint16*) - my_realloc((gptr) share->decode_tables, - (uint) ((byte*) decode_table - (byte*) share->decode_tables), - MYF(MY_HOLD_ON_ERROR)); - { - my_ptrdiff_t diff=PTR_BYTE_DIFF(decode_table,share->decode_tables); - share->decode_tables=decode_table; - for (i=0 ; i < trees ; i++) - share->decode_trees[i].table=ADD_TO_PTR(share->decode_trees[i].table, - diff, uint16*); - } - - /* Fix record-ref-length for keys */ - if (fix_keys) - { - for (i=0 ; i < share->base.keys ; i++) - { - share->keyinfo[i].base.keylength+=(uint16) diff_length; - share->keyinfo[i].base.minlength+=(uint16) diff_length; - share->keyinfo[i].base.maxlength+=(uint16) diff_length; - share->keyinfo[i].seg[share->keyinfo[i].base.keysegs].base.length= - (uint16) rec_reflength; - } - } - - if (bit_buff.error || bit_buff.pos < bit_buff.end) - { /* info_length was wrong */ - my_errno=HA_ERR_WRONG_IN_RECORD; - my_free((gptr) share->decode_trees,MYF(0)); - my_free((gptr) share->decode_tables,MYF(0)); - DBUG_RETURN(1); - } - DBUG_RETURN(0); -} - - - /* Read on huff-code-table from datafile */ - -static void read_huff_table(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree, - uint16 **decode_table, byte **intervall_buff, - uint16 *tmp_buff) -{ - uint min_chr,elements,char_bits,offset_bits,size,intervall_length,table_bits, - next_free_offset; - uint16 *ptr,*end; - - LINT_INIT(ptr); - if (!get_bits(bit_buff,1)) - { - min_chr=get_bits(bit_buff,8); - elements=get_bits(bit_buff,9); - char_bits=get_bits(bit_buff,5); - offset_bits=get_bits(bit_buff,5); - intervall_length=0; - ptr=tmp_buff; - } - else - { - min_chr=0; - elements=get_bits(bit_buff,15); - intervall_length=get_bits(bit_buff,16); - char_bits=get_bits(bit_buff,5); - offset_bits=get_bits(bit_buff,5); - decode_tree->quick_table_bits=0; - ptr= *decode_table; - } - size=elements*2-2; - - for (end=ptr+size ; ptr < end ; ptr++) - { - if (get_bit(bit_buff)) - *ptr= (uint16) get_bits(bit_buff,offset_bits); - else - *ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr)); - } - skipp_to_next_byte(bit_buff); - - decode_tree->table= *decode_table; - decode_tree->intervalls= *intervall_buff; - if (! intervall_length) - { - table_bits=find_longest_bitstream(tmp_buff); - if (table_bits > nisam_quick_table_bits) - table_bits=nisam_quick_table_bits; - next_free_offset= (1 << table_bits); - make_quick_table(*decode_table,tmp_buff,&next_free_offset,0,table_bits, - table_bits); - (*decode_table)+= next_free_offset; - decode_tree->quick_table_bits=table_bits; - } - else - { - (*decode_table)=end; - bit_buff->pos-= bit_buff->bits/8; - memcpy(*intervall_buff,bit_buff->pos,(size_t) intervall_length); - (*intervall_buff)+=intervall_length; - bit_buff->pos+=intervall_length; - bit_buff->bits=0; - } - return; -} - - -static void make_quick_table(uint16 *to_table, uint16 *decode_table, uint *next_free_offset, uint value, uint bits, uint max_bits) -{ - if (!bits--) - { - to_table[value]= (uint16) *next_free_offset; - *next_free_offset=copy_decode_table(to_table, *next_free_offset, - decode_table); - return; - } - if (!(*decode_table & IS_CHAR)) - { - make_quick_table(to_table,decode_table+ *decode_table, - next_free_offset,value,bits,max_bits); - } - else - fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table); - decode_table++; - value|= (1 << bits); - if (!(*decode_table & IS_CHAR)) - { - make_quick_table(to_table,decode_table+ *decode_table, - next_free_offset,value,bits,max_bits); - } - else - fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table); - return; -} - - -static void fill_quick_table(uint16 *table, uint bits, uint max_bits, uint value) -{ - uint16 *end; - value|=(max_bits-bits) << 8; - for (end=table+ (1 << bits) ; - table < end ; - *table++ = (uint16) value | IS_CHAR) ; -} - - -static uint copy_decode_table(uint16 *to_pos, uint offset, uint16 *decode_table) -{ - uint prev_offset; - prev_offset= offset; - - if (!(*decode_table & IS_CHAR)) - { - to_pos[offset]=2; - offset=copy_decode_table(to_pos,offset+2,decode_table+ *decode_table); - } - else - { - to_pos[offset]= *decode_table; - offset+=2; - } - decode_table++; - - if (!(*decode_table & IS_CHAR)) - { - to_pos[prev_offset+1]=(uint16) (offset-prev_offset-1); - offset=copy_decode_table(to_pos,offset,decode_table+ *decode_table); - } - else - to_pos[prev_offset+1]= *decode_table; - return offset; -} - - -static uint find_longest_bitstream(uint16 *table) -{ - uint length=1,length2; - if (!(*table & IS_CHAR)) - length=find_longest_bitstream(table+ *table)+1; - table++; - if (!(*table & IS_CHAR)) - { - length2=find_longest_bitstream(table+ *table)+1; - length=max(length,length2); - } - return length; -} - - - /* Read record from datafile */ - /* Returns length of packed record, -1 if error */ - -int _nisam_read_pack_record(N_INFO *info, ulong filepos, byte *buf) -{ - BLOCK_INFO block_info; - File file; - DBUG_ENTER("_nisam_read_pack_record"); - - if (filepos == NI_POS_ERROR) - DBUG_RETURN(-1); /* _search() didn't find record */ - - file=info->dfile; - if (_nisam_pack_get_block_info(&block_info,info->s->pack.ref_length,file, - filepos)) - goto err; - if (my_read(file,(byte*) info->rec_buff,block_info.rec_len,MYF(MY_NABP))) - goto panic; - info->update|= HA_STATE_AKTIV; - DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,info->rec_buff, - block_info.rec_len)); -panic: - my_errno=HA_ERR_WRONG_IN_RECORD; -err: - DBUG_RETURN(-1); -} - - - -int _nisam_pack_rec_unpack(register N_INFO *info, register byte *to, - byte *from, uint reclength) -{ - byte *end_field; - reg3 N_RECINFO *end; - N_RECINFO *current_field; - ISAM_SHARE *share=info->s; - DBUG_ENTER("_nisam_pack_rec_unpack"); - - init_bit_buffer(&info->bit_buff,from,reclength); - - for (current_field=share->rec, end=current_field+share->base.fields ; - current_field < end ; - current_field++,to=end_field) - { - end_field=to+current_field->base.length; - (*current_field->unpack)(current_field,&info->bit_buff,(uchar*) to, - (uchar*) end_field); - } - if (! info->bit_buff.error && - info->bit_buff.pos - info->bit_buff.bits/8 == info->bit_buff.end) - DBUG_RETURN(0); - my_errno=HA_ERR_WRONG_IN_RECORD; - info->update&= ~HA_STATE_AKTIV; - DBUG_RETURN(-1); -} /* _nisam_pack_rec_unpack */ - - - /* Return function to unpack field */ - -static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *, BIT_BUFF *, uchar *, uchar *) -{ - switch (rec->base_type) { - case FIELD_SKIP_ZERO: - if (rec->pack_type & PACK_TYPE_ZERO_FILL) - return &uf_zerofill_skipp_zero; - return &uf_skipp_zero; - case FIELD_NORMAL: - if (rec->pack_type & PACK_TYPE_SPACE_FIELDS) - return &uf_space_normal; - if (rec->pack_type & PACK_TYPE_ZERO_FILL) - return &uf_zerofill_normal; - return &decode_bytes; - case FIELD_SKIP_ENDSPACE: - if (rec->pack_type & PACK_TYPE_SPACE_FIELDS) - { - if (rec->pack_type & PACK_TYPE_SELECTED) - return &uf_space_endspace_selected; - return &uf_space_endspace; - } - if (rec->pack_type & PACK_TYPE_SELECTED) - return &uf_endspace_selected; - return &uf_endspace; - case FIELD_SKIP_PRESPACE: - if (rec->pack_type & PACK_TYPE_SPACE_FIELDS) - { - if (rec->pack_type & PACK_TYPE_SELECTED) - return &uf_space_prespace_selected; - return &uf_space_prespace; - } - if (rec->pack_type & PACK_TYPE_SELECTED) - return &uf_prespace_selected; - return &uf_prespace; - case FIELD_CONSTANT: - return &uf_constant; - case FIELD_INTERVALL: - return &uf_intervall; - case FIELD_ZERO: - return &uf_zero; - case FIELD_BLOB: /* Write this sometimes.. */ - case FIELD_LAST: - default: - return 0; /* This should never happend */ - } -} - - /* De different functions to unpack a field */ - -static void uf_zerofill_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - if (get_bit(bit_buff)) - bzero((char*) to,(uint) (end-to)); - else - { -#ifdef WORDS_BIGENDIAN - bzero((char*) to,rec->space_length_bits); - decode_bytes(rec,bit_buff,to+rec->space_length_bits,end); -#else - end-=rec->space_length_bits; - decode_bytes(rec,bit_buff,to,end); - bzero((byte*) end,rec->space_length_bits); -#endif - } -} - -static void uf_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - if (get_bit(bit_buff)) - bzero((char*) to,(uint) (end-to)); - else - decode_bytes(rec,bit_buff,to,end); -} - -static void uf_space_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - if (get_bit(bit_buff)) - bfill((byte*) to,(end-to),' '); - else - decode_bytes(rec,bit_buff,to,end); -} - -static void uf_space_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - uint spaces; - if (get_bit(bit_buff)) - bfill((byte*) to,(end-to),' '); - else - { - if (get_bit(bit_buff)) - { - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - if (to+spaces != end) - decode_bytes(rec,bit_buff,to,end-spaces); - bfill((byte*) end-spaces,spaces,' '); - } - else - decode_bytes(rec,bit_buff,to,end); - } -} - -static void uf_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - uint spaces; - if (get_bit(bit_buff)) - { - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - if (to+spaces != end) - decode_bytes(rec,bit_buff,to,end-spaces); - bfill((byte*) end-spaces,spaces,' '); - } - else - decode_bytes(rec,bit_buff,to,end); -} - -static void uf_space_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - uint spaces; - if (get_bit(bit_buff)) - bfill((byte*) to,(end-to),' '); - else - { - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - if (to+spaces != end) - decode_bytes(rec,bit_buff,to,end-spaces); - bfill((byte*) end-spaces,spaces,' '); - } -} - -static void uf_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, - uchar *end) -{ - uint spaces; - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - if (to+spaces != end) - decode_bytes(rec,bit_buff,to,end-spaces); - bfill((byte*) end-spaces,spaces,' '); -} - -static void uf_space_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - uint spaces; - if (get_bit(bit_buff)) - bfill((byte*) to,(end-to),' '); - else - { - if (get_bit(bit_buff)) - { - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - bfill((byte*) to,spaces,' '); - if (to+spaces != end) - decode_bytes(rec,bit_buff,to+spaces,end); - } - else - decode_bytes(rec,bit_buff,to,end); - } -} - - -static void uf_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - uint spaces; - if (get_bit(bit_buff)) - { - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - bfill((byte*) to,spaces,' '); - if (to+spaces != end) - decode_bytes(rec,bit_buff,to+spaces,end); - } - else - decode_bytes(rec,bit_buff,to,end); -} - - -static void uf_space_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - uint spaces; - if (get_bit(bit_buff)) - bfill((byte*) to,(end-to),' '); - else - { - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - bfill((byte*) to,spaces,' '); - if (to+spaces != end) - decode_bytes(rec,bit_buff,to+spaces,end); - } -} - -static void uf_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - uint spaces; - if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) - { - bit_buff->error=1; - return; - } - bfill((byte*) to,spaces,' '); - if (to+spaces != end) - decode_bytes(rec,bit_buff,to+spaces,end); -} - -static void uf_zerofill_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ -#ifdef WORDS_BIGENDIAN - bzero((char*) to,rec->space_length_bits); - decode_bytes(rec,bit_buff,(uchar*) to+rec->space_length_bits,end); -#else - end-=rec->space_length_bits; - decode_bytes(rec,bit_buff,(uchar*) to,end); - bzero((byte*) end,rec->space_length_bits); -#endif -} - -static void uf_constant(N_RECINFO *rec, - BIT_BUFF *bit_buff __attribute__((unused)), - uchar *to, uchar *end) -{ - memcpy(to,rec->huff_tree->intervalls,(size_t) (end-to)); -} - -static void uf_intervall(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - reg1 uint field_length=(uint) (end-to); - memcpy(to,rec->huff_tree->intervalls+field_length*decode_pos(bit_buff, - rec->huff_tree), - (size_t) field_length); -} - - -/*ARGSUSED*/ -static void uf_zero(N_RECINFO *rec __attribute__((unused)), - BIT_BUFF *bit_buff __attribute__((unused)), - uchar *to, uchar *end) -{ - bzero((char*) to,(uint) (end-to)); -} - - - /* Functions to decode of buffer of bits */ - -#if BITS_SAVED == 64 - -static void decode_bytes(rec,bit_buff,to,end) -N_RECINFO *rec; -BIT_BUFF *bit_buff; -uchar *to,*end; -{ - reg1 uint bits,low_byte; - reg3 uint16 *pos; - reg4 uint table_bits,table_and; - DECODE_TREE *decode_tree; - - decode_tree=rec->decode_tree; - bits=bit_buff->bits; /* Save in reg for quicker access */ - table_bits=decode_tree->quick_table_bits; - table_and= (1 << table_bits)-1; - - do - { - if (bits <= 32) - { - if (bit_buff->pos > bit_buff->end+4) - return; /* Can't be right */ - bit_buff->current_byte= (bit_buff->current_byte << 32) + - ((((uint) bit_buff->pos[3])) + - (((uint) bit_buff->pos[2]) << 8) + - (((uint) bit_buff->pos[1]) << 16) + - (((uint) bit_buff->pos[0]) << 24)); - bit_buff->pos+=4; - bits+=32; - } - /* First use info in quick_table */ - low_byte=(uint) (bit_buff->current_byte >> (bits - table_bits)) & table_and; - low_byte=decode_tree->table[low_byte]; - if (low_byte & IS_CHAR) - { - *to++ = (low_byte & 255); /* Found char in quick table */ - bits-= ((low_byte >> 8) & 31); /* Remove bits used */ - } - else - { /* Map through rest of decode-table */ - pos=decode_tree->table+low_byte; - bits-=table_bits; - for (;;) - { - low_byte=(uint) (bit_buff->current_byte >> (bits-8)); - decode_bytes_test_bit(0); - decode_bytes_test_bit(1); - decode_bytes_test_bit(2); - decode_bytes_test_bit(3); - decode_bytes_test_bit(4); - decode_bytes_test_bit(5); - decode_bytes_test_bit(6); - decode_bytes_test_bit(7); - bits-=8; - } - *to++ = *pos; - } - } while (to != end); - - bit_buff->bits=bits; - return; -} - -#else - -static void decode_bytes(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end) -{ - reg1 uint bits,low_byte; - reg3 uint16 *pos; - reg4 uint table_bits,table_and; - DECODE_TREE *decode_tree; - - decode_tree=rec->huff_tree; - bits=bit_buff->bits; /* Save in reg for quicker access */ - table_bits=decode_tree->quick_table_bits; - table_and= (1 << table_bits)-1; - - do - { - if (bits < table_bits) - { - if (bit_buff->pos > bit_buff->end+1) - return; /* Can't be right */ -#if BITS_SAVED == 32 - bit_buff->current_byte= (bit_buff->current_byte << 24) + - (((uint) ((uchar) bit_buff->pos[2]))) + - (((uint) ((uchar) bit_buff->pos[1])) << 8) + - (((uint) ((uchar) bit_buff->pos[0])) << 16); - bit_buff->pos+=3; - bits+=24; -#else - if (bits) /* We must have at leasts 9 bits */ - { - bit_buff->current_byte= (bit_buff->current_byte << 8) + - (uint) ((uchar) bit_buff->pos[0]); - bit_buff->pos++; - bits+=8; - } - else - { - bit_buff->current_byte= ((uint) ((uchar) bit_buff->pos[0]) << 8) + - ((uint) ((uchar) bit_buff->pos[1])); - bit_buff->pos+=2; - bits+=16; - } -#endif - } - /* First use info in quick_table */ - low_byte=(bit_buff->current_byte >> (bits - table_bits)) & table_and; - low_byte=decode_tree->table[low_byte]; - if (low_byte & IS_CHAR) - { - *to++ = (low_byte & 255); /* Found char in quick table */ - bits-= ((low_byte >> 8) & 31); /* Remove bits used */ - } - else - { /* Map through rest of decode-table */ - pos=decode_tree->table+low_byte; - bits-=table_bits; - for (;;) - { - if (bits < 8) - { /* We don't need to check end */ -#if BITS_SAVED == 32 - bit_buff->current_byte= (bit_buff->current_byte << 24) + - (((uint) ((uchar) bit_buff->pos[2]))) + - (((uint) ((uchar) bit_buff->pos[1])) << 8) + - (((uint) ((uchar) bit_buff->pos[0])) << 16); - bit_buff->pos+=3; - bits+=24; -#else - bit_buff->current_byte= (bit_buff->current_byte << 8) + - (uint) ((uchar) bit_buff->pos[0]); - bit_buff->pos+=1; - bits+=8; -#endif - } - low_byte=(uint) (bit_buff->current_byte >> (bits-8)); - decode_bytes_test_bit(0); - decode_bytes_test_bit(1); - decode_bytes_test_bit(2); - decode_bytes_test_bit(3); - decode_bytes_test_bit(4); - decode_bytes_test_bit(5); - decode_bytes_test_bit(6); - decode_bytes_test_bit(7); - bits-=8; - } - *to++ = (uchar) *pos; - } - } while (to != end); - - bit_buff->bits=bits; - return; -} -#endif /* BIT_SAVED == 64 */ - - -static uint decode_pos(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree) -{ - uint16 *pos=decode_tree->table; - for (;;) - { - if (get_bit(bit_buff)) - pos++; - if (*pos & IS_CHAR) - return (uint) (*pos & ~IS_CHAR); - pos+= *pos; - } -} - - -int _nisam_read_rnd_pack_record(N_INFO *info, byte *buf, - register ulong filepos, - int skipp_deleted_blocks) -{ - uint b_type; - BLOCK_INFO block_info; - ISAM_SHARE *share=info->s; - DBUG_ENTER("_nisam_read_rnd_pack_record"); - - if (filepos >= share->state.data_file_length) - { - my_errno= HA_ERR_END_OF_FILE; - goto err; - } - - if (info->opt_flag & READ_CACHE_USED) - { - if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos, - share->pack.ref_length, skipp_deleted_blocks)) - goto err; - b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length,-1, - filepos); - } - else - b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length, - info->dfile,filepos); - if (b_type) - goto err; -#ifndef DBUG_OFF - if (block_info.rec_len > share->max_pack_length) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - goto err; - } -#endif - if (info->opt_flag & READ_CACHE_USED) - { - if (_nisam_read_cache(&info->rec_cache,(byte*) info->rec_buff, - block_info.filepos, block_info.rec_len, - skipp_deleted_blocks)) - goto err; - } - else - { - if (my_read(info->dfile,(byte*) info->rec_buff,block_info.rec_len, - MYF(MY_NABP))) - goto err; - } - info->packed_length=block_info.rec_len; - info->lastpos=filepos; - info->nextpos=block_info.filepos+block_info.rec_len; - info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; - - DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,info->rec_buff, - block_info.rec_len)); -err: - DBUG_RETURN(-1); -} - - - /* Read and process header from a huff-record-file */ - -uint _nisam_pack_get_block_info(BLOCK_INFO *info, uint ref_length, File file, - ulong filepos) -{ - uchar *header=info->header; - - if (file >= 0) - { - VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); - if (my_read(file,(char*) header,ref_length,MYF(MY_NABP))) - return BLOCK_FATAL_ERROR; - } - DBUG_DUMP("header",(byte*) header,ref_length); - - switch (ref_length) { - case 1: - info->rec_len=header[0]; - info->filepos=filepos+1; - break; - case 2: - info->rec_len=uint2korr(header); - info->filepos=filepos+2; - break; - case 3: - info->rec_len=(uint) (uint3korr(header)); - info->filepos=filepos+3; - break; - default: break; - } - return 0; -} - - - /* routines for bit buffer */ - /* Buffer must be 6 byte bigger */ -static void init_bit_buffer(BIT_BUFF *bit_buff, char *buffer, uint length) -{ - bit_buff->pos=(uchar*) buffer; - bit_buff->end=(uchar*) buffer+length; - bit_buff->bits=bit_buff->error=0; - bit_buff->current_byte=0; /* Avoid purify errors */ -} - -static uint fill_and_get_bits(BIT_BUFF *bit_buff, uint count) -{ - uint tmp; - count-=bit_buff->bits; - tmp=(bit_buff->current_byte & mask[bit_buff->bits]) << count; - fill_buffer(bit_buff); - bit_buff->bits=BITS_SAVED - count; - return tmp+(bit_buff->current_byte >> (BITS_SAVED - count)); -} - - /* Fill in empty bit_buff->current_byte from buffer */ - /* Sets bit_buff->error if buffer is exhausted */ - -static void fill_buffer(BIT_BUFF *bit_buff) -{ - if (bit_buff->pos >= bit_buff->end) - { - bit_buff->error= 1; - bit_buff->current_byte=0; - return; - } -#if BITS_SAVED == 64 - bit_buff->current_byte= ((((uint) ((uchar) bit_buff->pos[7]))) + - (((uint) ((uchar) bit_buff->pos[6])) << 8) + - (((uint) ((uchar) bit_buff->pos[5])) << 16) + - (((uint) ((uchar) bit_buff->pos[4])) << 24) + - ((ulonglong) - ((((uint) ((uchar) bit_buff->pos[3]))) + - (((uint) ((uchar) bit_buff->pos[2])) << 8) + - (((uint) ((uchar) bit_buff->pos[1])) << 16) + - (((uint) ((uchar) bit_buff->pos[0])) << 24)) << 32)); - bit_buff->pos+=8; -#else -#if BITS_SAVED == 32 - bit_buff->current_byte= (((uint) ((uchar) bit_buff->pos[3])) + - (((uint) ((uchar) bit_buff->pos[2])) << 8) + - (((uint) ((uchar) bit_buff->pos[1])) << 16) + - (((uint) ((uchar) bit_buff->pos[0])) << 24)); - bit_buff->pos+=4; -#else - bit_buff->current_byte= (uint) (((uint) ((uchar) bit_buff->pos[1]))+ - (((uint) ((uchar) bit_buff->pos[0])) << 8)); - bit_buff->pos+=2; -#endif -#endif -} - - /* Get number of bits neaded to represent value */ - -static uint max_bit(register uint value) -{ - reg2 uint power=1; - - while ((value>>=1)) - power++; - return (power); -} - - -/***************************************************************************** - Some redefined functions to handle files when we are using memmap -*****************************************************************************/ - -#ifdef HAVE_MMAP - -#include <sys/mman.h> - -static int _nisam_read_mempack_record(N_INFO *info,ulong filepos,byte *buf); -static int _nisam_read_rnd_mempack_record(N_INFO*, byte *,ulong, int); - -#ifndef MAP_NORESERVE -#define MAP_NORESERVE 0 /* For irix */ -#endif -#ifndef MAP_FAILED -#define MAP_FAILED -1 -#endif - -my_bool _nisam_memmap_file(N_INFO *info) -{ - byte *file_map; - ISAM_SHARE *share=info->s; - DBUG_ENTER("_nisam_memmap_file"); - - if (!info->s->file_map) - { - if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) < - share->state.data_file_length+MEMMAP_EXTRA_MARGIN) - { - DBUG_PRINT("warning",("File isn't extended for memmap")); - DBUG_RETURN(0); - } - file_map=(byte*) - mmap(0,share->state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ, - MAP_SHARED | MAP_NORESERVE,info->dfile,0L); - if (file_map == (byte*) MAP_FAILED) - { - DBUG_PRINT("warning",("mmap failed: errno: %d",errno)); - my_errno=errno; - DBUG_RETURN(0); - } - info->s->file_map=file_map; - } - info->opt_flag|= MEMMAP_USED; - info->read_record=share->read_record=_nisam_read_mempack_record; - share->read_rnd=_nisam_read_rnd_mempack_record; - DBUG_RETURN(1); -} - - -void _nisam_unmap_file(N_INFO *info) -{ - if (info->s->file_map) - (void) munmap((caddr_t) info->s->file_map, - (size_t) info->s->state.data_file_length+ - MEMMAP_EXTRA_MARGIN); -} - - -static void _nisam_mempack_get_block_info(BLOCK_INFO *info, uint ref_length, - uchar *header) -{ - if (ref_length == 1) /* This is most usual */ - info->rec_len=header[0]; - else if (ref_length == 2) - info->rec_len=uint2korr(header); - else - info->rec_len=(uint) (uint3korr(header)); -} - - -static int _nisam_read_mempack_record(N_INFO *info, ulong filepos, byte *buf) -{ - BLOCK_INFO block_info; - ISAM_SHARE *share=info->s; - DBUG_ENTER("ni_read_mempack_record"); - - if (filepos == NI_POS_ERROR) - DBUG_RETURN(-1); /* _search() didn't find record */ - - _nisam_mempack_get_block_info(&block_info,share->pack.ref_length, - (uchar*) share->file_map+filepos); - DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,share->file_map+ - share->pack.ref_length+filepos, - block_info.rec_len)); -} - - -/*ARGSUSED*/ -static int _nisam_read_rnd_mempack_record(N_INFO *info, byte *buf, - register ulong filepos, - int skipp_deleted_blocks - __attribute__((unused))) -{ - BLOCK_INFO block_info; - ISAM_SHARE *share=info->s; - DBUG_ENTER("_nisam_read_rnd_mempack_record"); - - if (filepos >= share->state.data_file_length) - { - my_errno=HA_ERR_END_OF_FILE; - goto err; - } - - _nisam_mempack_get_block_info(&block_info,share->pack.ref_length, - (uchar*) share->file_map+filepos); -#ifndef DBUG_OFF - if (block_info.rec_len > info->s->max_pack_length) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - goto err; - } -#endif - info->packed_length=block_info.rec_len; - info->lastpos=filepos; - info->nextpos=filepos+share->pack.ref_length+block_info.rec_len; - info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; - - DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,share->file_map+ - share->pack.ref_length+filepos, - block_info.rec_len)); -err: - DBUG_RETURN(-1); -} - -#endif /* HAVE_MMAP */ diff --git a/isam/_page.c b/isam/_page.c deleted file mode 100644 index e31115e624f..00000000000 --- a/isam/_page.c +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* L{ser och skriver nyckelblock */ - -#include "isamdef.h" -#ifdef __WIN__ -#include <errno.h> -#endif - - /* Fetch a key-page in memory */ - -uchar *_nisam_fetch_keypage(register N_INFO *info, N_KEYDEF *keyinfo, - my_off_t page, uchar *buff, int return_buffer) -{ - uchar *tmp; - tmp=(uchar*) key_cache_read(dflt_key_cache, - info->s->kfile,page,DFLT_INIT_HITS,(byte*) buff, - (uint) keyinfo->base.block_length, - (uint) keyinfo->base.block_length, - return_buffer); - if (tmp == info->buff) - { - info->update|=HA_STATE_BUFF_SAVED; - info->int_pos=(ulong) page; - info->buff_used=1; - } - else - { - info->update&= ~HA_STATE_BUFF_SAVED; - if (tmp) - info->int_pos=(ulong) page; - else - { - info->int_pos=NI_POS_ERROR; - DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno)); - my_errno=HA_ERR_CRASHED; - } - } - return tmp; -} /* _nisam_fetch_keypage */ - - - /* Write a key-page on disk */ - -int _nisam_write_keypage(register N_INFO *info, register N_KEYDEF *keyinfo, - my_off_t page, uchar *buff) -{ - reg3 uint length; -#ifndef QQ /* Safety check */ - if (page < info->s->base.keystart || - page+keyinfo->base.block_length > info->s->state.key_file_length || - page & (nisam_block_size-1)) - { - DBUG_PRINT("error",("Trying to write outside key region: %lu", - (long) page)); - my_errno=EINVAL; - return(-1); - } - DBUG_PRINT("page",("write page at: %lu",(long) page,buff)); - DBUG_DUMP("buff",(byte*) buff,getint(buff)); -#endif - - if ((length=keyinfo->base.block_length) > IO_SIZE*2 && - info->s->state.key_file_length != page+length) - length= ((getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1)); -#ifdef HAVE_purify - { - length=getint(buff); - bzero((byte*) buff+length,keyinfo->base.block_length-length); - length=keyinfo->base.block_length; - } -#endif - return (key_cache_write(dflt_key_cache, - info->s->kfile,page,DFLT_INIT_HITS, - (byte*) buff,length, - (uint) keyinfo->base.block_length, - (int) (info->lock_type != F_UNLCK))); -} /* nisam_write_keypage */ - - - /* Remove page from disk */ - -int _nisam_dispose(register N_INFO *info, N_KEYDEF *keyinfo, my_off_t pos) -{ - uint keynr= (uint) (keyinfo - info->s->keyinfo); - ulong old_link; /* ulong is ok here */ - DBUG_ENTER("_nisam_dispose"); - - old_link=info->s->state.key_del[keynr]; - info->s->state.key_del[keynr]=(ulong) pos; - DBUG_RETURN(key_cache_write(dflt_key_cache, - info->s->kfile,pos,DFLT_INIT_HITS, - (byte*) &old_link, - sizeof(long), - (uint) keyinfo->base.block_length, - (int) (info->lock_type != F_UNLCK))); -} /* _nisam_dispose */ - - - /* Make new page on disk */ - -ulong _nisam_new(register N_INFO *info, N_KEYDEF *keyinfo) -{ - uint keynr= (uint) (keyinfo - info->s->keyinfo); - ulong pos; - DBUG_ENTER("_nisam_new"); - - if ((pos=info->s->state.key_del[keynr]) == NI_POS_ERROR) - { - if (info->s->state.key_file_length >= info->s->base.max_key_file_length) - { - my_errno=HA_ERR_INDEX_FILE_FULL; - DBUG_RETURN(NI_POS_ERROR); - } - pos=info->s->state.key_file_length; - info->s->state.key_file_length+= keyinfo->base.block_length; - } - else - { - if (!key_cache_read(dflt_key_cache, - info->s->kfile,pos,DFLT_INIT_HITS, - (byte*) &info->s->state.key_del[keynr], - (uint) sizeof(long), - (uint) keyinfo->base.block_length,0)) - pos= NI_POS_ERROR; - } - DBUG_PRINT("exit",("Pos: %d",pos)); - DBUG_RETURN(pos); -} /* _nisam_new */ diff --git a/isam/_search.c b/isam/_search.c deleted file mode 100644 index fbffd6786e1..00000000000 --- a/isam/_search.c +++ /dev/null @@ -1,889 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* S|ker efter positionen f|r en nyckel samt d{rmedh|rande funktioner */ - -#include "isamdef.h" -#include "m_ctype.h" - -#define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1) - - /* Check index */ - -int _nisam_check_index(N_INFO *info, int inx) -{ - if (inx == -1) /* Use last index */ - inx=info->lastinx; - if (inx >= (int) info->s->state.keys || inx < 0) - { - my_errno=HA_ERR_WRONG_INDEX; - return -1; - } - if (info->lastinx != inx) /* Index changed */ - { - info->lastinx = inx; - info->lastpos = NI_POS_ERROR; - info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) | - HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND); - } - if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache)) - return(-1); - return(inx); -} /* ni_check_index */ - - - /* S|ker reda p} positionen f|r ett record p} basen av en nyckel */ - /* Positionen l{ggs i info->lastpos */ - /* Returns -1 if not found and 1 if search at upper levels */ - -int _nisam_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, uint key_len, uint nextflag, register ulong pos) -{ - int error,flag; - uint nod_flag; - uchar *keypos,*maxpos; - uchar lastkey[N_MAX_KEY_BUFF],*buff; - DBUG_ENTER("_nisam_search"); - DBUG_PRINT("enter",("pos: %ld nextflag: %d lastpos: %ld", - pos,nextflag,info->lastpos)); - - if (pos == NI_POS_ERROR) - { - my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */ - info->lastpos= NI_POS_ERROR; - if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST))) - DBUG_RETURN(-1); /* Not found ; return error */ - DBUG_RETURN(1); /* Search at upper levels */ - } - - if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff, - test(!(nextflag & SEARCH_SAVE_BUFF))))) - goto err; - DBUG_DUMP("page",(byte*) buff,getint(buff)); - - flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag, - &keypos,lastkey); - nod_flag=test_if_nod(buff); - maxpos=buff+getint(buff)-1; - - if (flag) - { - if ((error=_nisam_search(info,keyinfo,key,key_len,nextflag, - _nisam_kpos(nod_flag,keypos))) <= 0) - DBUG_RETURN(error); - - if (flag >0) - { - if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && - keypos == buff+2+nod_flag) - DBUG_RETURN(1); /* Bigger than key */ - } - else if (nextflag & SEARCH_BIGGER && keypos >= maxpos) - DBUG_RETURN(1); /* Smaller than key */ - } - else - { - if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME) - || key_len) && nod_flag) - { - if ((error=_nisam_search(info,keyinfo,key,key_len,SEARCH_FIND, - _nisam_kpos(nod_flag,keypos))) >= 0 || - my_errno != HA_ERR_KEY_NOT_FOUND) - DBUG_RETURN(error); - info->int_pos= NI_POS_ERROR; /* Buffer not in memory */ - } - } - if (pos != info->int_pos) - { - uchar *old_buff=buff; - if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff, - test(!(nextflag & SEARCH_SAVE_BUFF))))) - goto err; - keypos=buff+(keypos-old_buff); - maxpos=buff+(maxpos-old_buff); - } - - if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0) - { - keypos=_nisam_get_last_key(info,keyinfo,buff,lastkey,keypos); - if (!(nextflag & SEARCH_SMALLER) && - _nisam_key_cmp(keyinfo->seg, lastkey, key, key_len, SEARCH_FIND)) - { - my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */ - goto err; - } - } - - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey)); - VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey)); - info->lastpos=_nisam_dpos(info,nod_flag,keypos); - info->int_keypos=info->buff+ (keypos-buff); - info->int_maxpos=info->buff+ (maxpos-buff); - info->page_changed=0; - info->buff_used= (info->buff != buff); - info->last_search_keypage=info->int_pos; - - DBUG_PRINT("exit",("found key at %ld",info->lastpos)); - DBUG_RETURN(0); -err: - DBUG_PRINT("exit",("Error: %d",my_errno)); - info->lastpos= NI_POS_ERROR; - DBUG_RETURN (-1); -} /* _nisam_search */ - - - /* Search after key in page-block */ - /* If packed key puts smaller or identical key in buff */ - /* ret_pos point to where find or bigger key starts */ - /* ARGSUSED */ - -int _nisam_bin_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, - uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, - uchar *buff __attribute__((unused))) -{ - reg4 int start,mid,end; - int flag; - uint totlength,nod_flag; - DBUG_ENTER("_nisam_bin_search"); - - LINT_INIT(flag); - totlength=keyinfo->base.keylength+(nod_flag=test_if_nod(page)); - start=0; mid=1; - end= (int) ((getint(page)-2-nod_flag)/totlength-1); - DBUG_PRINT("test",("getint: %d end: %d",getint(page),end)); - page+=2+nod_flag; - - while (start != end) - { - mid= (start+end)/2; - if ((flag=_nisam_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len, - comp_flag)) - >= 0) - end=mid; - else - start=mid+1; - } - if (mid != start) - flag=_nisam_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len, - comp_flag); - if (flag < 0) - start++; /* point at next, bigger key */ - *ret_pos=page+(uint) start*totlength; - DBUG_PRINT("exit",("flag: %d keypos: %d",flag,start)); - DBUG_RETURN(flag); -} /* _nisam_bin_search */ - - - /* Used instead of _nisam_bin_search() when key is packed */ - /* Puts smaller or identical key in buff */ - /* Key is searched sequentially */ - -int _nisam_seq_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff) -{ - int flag; - uint nod_flag,length; - uchar t_buff[N_MAX_KEY_BUFF],*end; - DBUG_ENTER("_nisam_seq_search"); - - LINT_INIT(flag); LINT_INIT(length); - end= page+getint(page); - nod_flag=test_if_nod(page); - page+=2+nod_flag; - *ret_pos=page; - while (page < end) - { - length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff); - if ((flag=_nisam_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag)) >= 0) - break; -#ifdef EXTRA_DEBUG - DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d",page,t_buff,flag)); -#endif - memcpy(buff,t_buff,length); - *ret_pos=page; - } - if (flag == 0) - memcpy(buff,t_buff,length); /* Result is first key */ - DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos)); - DBUG_RETURN(flag); -} /* _nisam_seq_search */ - - - /* Get pos to a key_block */ - -ulong _nisam_kpos(uint nod_flag, uchar *after_key) -{ - after_key-=nod_flag; - switch (nod_flag) { - case 3: - return uint3korr(after_key)*512L; - case 2: - return uint2korr(after_key)*512L; - case 1: - return (uint) (*after_key)*512L; - case 0: /* At leaf page */ - default: /* Impossible */ - return(NI_POS_ERROR); - } -} /* _kpos */ - - - /* Save pos to a key_block */ - -void _nisam_kpointer(register N_INFO *info, register uchar *buff, ulong pos) -{ - pos/=512L; - switch (info->s->base.key_reflength) { - case 3: int3store(buff,pos); break; - case 2: int2store(buff,(uint) pos); break; - case 1: buff[0]= (uchar) pos; break; - default: abort(); /* impossible */ - } -} /* _nisam_kpointer */ - - - /* Calc pos to a data-record */ - -ulong _nisam_dpos(N_INFO *info, uint nod_flag, uchar *after_key) -{ - ulong pos; - after_key-=(nod_flag + info->s->rec_reflength); - switch (info->s->rec_reflength) { - case 4: - pos= (ulong) uint4korr(after_key); - break; - case 3: - pos= (ulong) uint3korr(after_key); - break; - case 2: - pos= (ulong) uint2korr(after_key); - break; - default: - pos=0L; /* Shut compiler up */ - } - return (info->s->base.options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos : - pos*info->s->base.reclength; -} - - /* save pos to record */ - -void _nisam_dpointer(N_INFO *info, uchar *buff, ulong pos) -{ - if (!(info->s->base.options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) - pos/=info->s->base.reclength; - - switch (info->s->rec_reflength) { - case 4: int4store(buff,pos); break; - case 3: int3store(buff,pos); break; - case 2: int2store(buff,(uint) pos); break; - default: abort(); /* Impossible */ - } -} /* _nisam_dpointer */ - - - /* - ** Compare two keys with is bigger - ** Returns <0, 0, >0 acording to with is bigger - ** Key_length specifies length of key to use. Number-keys can't - ** be splitted - ** If flag <> SEARCH_FIND compare also position - */ -int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar *b, uint key_length, uint nextflag) -{ - reg4 int flag,length_diff; - int16 s_1,s_2; - int32 l_1,l_2; - uint32 u_1,u_2; - float f_1,f_2; - double d_1,d_2; - reg5 uchar *end; - - if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)) - || key_length == 0) - key_length=N_MAX_KEY_BUFF*2; - - for ( ; (int) key_length >0 ; key_length-= (keyseg++)->base.length) - { - end= a+ min(keyseg->base.length,key_length); - switch ((enum ha_base_keytype) keyseg->base.type) { - case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */ - case HA_KEYTYPE_BINARY: - if (keyseg->base.flag & HA_SPACE_PACK) - { - uchar *as, *bs; - int length,b_length; - - as=a++; bs=b++; - length= (length_diff= ((int) *as - (b_length= (int) *bs))) < 0 ? - (int) *as : b_length; - end= a+ min(key_length,(uint) length); - - if (use_strnxfrm(default_charset_info)) { - if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY) - { - while (a < end) - if ((flag= (int) *a++ - (int) *b++)) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - } - else - { - if ((flag = my_strnncoll(default_charset_info, - a, (int) (end-a), b, b_length))) - return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag; - b+= (uint) (end-a); - a=end; - } - } - else - { - while (a < end) - if ((flag= (int) *a++ - (int) *b++)) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - } - if (key_length < (uint) keyseg->base.length) - { /* key_part */ - if (length_diff) - { - if (length_diff < 0 || (uint) *as <= key_length) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? - -length_diff : length_diff); - for (length= (int) key_length-b_length; length-- > 0 ;) - { - if (*a++ != ' ') - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -1 : 1); - } - } - if (nextflag & SEARCH_NO_FIND) /* Find record after key */ - return (nextflag & SEARCH_BIGGER) ? -1 : 1; - return 0; - } - else - { - if (length_diff) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? - -length_diff : length_diff); - } - a=as+ (uint) *as+1 ; b= bs+ b_length+1; /* to next key */ - } - else - { - if (use_strnxfrm(default_charset_info)) { - if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY) - { - while (a < end) - if ((flag= (int) *a++ - (int) *b++)) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - } - else - { - if ((flag = my_strnncoll(default_charset_info, - a, (int) (end-a), b, (int) (end-a)))) - return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag; - b+= (uint) (end-a); - a=end; - } - } - else - { - while (a < end) - if ((flag= (int) *a++ - (int) *b++)) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - } - } - break; - case HA_KEYTYPE_INT8: - { - int i_1= (int) *((signed char*) a); - int i_2= (int) *((signed char*) b); - if ((flag = CMP(i_1,i_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b++; - break; - } - case HA_KEYTYPE_SHORT_INT: - shortget(s_1,a); - shortget(s_2,b); - if ((flag = CMP(s_1,s_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 2; /* sizeof(short int); */ - break; - case HA_KEYTYPE_USHORT_INT: - { - uint16 us_1,us_2; - ushortget(us_1,a); - ushortget(us_2,b); - if ((flag = CMP(us_1,us_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+=2; /* sizeof(short int); */ - break; - } - case HA_KEYTYPE_LONG_INT: - longget(l_1,a); - longget(l_2,b); - if ((flag = CMP(l_1,l_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 4; /* sizeof(long int); */ - break; - case HA_KEYTYPE_ULONG_INT: - ulongget(u_1,a); - ulongget(u_2,b); - if ((flag = CMP(u_1,u_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 4; /* sizeof(long int); */ - break; - case HA_KEYTYPE_INT24: - l_1=sint3korr(a); - l_2=sint3korr(b); - if ((flag = CMP(l_1,l_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 3; - break; - case HA_KEYTYPE_UINT24: - l_1=(long) uint3korr(a); - l_2=(long) uint3korr(b); - if ((flag = CMP(l_1,l_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 3; - break; - case HA_KEYTYPE_FLOAT: - bmove((byte*) &f_1,(byte*) a,(int) sizeof(float)); - bmove((byte*) &f_2,(byte*) b,(int) sizeof(float)); - if ((flag = CMP(f_1,f_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= sizeof(float); - break; - case HA_KEYTYPE_DOUBLE: - doubleget(d_1,a); - doubleget(d_2,b); - if ((flag = CMP(d_1,d_2))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= sizeof(double); - break; - case HA_KEYTYPE_NUM: /* Numeric key */ - { - int swap_flag=keyseg->base.flag & HA_REVERSE_SORT; - if (keyseg->base.flag & HA_SPACE_PACK) - { - int alength,blength; - - if (swap_flag) - swap_variables(uchar*, a, b); - alength= *a++; blength= *b++; - if ((flag=(int) (keyseg->base.length-key_length)) < 0) - flag=0; - if (alength != blength+flag) - { - if ((alength > blength+flag && *a != '-') || - (alength < blength+flag && *b == '-')) - return 1; - else - return -1; - } - if (*a == '-' && *b == '-') - { - swap_flag=1; - swap_variables(uchar*, a, b); - } - end=a+alength; - while (a < end) - if (*a++ != *b++) - { - a--; b--; - if (my_isdigit(default_charset_info, (char) *a) && - my_isdigit(default_charset_info, (char) *b)) - return ((int) *a - (int) *b); - if (*a == '-' || my_isdigit(default_charset_info,(char) *b)) - return (-1); - if (*b == '-' || *b++ == ' ' || - my_isdigit(default_charset_info,(char) *a)) - return (1); - if (*a++ == ' ') - return (-1); - } - } - else - { - for ( ; a < end && *a == ' ' && *b == ' ' ; a++, b++) ; - if (*a == '-' && *b == '-') - swap_flag=1; - if (swap_flag) - { - end=b+(int) (end-a); - swap_variables(uchar*, a, b); - } - while (a < end) - if (*a++ != *b++) - { - a--; b--; - if (my_isdigit(default_charset_info,(char) *a) && - my_isdigit(default_charset_info,(char) *b)) - return ((int) *a - (int) *b); - if (*a == '-' || my_isdigit(default_charset_info,(char) *b)) - return (-1); - if (*b == '-' || *b++ == ' ' || - my_isdigit(default_charset_info,(char) *a)) - return (1); - if (*a++ == ' ') - return -1; - } - } - if (swap_flag) - swap_variables(uchar*, a, b); - break; - } -#ifdef HAVE_LONG_LONG - case HA_KEYTYPE_LONGLONG: - { - longlong ll_a,ll_b; - longlongget(ll_a,a); - longlongget(ll_b,b); - if ((flag = CMP(ll_a,ll_b))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= sizeof(longlong); - break; - } - case HA_KEYTYPE_ULONGLONG: - { - ulonglong ll_a,ll_b; - longlongget(ll_a,a); - longlongget(ll_b,b); - if ((flag = CMP(ll_a,ll_b))) - return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= sizeof(ulonglong); - break; - } -#endif - case HA_KEYTYPE_END: /* Ready */ - case HA_KEYTYPE_VARTEXT: /* Impossible */ - case HA_KEYTYPE_VARBINARY: /* Impossible */ - goto end; - } - } -end: - if (!(nextflag & SEARCH_FIND)) - { - if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */ - return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1; - LINT_INIT(l_1); LINT_INIT(l_2); - switch (keyseg->base.length) { - case 4: - u_1= (ulong) uint4korr(a); - u_2= (ulong) uint4korr(b); - break; - case 3: - u_1= (ulong) uint3korr(a); - u_2= (ulong) uint3korr(b); - break; - case 2: - u_1= (ulong) uint2korr(a); - u_2= (ulong) uint2korr(b); - break; - default: abort(); /* Impossible */ - } - flag = CMP(u_1,u_2); - - if (nextflag & SEARCH_SAME) - return (flag); /* read same */ - if (nextflag & SEARCH_BIGGER) - return (flag <= 0 ? -1 : 1); /* read next */ - return (flag < 0 ? -1 : 1); /* read previous */ - } - return 0; -} /* _nisam_key_cmp */ - - - /* Get key from key-block */ - /* page points at previous key; its advanced to point at next key */ - /* key should contain previous key */ - /* Returns length of found key + pointers */ - /* nod_flag is a flag if we are on nod */ - -uint _nisam_get_key(register N_KEYDEF *keyinfo, uint nod_flag, - register uchar **page, register uchar *key) -{ - reg1 N_KEYSEG *keyseg; - uchar *start,*start_key; - uint length,c_length; - - LINT_INIT(start); - start_key=key; c_length=0; - for (keyseg=keyinfo->seg ; keyseg->base.type ;keyseg++) - { - if (keyseg->base.flag & (HA_SPACE_PACK | HA_PACK_KEY)) - { - start=key; - if (keyseg->base.flag & HA_SPACE_PACK) - key++; - if ((length= *(*page)++) & 128) - { - key+= (c_length=(length & 127)); - if (c_length == 0) /* Same key */ - { - key+= *start; /* Same diff_key as prev */ - length=0; - } - else - { - if (keyseg->base.flag & HA_SPACE_PACK) - length= *(*page)++; - else - length=keyseg->base.length-length+128; /* Rest of key */ - /* Prevent core dumps if wrong data formats */ - if (length > keyseg->base.length) - length=0; - } - } - } - else - length=keyseg->base.length; - memcpy((byte*) key,(byte*) *page,(size_t) length); key+=length; - if (keyseg->base.flag & HA_SPACE_PACK) - *start= (uchar) ((key-start)-1); - *page+=length; - } - length=keyseg->base.length+nod_flag; - bmove((byte*) key,(byte*) *page,length); - *page+=length; - return((uint) (key-start_key)+keyseg->base.length); -} /* _nisam_get_key */ - - - /* same as _nisam_get_key but used with fixed length keys */ - -uint _nisam_get_static_key(register N_KEYDEF *keyinfo, uint nod_flag, register uchar **page, register uchar *key) -{ - memcpy((byte*) key,(byte*) *page, - (size_t) (keyinfo->base.keylength+nod_flag)); - *page+=keyinfo->base.keylength+nod_flag; - return(keyinfo->base.keylength); -} /* _nisam_get_static_key */ - - - /* Get last key from key-block, starting from keypos */ - /* Return pointer to where keystarts */ - -uchar *_nisam_get_last_key(N_INFO *info, N_KEYDEF *keyinfo, uchar *keypos, uchar *lastkey, uchar *endpos) -{ - uint nod_flag; - uchar *lastpos; - - nod_flag=test_if_nod(keypos); - if (! (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED))) - { - lastpos=endpos-keyinfo->base.keylength-nod_flag; - if (lastpos > keypos) - bmove((byte*) lastkey,(byte*) lastpos,keyinfo->base.keylength+nod_flag); - } - else - { - lastpos=0 ; keypos+=2+nod_flag; - lastkey[0]=0; - while (keypos < endpos) - { - lastpos=keypos; - VOID(_nisam_get_key(keyinfo,nod_flag,&keypos,lastkey)); - } - } - return lastpos; -} /* _nisam_get_last_key */ - - - /* Calculate length of key */ - -uint _nisam_keylength(N_KEYDEF *keyinfo, register uchar *key) -{ - reg1 N_KEYSEG *keyseg; - uchar *start; - - if (! (keyinfo->base.flag & HA_SPACE_PACK_USED)) - return (keyinfo->base.keylength); - - start=key; - for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++) - { - if (keyseg->base.flag & HA_SPACE_PACK) - key+= *key+1; - else - key+= keyseg->base.length; - } - return((uint) (key-start)+keyseg->base.length); -} /* _nisam_keylength */ - - - /* Move a key */ - -uchar *_nisam_move_key(N_KEYDEF *keyinfo, uchar *to, uchar *from) -{ - reg1 uint length; - memcpy((byte*) to, (byte*) from, - (size_t) (length=_nisam_keylength(keyinfo,from))); - return to+length; -} - - /* Find next/previous record with same key */ - /* This can't be used when database is touched after last read */ - -int _nisam_search_next(register N_INFO *info, register N_KEYDEF *keyinfo, - uchar *key, uint nextflag, ulong pos) -{ - int error; - uint nod_flag; - uchar lastkey[N_MAX_KEY_BUFF]; - DBUG_ENTER("_nisam_search_next"); - DBUG_PRINT("enter",("nextflag: %d lastpos: %d int_keypos: %lx", - nextflag,info->lastpos,info->int_keypos)); - DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key);); - - if ((nextflag & SEARCH_BIGGER && info->int_keypos >= info->int_maxpos) || - info->int_pos == NI_POS_ERROR || info->page_changed) - DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF, - pos)); - - if (info->buff_used) - { - if (!_nisam_fetch_keypage(info,keyinfo,info->last_search_keypage, - info->buff,0)) - { - info->lastpos= NI_POS_ERROR; - DBUG_RETURN(-1); - } - info->buff_used=0; - } - - /* Last used buffer is in info->buff */ - - nod_flag=test_if_nod(info->buff); - VOID(_nisam_move_key(keyinfo,lastkey,key)); - - if (nextflag & SEARCH_BIGGER) /* Next key */ - { - ulong tmp_pos=_nisam_kpos(nod_flag,info->int_keypos); - if (tmp_pos != NI_POS_ERROR) - { - if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF, - tmp_pos)) <=0) - DBUG_RETURN(error); - } - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,lastkey)); - } - else /* Previous key */ - { - info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey, - info->int_keypos); - if (info->int_keypos == info->buff+2) - DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF, - pos)); - if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF, - _nisam_kpos(nod_flag,info->int_keypos))) <= 0) - DBUG_RETURN(error); - } - - info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey, - info->int_keypos); - VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey)); - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,info->lastkey)); - info->lastpos=_nisam_dpos(info,nod_flag,info->int_keypos); - DBUG_PRINT("exit",("found key at %d",info->lastpos)); - DBUG_RETURN(0); -} /* _nisam_search_next */ - - - /* S|ker reda p} positionen f|r f|rsta recordet i ett index */ - /* Positionen l{ggs i info->lastpos */ - -int _nisam_search_first(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos) -{ - uint nod_flag; - uchar *page; - DBUG_ENTER("_nisam_search_first"); - - if (pos == NI_POS_ERROR) - { - my_errno=HA_ERR_KEY_NOT_FOUND; - info->lastpos= NI_POS_ERROR; - DBUG_RETURN(-1); - } - - do - { - if (!_nisam_fetch_keypage(info,keyinfo,pos,info->buff,0)) - { - info->lastpos= NI_POS_ERROR; - DBUG_RETURN(-1); - } - nod_flag=test_if_nod(info->buff); - page=info->buff+2+nod_flag; - } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR); - - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,info->lastkey)); - info->int_keypos=page; info->int_maxpos=info->buff+getint(info->buff)-1; - info->lastpos=_nisam_dpos(info,nod_flag,page); - info->page_changed=info->buff_used=0; - info->last_search_keypage=info->int_pos; - - DBUG_PRINT("exit",("found key at %d",info->lastpos)); - DBUG_RETURN(0); -} /* _nisam_search_first */ - - - /* S|ker reda p} positionen f|r sista recordet i ett index */ - /* Positionen l{ggs i info->lastpos */ - -int _nisam_search_last(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos) -{ - uint nod_flag; - uchar *buff,*page; - DBUG_ENTER("_nisam_search_last"); - - if (pos == NI_POS_ERROR) - { - my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */ - info->lastpos= NI_POS_ERROR; - DBUG_RETURN(-1); - } - - buff=info->buff; - do - { - if (!_nisam_fetch_keypage(info,keyinfo,pos,buff,0)) - { - info->lastpos= NI_POS_ERROR; - DBUG_RETURN(-1); - } - page= buff+getint(buff); - nod_flag=test_if_nod(buff); - } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR); - - VOID(_nisam_get_last_key(info,keyinfo,buff,info->lastkey,page)); - info->lastpos=_nisam_dpos(info,nod_flag,page); - info->int_keypos=info->int_maxpos=page; - info->page_changed=info->buff_used=0; - info->last_search_keypage=info->int_pos; - - DBUG_PRINT("exit",("found key at %d",info->lastpos)); - DBUG_RETURN(0); -} /* _nisam_search_last */ diff --git a/isam/_statrec.c b/isam/_statrec.c deleted file mode 100644 index 9dbc948440f..00000000000 --- a/isam/_statrec.c +++ /dev/null @@ -1,265 +0,0 @@ -/* Copyright (C) 2000 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 */ - - /* Functions to handle fixed-length-records */ - -#include "isamdef.h" - - -int _nisam_write_static_record(N_INFO *info, const byte *record) -{ - uchar temp[4]; /* Not sizeof(long) */ - - if (info->s->state.dellink != NI_POS_ERROR) - { - ulong filepos=info->s->state.dellink; - info->rec_cache.seek_not_done=1; /* We have done a seek */ - VOID(my_seek(info->dfile,info->s->state.dellink+1,MY_SEEK_SET,MYF(0))); - - if (my_read(info->dfile,(char*) &temp[0],sizeof(temp), MYF(MY_NABP))) - goto err; - info->s->state.dellink=uint4korr(temp); - if (info->s->state.dellink == (uint32) ~0) /* Fix for 64 bit long */ - info->s->state.dellink=NI_POS_ERROR; - info->s->state.del--; - info->s->state.empty-=info->s->base.reclength; - VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); - if (my_write(info->dfile, (char*) record, info->s->base.reclength, - MYF(MY_NABP))) - goto err; - } - else - { - if (info->s->state.data_file_length > info->s->base.max_data_file_length) - { - my_errno=HA_ERR_RECORD_FILE_FULL; - return(2); - } - if (info->opt_flag & WRITE_CACHE_USED) - { /* Cash in use */ - if (my_b_write(&info->rec_cache, (byte*) record, info->s->base.reclength)) - goto err; - } - else - { - info->rec_cache.seek_not_done=1; /* We have done a seek */ - VOID(my_seek(info->dfile,info->s->state.data_file_length, - MY_SEEK_SET,MYF(0))); - if (my_write(info->dfile,(char*) record,info->s->base.reclength, - MYF(MY_NABP | MY_WAIT_IF_FULL))) - goto err; - } - info->s->state.data_file_length+=info->s->base.reclength; - info->s->state.splitt++; - } - return 0; - err: - return 1; -} - -int _nisam_update_static_record(N_INFO *info, ulong pos, const byte *record) -{ - info->rec_cache.seek_not_done=1; /* We have done a seek */ - VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0))); - return (my_write(info->dfile,(char*) record,info->s->base.reclength, - MYF(MY_NABP)) != 0); -} - - -int _nisam_delete_static_record(N_INFO *info) -{ - uchar temp[5]; /* 1+sizeof(uint32) */ - - info->s->state.del++; - info->s->state.empty+=info->s->base.reclength; - temp[0]= '\0'; /* Mark that record is deleted */ - int4store(temp+1,info->s->state.dellink); - info->s->state.dellink = info->lastpos; - info->rec_cache.seek_not_done=1; - VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0))); - return (my_write(info->dfile,(byte*) temp,(uint) sizeof(temp), - MYF(MY_NABP)) != 0); -} - - -int _nisam_cmp_static_record(register N_INFO *info, register const byte *old) -{ - DBUG_ENTER("_nisam_rectest"); - - /* We are going to do changes; dont let anybody disturb */ - dont_break(); /* Dont allow SIGHUP or SIGINT */ - - if (info->opt_flag & WRITE_CACHE_USED) - { - if (flush_io_cache(&info->rec_cache)) - { - DBUG_RETURN(-1); - } - info->rec_cache.seek_not_done=1; /* We have done a seek */ - } - - if ((info->opt_flag & READ_CHECK_USED)) - { /* If check isn't disabled */ - info->rec_cache.seek_not_done=1; /* We have done a seek */ - VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0))); - if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength, - MYF(MY_NABP))) - DBUG_RETURN(-1); - if (memcmp((byte*) info->rec_buff, (byte*) old, - (uint) info->s->base.reclength)) - { - DBUG_DUMP("read",old,info->s->base.reclength); - DBUG_DUMP("disk",info->rec_buff,info->s->base.reclength); - my_errno=HA_ERR_RECORD_CHANGED; /* Record have changed */ - DBUG_RETURN(1); - } - } - DBUG_RETURN(0); -} - - /* Read a fixed-length-record */ - /* Returns 0 if Ok. */ - /* 1 if record is deleted */ - /* MY_FILE_ERROR on read-error or locking-error */ - -int _nisam_read_static_record(register N_INFO *info, register ulong pos, - register byte *record) -{ - int error; - - if (pos != NI_POS_ERROR) - { - if (info->opt_flag & WRITE_CACHE_USED && - info->rec_cache.pos_in_file <= pos && - flush_io_cache(&info->rec_cache)) - return(-1); - info->rec_cache.seek_not_done=1; /* We have done a seek */ - - error=my_pread(info->dfile,(char*) record,info->s->base.reclength, - pos,MYF(MY_NABP)) != 0; - if (info->s->r_locks == 0 && info->s->w_locks == 0) - VOID(_nisam_writeinfo(info,0)); - if (! error) - { - if (!*record) return(1); /* Record is deleted */ - info->update|= HA_STATE_AKTIV; /* Record is read */ - my_errno=HA_ERR_RECORD_DELETED; - return(0); - } - return(-1); /* Error on read */ - } - VOID(_nisam_writeinfo(info,0)); /* No such record */ - return(-1); -} /* _nisam_read_record */ - - -int _nisam_read_rnd_static_record(N_INFO *info, byte *buf, - register ulong filepos, - int skipp_deleted_blocks) -{ - int locked,error,cache_read; - uint cache_length; - ISAM_SHARE *share=info->s; - DBUG_ENTER("_nisam_read_rnd_static_record"); - - cache_read=0; - LINT_INIT(cache_length); - if (info->opt_flag & WRITE_CACHE_USED && - (info->rec_cache.pos_in_file <= filepos || skipp_deleted_blocks) && - flush_io_cache(&info->rec_cache)) - DBUG_RETURN(-1); - if (info->opt_flag & READ_CACHE_USED) - { /* Cash in use */ - if (filepos == my_b_tell(&info->rec_cache) && - (skipp_deleted_blocks || !filepos)) - { - cache_read=1; /* Read record using cache */ - cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos); - } - else - info->rec_cache.seek_not_done=1; /* Filepos is changed */ - } -#ifndef NO_LOCKING - locked=0; - if (info->lock_type == F_UNLCK) - { - if (filepos >= share->state.data_file_length) - { /* Test if new records */ - if (_nisam_readinfo(info,F_RDLCK,0)) - DBUG_RETURN(-1); - locked=1; - } - else - { /* We don't nead new info */ -#ifndef UNSAFE_LOCKING - if ((! cache_read || share->base.reclength > cache_length) && - share->r_locks == 0 && share->w_locks == 0) - { /* record not in cache */ - if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF, - MYF(MY_SEEK_NOT_DONE) | info->lock_wait)) - DBUG_RETURN(-1); - locked=1; - } -#else - info->tmp_lock_type=F_RDLCK; -#endif - } - } -#endif - if (filepos >= share->state.data_file_length) - { -#ifndef NO_LOCKING - DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld", - filepos/share->base.reclength,filepos, - share->state.records, share->state.del)); - VOID(_nisam_writeinfo(info,0)); -#endif - my_errno=HA_ERR_END_OF_FILE; - DBUG_RETURN(-1); - } - info->lastpos= filepos; - info->nextpos= filepos+share->base.reclength; - - if (! cache_read) /* No cacheing */ - { - error=_nisam_read_static_record(info,filepos,buf); - if (error > 0) - my_errno=HA_ERR_RECORD_DELETED; - DBUG_RETURN(error); - } - - /* Read record with cacheing */ - error=my_b_read(&info->rec_cache,(byte*) buf,share->base.reclength); - -#ifndef NO_LOCKING - if (locked) - VOID(_nisam_writeinfo(info,0)); /* Unlock keyfile */ -#endif - if (!error) - { - if (!buf[0]) - { /* Record is removed */ - my_errno=HA_ERR_RECORD_DELETED; - DBUG_RETURN(1); - } - /* Found and may be updated */ - info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; - DBUG_RETURN(0); - } - if (info->rec_cache.error != -1 || my_errno == 0) - my_errno=HA_ERR_WRONG_IN_RECORD; - DBUG_RETURN(-1); /* Something wrong (EOF?) */ -} diff --git a/isam/changed.c b/isam/changed.c deleted file mode 100644 index b8132538b86..00000000000 --- a/isam/changed.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Check if somebody has changed table since last check. */ - -#include "isamdef.h" - - /* Return 0 if table isn't changed */ - -int nisam_is_changed(N_INFO *info) -{ - int result; - DBUG_ENTER("nisam_is_changed"); -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1); - VOID(_nisam_writeinfo(info,0)); -#endif - result=(int) info->data_changed; - info->data_changed=0; - DBUG_PRINT("exit",("result: %d",result)); - DBUG_RETURN(result); -} diff --git a/isam/close.c b/isam/close.c deleted file mode 100644 index 37425653a5d..00000000000 --- a/isam/close.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* close a isam-database */ - -#include "isamdef.h" - -int nisam_close(register N_INFO *info) -{ - int error=0,flag; - ISAM_SHARE *share=info->s; - DBUG_ENTER("nisam_close"); - DBUG_PRINT("enter",("base: %lx reopen: %u locks: %u", - info,(uint) share->reopen, - (uint) (share->w_locks+share->r_locks))); - - pthread_mutex_lock(&THR_LOCK_isam); - if (info->lock_type == F_EXTRA_LCK) - info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */ - -#ifndef NO_LOCKING - if (info->lock_type != F_UNLCK) - VOID(nisam_lock_database(info,F_UNLCK)); -#else - info->lock_type=F_UNLCK; - share->w_locks--; - if (_nisam_writeinfo(info,test(share->changed))) - error=my_errno; -#endif - pthread_mutex_lock(&share->intern_lock); - - if (share->base.options & HA_OPTION_READ_ONLY_DATA) - share->r_locks--; - if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) - { - if (end_io_cache(&info->rec_cache)) - error=my_errno; - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - } - flag= !--share->reopen; - nisam_open_list=list_delete(nisam_open_list,&info->open_list); - pthread_mutex_unlock(&share->intern_lock); - - if (flag) - { - if (share->kfile >= 0 && - flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE)) - error=my_errno; - if (share->kfile >= 0 && my_close(share->kfile,MYF(0))) - error = my_errno; -#ifdef HAVE_MMAP - _nisam_unmap_file(info); -#endif - if (share->decode_trees) - { - my_free((gptr) share->decode_trees,MYF(0)); - my_free((gptr) share->decode_tables,MYF(0)); - } -#ifdef THREAD - thr_lock_delete(&share->lock); - VOID(pthread_mutex_destroy(&share->intern_lock)); -#endif - my_free((gptr) info->s,MYF(0)); - } - pthread_mutex_unlock(&THR_LOCK_isam); - if (info->dfile >= 0 && my_close(info->dfile,MYF(0))) - error = my_errno; - - nisam_log_command(LOG_CLOSE,info,NULL,0,error); - my_free((gptr) info->rec_alloc,MYF(0)); - my_free((gptr) info,MYF(0)); - - if (error) - { - my_errno=error; - DBUG_RETURN(-1); - } - DBUG_RETURN(0); -} /* nisam_close */ diff --git a/isam/create.c b/isam/create.c deleted file mode 100644 index 4c23f3edd11..00000000000 --- a/isam/create.c +++ /dev/null @@ -1,328 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Skapar en isam-databas */ - -#include "isamdef.h" -#if defined(MSDOS) || defined(__WIN__) -#ifdef __WIN__ -#include <fcntl.h> -#else -#include <process.h> /* Prototype for getpid */ -#endif -#endif - - /* - ** Old options is used when recreating database, from isamchk - ** Note that the minimun reclength that MySQL allows for static rows - ** are 5. (Will be fixed in the next generation) - */ - -int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo, - N_RECINFO *recinfo, - ulong records,ulong reloc, uint flags,uint old_options, - ulong data_file_length) -{ - register uint i,j; - File dfile,file; - int errpos,save_errno; - uint fields,length,max_key_length,packed,pointer,reclength,min_pack_length, - key_length,info_length,key_segs,options,min_key_length_skipp,max_block, - base_pos; - char buff[max(FN_REFLEN,512)]; - ulong tot_length,pack_reclength; - enum en_fieldtype type; - ISAM_SHARE share; - N_KEYDEF *keydef; - N_KEYSEG *keyseg; - N_RECINFO *rec; - DBUG_ENTER("nisam_create"); - - LINT_INIT(dfile); - pthread_mutex_lock(&THR_LOCK_isam); - errpos=0; - options=0; - base_pos=512; /* Enough for N_STATE_INFO */ - bzero((byte*) &share,sizeof(share)); - if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0, - O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) - goto err; - errpos=1; - VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4)); - if (!(flags & HA_DONT_TOUCH_DATA)) - { - if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) - goto err; - errpos=2; - } - else if (!(old_options & HA_OPTION_TEMP_COMPRESS_RECORD)) - options=old_options & (HA_OPTION_COMPRESS_RECORD | - HA_OPTION_READ_ONLY_DATA | HA_OPTION_PACK_RECORD); - if (reloc > records) - reloc=records; /* Check if wrong parameter */ - - /* Start by checking fields and field-types used */ - reclength=0; - for (rec=recinfo, fields=packed=min_pack_length=0, pack_reclength=0L; - rec->base.type != (int) FIELD_LAST; - rec++,fields++) - { - reclength+=rec->base.length; - if ((type=(enum en_fieldtype) rec->base.type)) - { - packed++; - if (type == FIELD_BLOB) - { - share.base.blobs++; - rec->base.length-= sizeof(char*); /* Don't calc pointer */ - if (pack_reclength != NI_POS_ERROR) - { - if (rec->base.length == 4) - pack_reclength= (ulong) NI_POS_ERROR; - else - pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8)); - } - } - else if (type == FIELD_SKIP_PRESPACE || - type == FIELD_SKIP_ENDSPACE) - { - if (pack_reclength != NI_POS_ERROR) - pack_reclength+= rec->base.length > 255 ? 2 : 1; - min_pack_length++; - } - else if (type == FIELD_ZERO) - packed--; - else if (type != FIELD_SKIP_ZERO) - { - min_pack_length+=rec->base.length; - packed--; /* Not a pack record type */ - } - } - else - min_pack_length+=rec->base.length; - } - if ((packed & 7) == 1) - { /* Bad packing, try to remove a zero-field */ - while (rec != recinfo) - { - rec--; - if (rec->base.type == (int) FIELD_SKIP_ZERO && rec->base.length == 1) - { - rec->base.type=(int) FIELD_NORMAL; - packed--; - min_pack_length++; - break; - } - } - } - if (packed && !(options & HA_OPTION_COMPRESS_RECORD)) - options|=HA_OPTION_PACK_RECORD; /* Must use packed records */ - - packed=(packed+7)/8; - if (pack_reclength != NI_POS_ERROR) - pack_reclength+= reclength+packed; - min_pack_length+=packed; - - if (options & HA_OPTION_COMPRESS_RECORD) - { - if (data_file_length >= (1L << 24)) - pointer=4; - else if (data_file_length >= (1L << 16)) - pointer=3; - else - pointer=2; - } - else if (((records == 0L && pack_reclength < 255) || - options & HA_OPTION_PACK_RECORD) || - records >= (ulong) 16000000L || - pack_reclength == (ulong) NI_POS_ERROR || - ((options & HA_OPTION_PACK_RECORD) && - pack_reclength+4 >= (ulong) 14000000L/records)) - pointer=4; - else if (records == 0L || records >= (ulong) 65000L || - ((options & HA_OPTION_PACK_RECORD) && - pack_reclength+4 >= (ulong) 60000L/records)) - pointer=3; - else - pointer=2; - - max_block=max_key_length=0; tot_length=key_segs=0; - for (i=0, keydef=keyinfo ; i < keys ; i++ , keydef++) - { - share.state.key_root[i]= share.state.key_del[i]= NI_POS_ERROR; - share.base.rec_per_key[i]= (keydef->base.flag & HA_NOSAME) ? 1L : 0L; - min_key_length_skipp=length=0; - key_length=pointer; - - if (keydef->base.flag & HA_PACK_KEY && - keydef->seg[0].base.length > 127) - keydef->base.flag&= ~HA_PACK_KEY; /* Can't pack long keys */ - if (keydef->base.flag & HA_PACK_KEY) - { - if ((keydef->seg[0].base.flag & HA_SPACE_PACK) && - keydef->seg[0].base.type == (int) HA_KEYTYPE_NUM) - keydef->seg[0].base.flag&= ~HA_SPACE_PACK; - if (!(keydef->seg[0].base.flag & HA_SPACE_PACK)) - length++; - keydef->seg[0].base.flag|=HA_PACK_KEY; /* for easyer intern test */ - options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ - if (!(keydef->seg[0].base.flag & HA_SPACE_PACK)) - min_key_length_skipp+=keydef->seg[0].base.length; - } - keydef->base.keysegs=0; - for (keyseg=keydef->seg ; keyseg->base.type ; keyseg++) - { - keydef->base.keysegs++; - if (keyseg->base.length > 127) - keyseg->base.flag&= ~(HA_SPACE_PACK | HA_PACK_KEY); - if (keyseg->base.flag & HA_SPACE_PACK) - { - keydef->base.flag |= HA_SPACE_PACK_USED; - options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ - length++; - min_key_length_skipp+=keyseg->base.length; - } - key_length+= keyseg->base.length; - } - bzero((gptr) keyseg,sizeof(keyseg[0])); - keyseg->base.length=(uint16) pointer; /* Last key part is pointer */ - key_segs+=keydef->base.keysegs; - length+=key_length; - keydef->base.block_length=nisam_block_size; - keydef->base.keylength= (uint16) key_length; - keydef->base.minlength= (uint16) (length-min_key_length_skipp); - keydef->base.maxlength= (uint16) length; - - if ((uint) keydef->base.block_length > max_block) - max_block=(uint) keydef->base.block_length; - if (length > max_key_length) - max_key_length= length; - tot_length+= (records/(ulong) (((uint) keydef->base.block_length-5)/ - (length*2)))* - (ulong) keydef->base.block_length; - } - info_length=(uint) (base_pos+sizeof(N_BASE_INFO)+keys*sizeof(N_SAVE_KEYDEF)+ - (keys+key_segs)*sizeof(N_SAVE_KEYSEG)+ - fields*sizeof(N_SAVE_RECINFO)); - - bmove(share.state.header.file_version,(byte*) nisam_file_magic,4); - old_options=options| (old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? - HA_OPTION_COMPRESS_RECORD | - HA_OPTION_TEMP_COMPRESS_RECORD: 0); - int2store(share.state.header.options,old_options); - int2store(share.state.header.header_length,info_length); - int2store(share.state.header.state_info_length,sizeof(N_STATE_INFO)); - int2store(share.state.header.base_info_length,sizeof(N_BASE_INFO)); - int2store(share.state.header.base_pos,base_pos); - - share.state.dellink = NI_POS_ERROR; - share.state.process= (ulong) getpid(); - share.state.uniq= (ulong) file; - share.state.loop= 0; - share.state.version= (ulong) time((time_t*) 0); - share.base.options=options; - share.base.rec_reflength=pointer; - share.base.key_reflength=((!tot_length || tot_length > 30000000L) ? 3 : - tot_length > 120000L ? 2 : 1); - share.base.keys= share.state.keys = keys; - share.base.keystart = share.state.key_file_length=MY_ALIGN(info_length, - nisam_block_size); - share.base.max_block=max_block; - share.base.max_key_length=(uint) ALIGN_SIZE(max_key_length+4); - share.base.records=records; - share.base.reloc=reloc; - share.base.reclength=reclength; - share.base.pack_reclength= - (uint) (reclength+packed-share.base.blobs*sizeof(char*)); - share.base.max_pack_length=pack_reclength; - share.base.min_pack_length=min_pack_length; - share.base.pack_bits=packed; - share.base.fields=fields; - share.base.pack_fields=packed; - share.base.sortkey= (ushort) ~0; - share.base.max_data_file_length= (pointer == 4) ? (ulong) ~0L : - (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? - (ulong) (1L << (pointer*8)) : - (pointer == 3 && reclength >= 256L) ? (ulong) NI_POS_ERROR : - ((ulong) reclength * (1L << (pointer*8))); - share.base.max_key_file_length= (share.base.key_reflength == 3 ? - NI_POS_ERROR : - (ulong) - (1L << (share.base.key_reflength*8))*512); - share.base.min_block_length= - (share.base.pack_reclength+3 < N_EXTEND_BLOCK_LENGTH && - ! share.base.blobs) ? - max(share.base.pack_reclength,N_MIN_BLOCK_LENGTH) : - N_EXTEND_BLOCK_LENGTH; - if (! (flags & HA_DONT_TOUCH_DATA)) - share.base.create_time= (long) time((time_t*) 0); - - bzero(buff,base_pos); - if (my_write(file,(char*) &share.state,sizeof(N_STATE_INFO),MYF(MY_NABP)) || - my_write(file,buff,base_pos-sizeof(N_STATE_INFO),MYF(MY_NABP)) || - my_write(file,(char*) &share.base,sizeof(N_BASE_INFO),MYF(MY_NABP))) - goto err; - - for (i=0 ; i < share.base.keys ; i++) - { - if (my_write(file,(char*) &keyinfo[i].base,sizeof(N_SAVE_KEYDEF), - MYF(MY_NABP))) - goto err; - for (j=0 ; j <= keyinfo[i].base.keysegs ; j++) - { - if (my_write(file,(char*) &keyinfo[i].seg[j].base,sizeof(N_SAVE_KEYSEG), - MYF(MY_NABP))) - goto err; - } - } - for (i=0 ; i < share.base.fields ; i++) - if (my_write(file,(char*) &recinfo[i].base, (uint) sizeof(N_SAVE_RECINFO), - MYF(MY_NABP))) - goto err; - - /* Enlarge files */ - if (my_chsize(file, (ulong) share.base.keystart, 0, MYF(0))) - goto err; - - if (! (flags & HA_DONT_TOUCH_DATA)) - { -#ifdef USE_RELOC - if (my_chsize(dfile, share.base.min_pack_length*reloc, 0, MYF(0))) - goto err; -#endif - errpos=1; - if (my_close(dfile,MYF(0))) - goto err; - } - errpos=0; - pthread_mutex_unlock(&THR_LOCK_isam); - if (my_close(file,MYF(0))) - goto err; - DBUG_RETURN(0); - -err: - pthread_mutex_unlock(&THR_LOCK_isam); - save_errno=my_errno; - switch (errpos) { - case 2: - VOID(my_close(dfile,MYF(0))); - /* fall through */ - case 1: - VOID(my_close(file,MYF(0))); - } - my_errno=save_errno; /* R{tt felkod tillbaka */ - DBUG_RETURN(-1); -} /* nisam_create */ diff --git a/isam/delete.c b/isam/delete.c deleted file mode 100644 index 5aa542561c1..00000000000 --- a/isam/delete.c +++ /dev/null @@ -1,615 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Tar bort ett record fr}n en isam-databas */ - -#include "isamdef.h" -#ifdef __WIN__ -#include <errno.h> -#endif -#include <assert.h> - -static int d_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,ulong page, - uchar *anc_buff); -static int del(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uchar *anc_buff, - ulong leaf_page,uchar *leaf_buff,uchar *keypos, - ulong next_block,uchar *ret_key); -static int underflow(N_INFO *info,N_KEYDEF *keyinfo,uchar *anc_buff, - ulong leaf_page, uchar *leaf_buff,uchar *keypos); -static uint remove_key(N_KEYDEF *keyinfo,uint nod_flag,uchar *keypos, - uchar *lastkey,uchar *page_end); - - -int nisam_delete(N_INFO *info,const byte *record) -{ - uint i; - uchar *old_key; - int save_errno; - uint32 lastpos; - ISAM_SHARE *share=info->s; - DBUG_ENTER("nisam_delete"); - - /* Test if record is in datafile */ - - if (!(info->update & HA_STATE_AKTIV)) - { - my_errno=HA_ERR_KEY_NOT_FOUND; /* No database read */ - DBUG_RETURN(-1); - } - if (share->base.options & HA_OPTION_READ_ONLY_DATA) - { - my_errno=EACCES; - DBUG_RETURN(-1); - } -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1); -#endif - if ((*share->compare_record)(info,record)) - goto err; /* Fel vid kontroll-l{sning */ - - /* Remove all keys from the .ISAM file */ - - old_key=info->lastkey+share->base.max_key_length; - for (i=0 ; i < share->state.keys ; i++ ) - { - VOID(_nisam_make_key(info,i,old_key,record,info->lastpos)); - if (_nisam_ck_delete(info,i,old_key)) goto err; - } - - if ((*share->delete_record)(info)) - goto err; /* Remove record from database */ - - info->update= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_DELETED; - share->state.records--; - - lastpos= (uint32) info->lastpos; - nisam_log_command(LOG_DELETE,info,(byte*) &lastpos,sizeof(lastpos),0); - VOID(_nisam_writeinfo(info,1)); - allow_break(); /* Allow SIGHUP & SIGINT */ - DBUG_RETURN(0); - -err: - save_errno=my_errno; - lastpos= (uint32) info->lastpos; - nisam_log_command(LOG_DELETE,info,(byte*) &lastpos, sizeof(lastpos),0); - VOID(_nisam_writeinfo(info,1)); - info->update|=HA_STATE_WRITTEN; /* Buffer changed */ - allow_break(); /* Allow SIGHUP & SIGINT */ - my_errno=save_errno; - if (save_errno == HA_ERR_KEY_NOT_FOUND) - my_errno=HA_ERR_CRASHED; - - DBUG_RETURN(-1); -} /* nisam_delete */ - - - /* Tar bort en nyckel till isam-nyckelfilen */ - -int _nisam_ck_delete(register N_INFO *info, uint keynr, uchar *key) -{ - int error; - uint nod_flag; - ulong old_root; - uchar *root_buff; - N_KEYDEF *keyinfo; - DBUG_ENTER("_nisam_ck_delete"); - - if ((old_root=info->s->state.key_root[keynr]) == NI_POS_ERROR) - { - my_errno=HA_ERR_CRASHED; - DBUG_RETURN(-1); - } - keyinfo=info->s->keyinfo+keynr; - if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+ - N_MAX_KEY_BUFF*2))) - DBUG_RETURN(-1); - if (!_nisam_fetch_keypage(info,keyinfo,old_root,root_buff,0)) - { - error= -1; - goto err; - } - if ((error=d_search(info,keyinfo,key,old_root,root_buff)) >0) - { - if (error == 2) - { - DBUG_PRINT("test",("Enlarging of root when deleting")); - error=_nisam_enlarge_root(info,keynr,key); - } - else - { - error=0; - if (getint(root_buff) <= (nod_flag=test_if_nod(root_buff))+3) - { - if (nod_flag) - info->s->state.key_root[keynr]=_nisam_kpos(nod_flag, - root_buff+2+nod_flag); - else - info->s->state.key_root[keynr]= NI_POS_ERROR; - if (_nisam_dispose(info,keyinfo,old_root)) - error= -1; - } - } - } -err: - my_afree((gptr) root_buff); - DBUG_RETURN(error); -} /* _nisam_ck_delete */ - - - /* Tar bort en nyckel under root */ - /* Returnerar 1 om nuvarande buffert minskade */ - /* Returnerar 2 om nuvarande buffert |kar */ - -static int d_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, ulong page, uchar *anc_buff) -{ - int flag,ret_value,save_flag; - uint length,nod_flag; - uchar *leaf_buff,*keypos,*next_keypos; - ulong leaf_page,next_block; - uchar lastkey[N_MAX_KEY_BUFF]; - DBUG_ENTER("d_search"); - DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff)); - - flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,0,SEARCH_SAME,&keypos, - lastkey); - nod_flag=test_if_nod(anc_buff); - - leaf_buff=0; - LINT_INIT(leaf_page); - if (nod_flag) - { - leaf_page=_nisam_kpos(nod_flag,keypos); - if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+ - N_MAX_KEY_BUFF*2))) - { - my_errno=ENOMEM; - DBUG_RETURN(-1); - } - if (!_nisam_fetch_keypage(info,keyinfo,leaf_page,leaf_buff,0)) - goto err; - } - - if (flag != 0) - { - if (!nod_flag) - { - my_errno=HA_ERR_CRASHED; /* This should newer happend */ - goto err; - } - save_flag=0; - ret_value=d_search(info,keyinfo,key,leaf_page,leaf_buff); - } - else - { /* Found key */ - next_keypos=keypos; /* Find where next block is */ - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&next_keypos,lastkey)); - next_block=_nisam_kpos(nod_flag,next_keypos); - length=getint(anc_buff); - length-= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length); - putint(anc_buff,length,nod_flag); - if (!nod_flag) - { /* On leaf page */ - if (_nisam_write_keypage(info,keyinfo,page,anc_buff)) - DBUG_RETURN(-1); - DBUG_RETURN(length <= (uint) keyinfo->base.block_length/2); - } - save_flag=1; - ret_value=del(info,keyinfo,key,anc_buff,leaf_page,leaf_buff,keypos, - next_block,lastkey); - } - if (ret_value >0) - { - save_flag=1; - if (ret_value == 1) - ret_value= underflow(info,keyinfo,anc_buff,leaf_page,leaf_buff,keypos); - else - { /* This happens only with packed keys */ - DBUG_PRINT("test",("Enlarging of key when deleting")); - VOID(_nisam_get_last_key(info,keyinfo,anc_buff,lastkey,keypos)); - ret_value=_nisam_insert(info,keyinfo,key,anc_buff,keypos,lastkey, - (uchar*) 0,(uchar*) 0,0L); - } - } - if (ret_value == 0 && getint(anc_buff) > keyinfo->base.block_length) - { - save_flag=1; - ret_value=_nisam_splitt_page(info,keyinfo,key,anc_buff,lastkey) | 2; - } - if (save_flag) - ret_value|=_nisam_write_keypage(info,keyinfo,page,anc_buff); - else - { - DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff)); - } - my_afree((byte*) leaf_buff); - DBUG_RETURN(ret_value); -err: - my_afree((byte*) leaf_buff); - DBUG_PRINT("exit",("Error: %d",my_errno)); - DBUG_RETURN (-1); -} /* d_search */ - - - /* Remove a key that has a page-reference */ - -static int del(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, - uchar *anc_buff, ulong leaf_page, uchar *leaf_buff, - uchar *keypos, /* Pos to where deleted key was */ - ulong next_block, - uchar *ret_key) /* key before keypos in anc_buff */ -{ - int ret_value,length; - uint a_length,nod_flag; - ulong next_page; - uchar keybuff[N_MAX_KEY_BUFF],*endpos,*next_buff,*key_start; - ISAM_SHARE *share=info->s; - S_PARAM s_temp; - DBUG_ENTER("del"); - DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos)); - DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff)); - - endpos=leaf_buff+getint(leaf_buff); - key_start=_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos); - - if ((nod_flag=test_if_nod(leaf_buff))) - { - next_page= _nisam_kpos(nod_flag,endpos); - if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+ - N_MAX_KEY_BUFF))) - DBUG_RETURN(-1); - if (!_nisam_fetch_keypage(info,keyinfo,next_page,next_buff,0)) - ret_value= -1; - else - { - DBUG_DUMP("next_page",(byte*) next_buff,getint(next_buff)); - if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff, - keypos,next_block,ret_key)) >0) - { - endpos=leaf_buff+getint(leaf_buff); - if (ret_value == 1) - { - ret_value=underflow(info,keyinfo,leaf_buff,next_page, - next_buff,endpos); - if (ret_value == 0 && getint(leaf_buff) > keyinfo->base.block_length) - { - ret_value=_nisam_splitt_page(info,keyinfo,key,leaf_buff,ret_key) | 2; - } - } - else - { - DBUG_PRINT("test",("Inserting of key when deleting")); - VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos)); - ret_value=_nisam_insert(info,keyinfo,key,leaf_buff,endpos,keybuff, - (uchar*) 0,(uchar*) 0,0L); - } - } - if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff)) - goto err; - } - my_afree((byte*) next_buff); - DBUG_RETURN(ret_value); - } - - /* Remove last key from leaf page */ - - putint(leaf_buff,key_start-leaf_buff,nod_flag); - if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff)) - goto err; - - /* Place last key in ancestor page on deleted key position */ - - a_length=getint(anc_buff); - endpos=anc_buff+a_length; - VOID(_nisam_get_last_key(info,keyinfo,anc_buff,ret_key,keypos)); - length=_nisam_get_pack_key_length(keyinfo,share->base.key_reflength, - keypos == endpos ? (uchar*) 0 : keypos, - ret_key,keybuff,&s_temp); - if (length > 0) - bmove_upp((byte*) endpos+length,(byte*) endpos,(uint) (endpos-keypos)); - else - bmove(keypos,keypos-length, (int) (endpos-keypos)+length); - _nisam_store_key(keyinfo,keypos,&s_temp); - /* Save pointer to next leaf */ - VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key)); - _nisam_kpointer(info,keypos - share->base.key_reflength,next_block); - putint(anc_buff,a_length+length,share->base.key_reflength); - - DBUG_RETURN( getint(leaf_buff) <= (uint) keyinfo->base.block_length/2 ); -err: - DBUG_RETURN(-1); -} /* del */ - - - /* Balances adjacent pages if underflow occours */ - -static int underflow(register N_INFO *info, register N_KEYDEF *keyinfo, - uchar *anc_buff, - ulong leaf_page, /* Ancestor page and underflow page */ - uchar *leaf_buff, - uchar *keypos) /* Position to pos after key */ -{ - int t_length; - uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag; - ulong next_page; - uchar anc_key[N_MAX_KEY_BUFF],leaf_key[N_MAX_KEY_BUFF], - *buff,*endpos,*next_keypos,*half_pos,*temp_pos; - S_PARAM s_temp; - ISAM_SHARE *share=info->s; - DBUG_ENTER("underflow"); - DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos)); - DBUG_DUMP("anc_buff",(byte*) anc_buff,getint(anc_buff)); - DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff)); - - buff=info->buff; - next_keypos=keypos; - nod_flag=test_if_nod(leaf_buff); - p_length=2+nod_flag; - anc_length=getint(anc_buff); - leaf_length=getint(leaf_buff); - info->page_changed=1; - - if ((keypos < anc_buff+anc_length && (share->rnd++ & 1)) || - keypos == anc_buff+2+share->base.key_reflength) - { /* Use page right of anc-page */ - DBUG_PRINT("test",("use right page")); - - VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos, - buff)); - next_page= _nisam_kpos(share->base.key_reflength,next_keypos); - if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0)) - goto err; - buff_length=getint(buff); - DBUG_DUMP("next",(byte*) buff,buff_length); - - /* find keys to make a big key-page */ - bmove((byte*) next_keypos-share->base.key_reflength,(byte*) buff+2, - share->base.key_reflength); - VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos)); - VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,leaf_key, - leaf_buff+leaf_length)); - - /* merge pages and put parting key from anc_buff between */ - t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,buff+p_length, - (leaf_length == nod_flag+2 ? - (uchar*) 0 : leaf_key), - anc_key,&s_temp); - length=buff_length-p_length; - endpos=buff+length+leaf_length+t_length; - bmove_upp((byte*) endpos, (byte*) buff+buff_length,length); - memcpy((byte*) buff, (byte*) leaf_buff,(size_t) leaf_length); - _nisam_store_key(keyinfo,buff+leaf_length,&s_temp); - buff_length=(uint) (endpos-buff); - putint(buff,buff_length,nod_flag); - - /* remove key from anc_buff */ - - s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key, - anc_buff+anc_length); - putint(anc_buff,(anc_length-=s_length),share->base.key_reflength); - - if (buff_length <= keyinfo->base.block_length) - { /* Keys in one page */ - memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length); - if (_nisam_dispose(info,keyinfo,next_page)) - goto err; - } - else - { /* Page is full */ - VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos)); - half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key); - length=(uint) (half_pos-buff); - memcpy((byte*) leaf_buff,(byte*) buff,(size_t) length); - putint(leaf_buff,length,nod_flag); - endpos=anc_buff+anc_length; - - /* Correct new keypointer to leaf_page */ - length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key); - _nisam_kpointer(info,leaf_key+length,next_page); - /* Save key in anc_buff */ - t_length=(int) _nisam_get_pack_key_length(keyinfo, - share->base.key_reflength, - keypos == endpos ? - (uchar*) 0 : keypos, - anc_key,leaf_key,&s_temp); - if (t_length >= 0) - bmove_upp((byte*) endpos+t_length,(byte*) endpos, - (uint) (endpos-keypos)); - else - bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length); - _nisam_store_key(keyinfo,keypos,&s_temp); - putint(anc_buff,(anc_length+=t_length),share->base.key_reflength); - - /* Store new page */ - if (nod_flag) - bmove((byte*) buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag); - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)); - t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0, - (uchar*) 0, leaf_key,&s_temp); - s_temp.n_length= *half_pos; /* For _nisam_store_key */ - length=(uint) ((buff+getint(buff))-half_pos); - bmove((byte*) buff+p_length+t_length,(byte*) half_pos,(size_t) length); - _nisam_store_key(keyinfo,buff+p_length,&s_temp); - putint(buff,length+t_length+p_length,nod_flag); - - if (_nisam_write_keypage(info,keyinfo,next_page,buff)) - goto err; - } - if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff)) - goto err; - DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2); - } - - DBUG_PRINT("test",("use left page")); - - keypos=_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos); - next_page= _nisam_kpos(share->base.key_reflength,keypos); - if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0)) - goto err; - buff_length=getint(buff); - endpos=buff+buff_length; - DBUG_DUMP("prev",(byte*) buff,buff_length); - - /* find keys to make a big key-page */ - bmove((byte*) next_keypos - share->base.key_reflength,(byte*) leaf_buff+2, - share->base.key_reflength); - next_keypos=keypos; - VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos, - anc_key)); - VOID(_nisam_get_last_key(info,keyinfo,buff,leaf_key,endpos)); - - /* merge pages and put parting key from anc_buff between */ - t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag, - leaf_buff+p_length, - (leaf_length == nod_flag+2 ? - (uchar*) 0 : leaf_key), - anc_key,&s_temp); - if (t_length >= 0) - bmove((byte*) endpos+t_length,(byte*) leaf_buff+p_length, - (size_t) (leaf_length-p_length)); - else /* We gained space */ - bmove((byte*) endpos,(byte*) leaf_buff+((int) p_length-t_length), - (size_t) (leaf_length-p_length+t_length)); - - _nisam_store_key(keyinfo,endpos,&s_temp); - buff_length=buff_length+leaf_length-p_length+t_length; - putint(buff,buff_length,nod_flag); - - /* remove key from anc_buff */ - s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key, - anc_buff+anc_length); - putint(anc_buff,(anc_length-=s_length),share->base.key_reflength); - - if (buff_length <= keyinfo->base.block_length) - { /* Keys in one page */ - if (_nisam_dispose(info,keyinfo,leaf_page)) - goto err; - } - else - { /* Page is full */ - VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos)); - endpos=half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key); - - /* Correct new keypointer to leaf_page */ - length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key); - _nisam_kpointer(info,leaf_key+length,leaf_page); - /* Save key in anc_buff */ - DBUG_DUMP("anc_buff",(byte*) anc_buff,anc_length); - DBUG_DUMP("key",(byte*) leaf_key,16); - - temp_pos=anc_buff+anc_length; - t_length=(int) _nisam_get_pack_key_length(keyinfo, - share->base.key_reflength, - keypos == temp_pos ? (uchar*) 0 - : keypos, - anc_key,leaf_key,&s_temp); - if (t_length > 0) - bmove_upp((byte*) temp_pos+t_length,(byte*) temp_pos, - (uint) (temp_pos-keypos)); - else - bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length); - _nisam_store_key(keyinfo,keypos,&s_temp); - putint(anc_buff,(anc_length+=t_length),share->base.key_reflength); - - /* Store new page */ - if (nod_flag) - bmove((byte*) leaf_buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag); - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)); - t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag, (uchar*) 0, - (uchar*) 0, leaf_key, &s_temp); - s_temp.n_length= *half_pos; /* For _nisam_store_key */ - length=(uint) ((buff+buff_length)-half_pos); - bmove((byte*) leaf_buff+p_length+t_length,(byte*) half_pos, - (size_t) length); - _nisam_store_key(keyinfo,leaf_buff+p_length,&s_temp); - putint(leaf_buff,length+t_length+p_length,nod_flag); - putint(buff,endpos-buff,nod_flag); - if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff)) - goto err; - } - if (_nisam_write_keypage(info,keyinfo,next_page,buff)) - goto err; - DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2); -err: - DBUG_RETURN(-1); -} /* underflow */ - - - /* remove a key from packed buffert */ - /* returns how many chars was removed */ - -static uint remove_key(N_KEYDEF *keyinfo, uint nod_flag, - uchar *keypos, /* Where key starts */ - uchar *lastkey, /* key to be removed */ - uchar *page_end) /* End of page */ -{ - int r_length,s_length,first,diff_flag; - uchar *start; - DBUG_ENTER("remove_key"); - DBUG_PRINT("enter",("keypos: %lx page_end: %lx",keypos,page_end)); - - start=keypos; - if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED))) - s_length=(int) (keyinfo->base.keylength+nod_flag); - else - { /* Let keypos point at next key */ - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey)); - s_length=(uint) (keypos-start); - if (keyinfo->base.flag & HA_PACK_KEY) - { - diff_flag= (keyinfo->seg[0].base.flag & HA_SPACE_PACK); - first= *start; - if (keypos != page_end && *keypos & 128 && first != 128) - { /* Referens length */ - if ((r_length= *keypos++ & 127) == 0) - { /* Same key after */ - if (first & 128) - start++; /* Skip ref length */ - if (diff_flag) - start+= *start+1; /* Skip key length */ - else - start+=keyinfo->seg[0].base.length- (first & 127); - s_length=(uint)(keypos-start); /* Remove pntrs and next-key-flag */ - } - else if (! (first & 128)) - { /* Deleted key was not compressed */ - if (diff_flag) - { - *start= (uchar) (r_length+ *keypos); - start+=r_length+1; /* Let ref-part remain */ - s_length=(uint) (keypos-start)+1; /* Skip everything between */ - } - else - { - start+=r_length+1; /* Let ref-part remain */ - s_length=(uint) (keypos-start); /* Skip everything between */ - } - } - else if ((first & 127) < r_length) - { /* mid-part of key is used */ - r_length-=(first & 127); - start++; /* Ref remains the same */ - if (diff_flag) - *start++= (uchar) (*keypos++ + r_length); - start+= r_length; - s_length=(uint) (keypos-start); /* Skip everything between */ - } - } - } - } - bmove((byte*) start,(byte*) start+s_length, - (uint) (page_end-start-s_length)); - DBUG_RETURN((uint) s_length); -} /* remove_key */ diff --git a/isam/extra.c b/isam/extra.c deleted file mode 100644 index 421404311c8..00000000000 --- a/isam/extra.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Extra functions we want to do with a database */ -/* - Set flags for quicker databasehandler */ -/* - Set databasehandler to normal */ -/* - Reset recordpointers as after open database */ - -#include "isamdef.h" -#ifdef HAVE_MMAP -#include <sys/mman.h> -#endif -#ifdef __WIN__ -#include <errno.h> -#endif - - /* set extra flags for database */ - -int nisam_extra(N_INFO *info, enum ha_extra_function function) -{ - int error=0; - DBUG_ENTER("nisam_extra"); - - switch (function) { - case HA_EXTRA_RESET: - if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) - { - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - error=end_io_cache(&info->rec_cache); - } - info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS); - - case HA_EXTRA_RESET_STATE: - info->lastinx= 0; /* Use first index as def */ - info->int_pos=info->lastpos= NI_POS_ERROR; - info->page_changed=1; - /* Next/prev gives first/last */ - if (info->opt_flag & READ_CACHE_USED) - { - VOID(flush_io_cache(&info->rec_cache)); - reinit_io_cache(&info->rec_cache,READ_CACHE,0, - (pbool) (info->lock_type != F_UNLCK), - (pbool) test(info->update & HA_STATE_ROW_CHANGED)); - } - info->update=((info->update & HA_STATE_CHANGED) | - HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND); - break; - case HA_EXTRA_CACHE: -#ifndef NO_LOCKING - if (info->lock_type == F_UNLCK && (info->options & HA_OPTION_PACK_RECORD)) - { - error=1; /* Not possibly if not locked */ - my_errno=EACCES; - break; - } -#endif -#if defined(HAVE_MMAP) && defined(HAVE_MADVICE) - if ((info->options & HA_OPTION_COMPRESS_RECORD)) - { - pthread_mutex_lock(&info->s->intern_lock); - if (_nisam_memmap_file(info)) - { - /* We don't nead MADV_SEQUENTIAL if small file */ - madvise(info->s->file_map,info->s->state.data_file_length, - info->s->state.data_file_length <= RECORD_CACHE_SIZE*16 ? - MADV_RANDOM : MADV_SEQUENTIAL); - pthread_mutex_unlock(&info->s->intern_lock); - break; - } - pthread_mutex_unlock(&info->s->intern_lock); - } -#endif - if (info->opt_flag & WRITE_CACHE_USED) - { - info->opt_flag&= ~WRITE_CACHE_USED; - if ((error=end_io_cache(&info->rec_cache))) - break; - } - if (!(info->opt_flag & - (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED))) - { - if (!(init_io_cache(&info->rec_cache,info->dfile, - (uint) min(info->s->state.data_file_length+1, - my_default_record_cache_size), - READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK), - MYF(MY_WAIT_IF_FULL)))) - { - info->opt_flag|=READ_CACHE_USED; - info->update&= ~HA_STATE_ROW_CHANGED; - } - /* info->rec_cache.end_of_file=info->s->state.data_file_length; */ - } - break; - case HA_EXTRA_REINIT_CACHE: - if (info->opt_flag & READ_CACHE_USED) - { - reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos, - (pbool) (info->lock_type != F_UNLCK), - (pbool) test(info->update & HA_STATE_ROW_CHANGED)); - info->update&= ~HA_STATE_ROW_CHANGED; - /* info->rec_cache.end_of_file=info->s->state.data_file_length; */ - } - break; - case HA_EXTRA_WRITE_CACHE: -#ifndef NO_LOCKING - if (info->lock_type == F_UNLCK) - { - error=1; /* Not possibly if not locked */ - break; - } -#endif - if (!(info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))) - { - if (!(init_io_cache(&info->rec_cache,info->dfile,0, - WRITE_CACHE,info->s->state.data_file_length, - (pbool) (info->lock_type != F_UNLCK), - MYF(MY_WAIT_IF_FULL)))) - { - info->opt_flag|=WRITE_CACHE_USED; - info->update&= ~HA_STATE_ROW_CHANGED; - } - } - break; - case HA_EXTRA_PREPARE_FOR_UPDATE: - if (info->s->data_file_type != DYNAMIC_RECORD) - break; - /* Remove read/write cache if dynamic rows */ - case HA_EXTRA_NO_CACHE: - if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) - { - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - error=end_io_cache(&info->rec_cache); - } -#if defined(HAVE_MMAP) && defined(HAVE_MADVICE) - if (info->opt_flag & MEMMAP_USED) - madvise(info->s->file_map,info->s->state.data_file_length,MADV_RANDOM); -#endif - break; - case HA_EXTRA_FLUSH_CACHE: - if (info->opt_flag & WRITE_CACHE_USED) - error=flush_io_cache(&info->rec_cache); - break; - case HA_EXTRA_NO_READCHECK: - info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */ - break; - case HA_EXTRA_READCHECK: - info->opt_flag|= READ_CHECK_USED; - break; - case HA_EXTRA_KEYREAD: /* Read only keys to record */ - case HA_EXTRA_REMEMBER_POS: - info->opt_flag |= REMEMBER_OLD_POS; - bmove((byte*) info->lastkey+info->s->base.max_key_length*2, - (byte*) info->lastkey,info->s->base.max_key_length); - info->save_update= info->update; - info->save_lastinx= info->lastinx; - info->save_lastpos= info->lastpos; - if (function == HA_EXTRA_REMEMBER_POS) - break; - /* fall through */ - case HA_EXTRA_KEYREAD_CHANGE_POS: - info->opt_flag |= KEY_READ_USED; - info->read_record=_nisam_read_key_record; - break; - case HA_EXTRA_NO_KEYREAD: - case HA_EXTRA_RESTORE_POS: - if (info->opt_flag & REMEMBER_OLD_POS) - { - bmove((byte*) info->lastkey, - (byte*) info->lastkey+info->s->base.max_key_length*2, - info->s->base.max_key_length); - info->update= info->save_update | HA_STATE_WRITTEN; - info->lastinx= info->save_lastinx; - info->lastpos= info->save_lastpos; - } - info->read_record= info->s->read_record; - info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS); - break; - case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */ - info->lock_type= F_EXTRA_LCK; /* Simulate as locked */ - break; - case HA_EXTRA_WAIT_LOCK: - info->lock_wait=0; - break; - case HA_EXTRA_NO_WAIT_LOCK: - info->lock_wait=MY_DONT_WAIT; - break; - case HA_EXTRA_NO_KEYS: -#ifndef NO_LOCKING - if (info->lock_type == F_UNLCK) - { - error=1; /* Not possibly if not lock */ - break; - } -#endif - info->s->state.keys=0; - info->s->state.key_file_length=info->s->base.keystart; - info->s->changed=1; /* Update on close */ - break; - case HA_EXTRA_FORCE_REOPEN: - case HA_EXTRA_PREPARE_FOR_DELETE: - pthread_mutex_lock(&THR_LOCK_isam); - info->s->last_version= 0L; /* Impossible version */ -#ifdef __WIN__ - /* Close the isam and data files as Win32 can't drop an open table */ - if (flush_key_blocks(dflt_key_cache, info->s->kfile, FLUSH_RELEASE)) - error=my_errno; - if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) - { - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - error=end_io_cache(&info->rec_cache); - } - if (info->lock_type != F_UNLCK && ! info->was_locked) - { - info->was_locked=info->lock_type; - if (nisam_lock_database(info,F_UNLCK)) - error=my_errno; - } - if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0))) - error=my_errno; - { - LIST *list_element ; - for (list_element=nisam_open_list ; - list_element ; - list_element=list_element->next) - { - N_INFO *tmpinfo=(N_INFO*) list_element->data; - if (tmpinfo->s == info->s) - { - if (tmpinfo->dfile >= 0 && my_close(tmpinfo->dfile,MYF(0))) - error = my_errno; - tmpinfo->dfile=-1; - } - } - } - info->s->kfile=-1; /* Files aren't open anymore */ -#endif - pthread_mutex_unlock(&THR_LOCK_isam); - break; - case HA_EXTRA_FLUSH: - if (info->s->not_flushed) - { - info->s->not_flushed=0; - if (my_sync(info->s->kfile, MYF(0))) - error= my_errno; - if (my_sync(info->dfile, MYF(0))) - error= my_errno; - } - break; - case HA_EXTRA_NORMAL: /* Theese isn't in use */ - case HA_EXTRA_QUICK: - case HA_EXTRA_KEY_CACHE: - case HA_EXTRA_NO_KEY_CACHE: - default: - break; - } - nisam_log_command(LOG_EXTRA,info,(byte*) &function,sizeof(function),error); - DBUG_RETURN(error); -} /* nisam_extra */ diff --git a/isam/info.c b/isam/info.c deleted file mode 100644 index a23494e4876..00000000000 --- a/isam/info.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Ger tillbaka en struct med information om isam-filen */ - -#include "isamdef.h" -#ifdef __WIN__ -#include <sys/stat.h> -#endif - -ulong nisam_position(N_INFO *info) -{ - return info->lastpos; -} - - /* If flag == 1 one only gets pos of last record */ - /* if flag == 2 one get current info (no sync from database */ - -int nisam_info(N_INFO *info, register N_ISAMINFO *x, int flag) -{ - struct stat state; - ISAM_SHARE *share=info->s; - DBUG_ENTER("nisam_info"); - - x->recpos = info->lastpos; - if (flag & (HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE | - HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK)) - { -#ifndef NO_LOCKING - if (!(flag & HA_STATUS_NO_LOCK)) - { - pthread_mutex_lock(&share->intern_lock); - VOID(_nisam_readinfo(info,F_RDLCK,0)); - VOID(_nisam_writeinfo(info,0)); - pthread_mutex_unlock(&share->intern_lock); - } -#endif - x->records = share->state.records; - x->deleted = share->state.del; - x->delete_length= share->state.empty; - x->keys = share->state.keys; - x->reclength = share->base.reclength; - x->mean_reclength= share->state.records ? - (share->state.data_file_length-share->state.empty)/share->state.records : - share->min_pack_length; - x->data_file_length=share->state.data_file_length; - x->max_data_file_length=share->base.max_data_file_length; - x->index_file_length=share->state.key_file_length; - x->max_index_file_length=share->base.max_key_file_length; - x->filenr = info->dfile; - x->errkey = info->errkey; - x->dupp_key_pos= info->dupp_key_pos; - x->options = share->base.options; - x->create_time=share->base.create_time; - x->isamchk_time=share->base.isamchk_time; - x->rec_per_key=share->base.rec_per_key; - if ((flag & HA_STATUS_TIME) && !fstat(info->dfile,&state)) - x->update_time=state.st_mtime; - else - x->update_time=0; - x->sortkey= -1; /* No clustering */ - } - DBUG_RETURN(0); -} /* nisam_info */ diff --git a/isam/isamchk.c b/isam/isamchk.c deleted file mode 100644 index 5dd20c14063..00000000000 --- a/isam/isamchk.c +++ /dev/null @@ -1,3424 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Descript, check and repair of ISAM tables */ - -#include "isamdef.h" - -#include <m_ctype.h> -#include <stdarg.h> -#include <my_getopt.h> -#ifdef HAVE_SYS_VADVICE_H -#include <sys/vadvise.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -SET_STACK_SIZE(9000) /* Minimum stack size for program */ - -#define T_VERBOSE 1 -#define T_SILENT 2 -#define T_DESCRIPT 4 -#define T_EXTEND 8 -#define T_INFO 16 -#define T_REP 32 -#define T_OPT 64 /* Not currently used */ -#define T_FORCE_CREATE 128 -#define T_WRITE_LOOP 256 -#define T_UNPACK 512 -#define T_STATISTICS 1024 -#define T_VERY_SILENT 2048 -#define T_SORT_RECORDS 4096 -#define T_SORT_INDEX 8192 -#define T_WAIT_FOREVER 16384 -#define T_REP_BY_SORT 32768L - - -#define O_NEW_INDEX 1 /* Bits set in out_flag */ -#define O_NEW_DATA 2 - -#if defined(_MSC_VER) && !defined(__WIN__) -#define USE_BUFFER_INIT 250L*1024L -#define READ_BUFFER_INIT ((uint) 32768-MALLOC_OVERHEAD) -#define SORT_BUFFER_INIT (uint) (65536L-MALLOC_OVERHEAD) -#define MIN_SORT_BUFFER (1024*16-MALLOC_OVERHEAD) -#else -#define USE_BUFFER_INIT (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE) -#define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD) -#define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD) -#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) -#endif - -#define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */ -#define MAXERR 20 -#define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */ -#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE -#define INDEX_TMP_EXT ".TMM" -#define DATA_TMP_EXT ".TMD" -#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) - -#define UPDATE_TIME 1 -#define UPDATE_STAT 2 -#define UPDATE_SORT 4 - -typedef struct st_isam_sort_key_blocks { /* Used when sorting */ - uchar *buff,*end_pos; - uchar lastkey[N_MAX_POSSIBLE_KEY_BUFF]; - uint last_length; - int inited; -} ISAM_SORT_KEY_BLOCKS; - -typedef struct st_isam_sort_info { - N_INFO *info; - enum data_file_type new_data_file_type; - ISAM_SORT_KEY_BLOCKS *key_block,*key_block_end; - uint key,find_length; - ulong pos,max_pos,filepos,start_recpos,filelength,dupp,max_records,unique, - buff_length; - my_bool fix_datafile; - char *record,*buff; - N_KEYDEF *keyinfo; - N_KEYSEG *keyseg; -} ISAM_SORT_INFO; - -enum ic_options {OPT_CHARSETS_DIR_IC=256, OPT_KEY_BUFFER_SIZE, - OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, - OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, - OPT_DECODE_BITS}; - -static ulong use_buffers=0,read_buffer_length=0,write_buffer_length=0, - sort_buffer_length=0,sort_key_blocks=0,crc=0,unique_count=0; -static uint testflag=0,out_flag=0,warning_printed=0,error_printed=0, - verbose=0,opt_follow_links=1; -static my_bool rep_quick= 0; -static uint opt_sort_key=0,total_files=0,max_level=0,max_key=N_MAXKEY; -static ulong keydata=0,totaldata=0,key_blocks=0; -static ulong new_file_pos=0,record_checksum=0,key_file_blocks=0,decode_bits; -static ulong total_records=0,total_deleted=0; -static ulong search_after_block=NI_POS_ERROR; -static byte *record_buff; -static char **defaults_alloc; -static const char *type_names[]= -{ "?","text","binary", "short", "long", "float", - "double","number","unsigned short", - "unsigned long","longlong","ulonglong","int24", - "uint24","int8","?",}, - *packed_txt="packed ", - *diff_txt="stripped ", - *field_pack[]={"","no endspace", "no prespace", - "no zeros", "blob", "constant", "table-lookup", - "always zero","?","?",}; - -static char temp_filename[FN_REFLEN], *isam_file_name, *default_charset; -static IO_CACHE read_cache; -static ISAM_SORT_INFO sort_info; -static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL; - -static const char *load_default_groups[]= { "isamchk",0 }; - - /* Functions defined in this file */ - -extern int main(int argc,char * *argv); -extern void print_error _VARARGS((const char *fmt,...)); -static void print_warning _VARARGS((const char *fmt,...)); -static void print_info _VARARGS((const char *fmt,...)); -static int nisamchk(char *filename); -static void get_options(int *argc,char * * *argv); -static int chk_del(N_INFO *info,uint testflag); -static int check_k_link(N_INFO *info,uint nr); -static int chk_size(N_INFO *info); -static int chk_key(N_INFO *info); -static int chk_index(N_INFO *info, N_KEYDEF *keyinfo, ulong page, uchar *buff, - ulong *keys, uint level); -static uint isam_key_length(N_INFO *info,N_KEYDEF *keyinfo); -static unsigned long calc_checksum(ulong count); -static int chk_data_link(N_INFO *info,int extend); -static int rep(N_INFO *info,char *name); -static int writekeys(N_INFO *info,byte *buff,ulong filepos); -static void descript(N_INFO *info,char *name); -static int movepoint(N_INFO *info,byte *record,ulong oldpos,ulong newpos, - uint prot_key); -static void lock_memory(void); -static int flush_blocks(File file); -static int sort_records(N_INFO *,my_string,uint,int); -static int sort_index(N_INFO *info,my_string name); -static int sort_record_index(N_INFO *info,N_KEYDEF *keyinfo,ulong page, - uchar *buff,uint sortkey,File new_file); -static int sort_one_index(N_INFO *info,N_KEYDEF *keyinfo,uchar *buff, - File new_file); -static int change_to_newfile(const char * filename,const char * old_ext, - const char * new_ext); -static int lock_file(File file,ulong start,int lock_type,const char* filetype, - const char *filename); -static int filecopy(File to,File from,ulong start,ulong length, - const char * type); - -static void print_version(void); -static int rep_by_sort(N_INFO *info,my_string name); -static int sort_key_read(void *key); -static int sort_get_next_record(void); -static int sort_write_record(void); -static int sort_key_cmp(const void *not_used, const void *a,const void *b); -static int sort_key_write(const void *a); -static ulong get_record_for_key(N_INFO *info,N_KEYDEF *keyinfo, - uchar *key); -static int sort_insert_key(reg1 ISAM_SORT_KEY_BLOCKS *key_block,uchar *key, - ulong prev_block); -static int sort_delete_record(void); -static void usage(void); -static int flush_pending_blocks(void); -static ISAM_SORT_KEY_BLOCKS *alloc_key_blocks(uint blocks,uint buffer_length); -static int test_if_almost_full(N_INFO *info); -static int recreate_database(N_INFO **info,char *filename); -static void save_integer(byte *pos,uint pack_length,ulong value); -static int write_data_suffix(N_INFO *info); -static int update_state_info(N_INFO *info,uint update); - - - /* Main program */ - -int main( int argc, char **argv) -{ - int error; - MY_INIT(argv[0]); - -#ifdef __EMX__ - _wildcard (&argc, &argv); -#endif - - get_options(&argc,(char***) &argv); - nisam_quick_table_bits=(uint) decode_bits; - error=0; - while (--argc >= 0) - { - error|= nisamchk(*(argv++)); - VOID(fflush(stdout)); - VOID(fflush(stderr)); - if ((error_printed | warning_printed) && (testflag & T_FORCE_CREATE) && - (!(testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS | - T_SORT_INDEX)))) - { - testflag|=T_REP; - error|=nisamchk(argv[-1]); - testflag&= ~T_REP; - VOID(fflush(stdout)); - VOID(fflush(stderr)); - } - if (argc && (!(testflag & T_SILENT) || testflag & T_INFO)) - { - puts("\n---------\n"); - VOID(fflush(stdout)); - } - } - if (total_files > 1) - { /* Only if descript */ - if (!(testflag & T_SILENT) || testflag & T_INFO) - puts("\n---------\n"); - printf("\nTotal of all %d ISAM-files:\nData records: %8lu Deleted blocks: %8lu\n",total_files,total_records,total_deleted); - } - free_defaults(defaults_alloc); - my_end(testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); - exit(error); -#ifndef _lint - return 0; /* No compiler warning */ -#endif -} /* main */ - - -static struct my_option my_long_options[] = -{ - {"analyze", 'a', - "Analyze distribution of keys. Will make some joins in MySQL faster.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"character-sets-dir", OPT_CHARSETS_DIR_IC, - "Directory where character sets are", (gptr*) &charsets_dir, - (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifndef DBUG_OFF - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif - {"default-character-set", 'C', "Set the default character set", - (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"description", 'd', "Prints some information about table.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"extend-check", 'e', - "Check the table VERY thoroughly. One need to use this only in extreme cases, because isamchk should normally find all errors even without this switch.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"information", 'i', "Print statistics information about the table", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"force", 'f', - "Overwrite old temporary files. If one uses -f when checking tables (running isamchk without -r), isamchk will automatically restart with -r on any wrong table.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, - 0, 0, 0, 0, 0}, - {"keys-used", 'k', - "Used with '-r'. Tell ISAM to update only the first # keys. This can be used to get faster inserts!", - (gptr*) &max_key, (gptr*) &max_key, 0, GET_UINT, REQUIRED_ARG, N_MAXKEY, 0, - 0, 0, 0, 0}, - {"no-symlinks", 'l', - "Do not follow symbolic links when repairing. Normally isamchk repairs the table a symlink points at.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"quick", 'q', - "Used with -r to get a faster repair. (The data file isn't touched.) One can give a second '-q' to force isamchk to modify the original datafile.", - (gptr*) &rep_quick, (gptr*) &rep_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, - 0}, - {"recover", 'r', - "Can fix almost anything except unique keys that aren't unique.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"safe-recover", 'o', - "Uses old recovery method; slower than '-r' but can handle a couple of cases that '-r' cannot handle.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"set-variable", 'O', - "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"block-search", 'b', "For debugging.", (gptr*) &search_after_block, - (gptr*) &search_after_block, 0, GET_ULONG, REQUIRED_ARG, - (longlong) NI_POS_ERROR, 0, 0, 0, 0, 0}, - {"silent", 's', - "Only print errors. One can use two -s to make isamchk very silent.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"sort-index", 'S', - "Sort index blocks. This speeds up 'read-next' in applications.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"sort-records", 'R', - "Sort records according to an index. This makes your data much more localized and may speed up things (It may be VERY slow to do a sort the first time!)", - (gptr*) &opt_sort_key, (gptr*) &opt_sort_key, 0, GET_UINT, REQUIRED_ARG, - 0, 0, (N_MAXKEY - 1), 1, 0, 0}, - {"unpack", 'u', "Unpack file packed with pack_isam.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', - "Print more information. This can be used with -d and -e. Use many -v for more verbosity!", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"version", 'V', "Print version and exit.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"wait", 'w', "Wait if table is locked.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "", (gptr*) &use_buffers, - (gptr*) &use_buffers, 0, GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, - (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, - 0}, - {"read_buffer_size", OPT_READ_BUFFER_SIZE, "", - (gptr*) &read_buffer_length, (gptr*) &read_buffer_length, 0, GET_ULONG, - REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, - (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0}, - {"write_buffer_size", OPT_WRITE_BUFFER_SIZE, "", - (gptr*) &write_buffer_length, (gptr*) &write_buffer_length, 0, GET_ULONG, - REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, - (long) MALLOC_OVERHEAD, (long) 1L, 0}, - {"sort_buffer_size", OPT_SORT_BUFFER_SIZE, "", - (gptr*) &sort_buffer_length, (gptr*) &sort_buffer_length, 0, GET_ULONG, - REQUIRED_ARG, (long) SORT_BUFFER_INIT, - (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L, - (long) MALLOC_OVERHEAD, (long) 1L, 0}, - {"sort_key_blocks", OPT_SORT_KEY_BLOCKS, "", - (gptr*) &sort_key_blocks, (gptr*) &sort_key_blocks, 0, GET_ULONG, - REQUIRED_ARG, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0}, - {"decode_bits", OPT_DECODE_BITS, "", - (gptr*) &decode_bits, (gptr*) &decode_bits, 0, GET_ULONG, REQUIRED_ARG, - 9L, 4L, 17L, 0L, 1L, 0}, - {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} -}; - -#include <help_start.h> - -static void print_version(void) -{ - printf("%s Ver 6.01 for %s at %s\n", my_progname, SYSTEM_TYPE, - MACHINE_TYPE); - NETWARE_SET_SCREEN_MODE(1); -} - - -static void usage(void) -{ - print_version(); - puts("MySQL AB, by Monty, for your professional use"); - puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n"); - puts("Description, check and repair of ISAM tables."); - puts("Used without options all tables on the command will be checked for errors"); - printf("Usage: %s [OPTIONS] tables[.ISM]\n", my_progname); - my_print_help(my_long_options); - print_defaults("my", load_default_groups); - my_print_variables(my_long_options); -} - -#include <help_end.h> - - /* Check table */ - -static int nisamchk(my_string filename) -{ - int error,lock_type,recreate; - N_INFO *info; - File datafile; - char fixed_name[FN_REFLEN]; - ISAM_SHARE *share; - DBUG_ENTER("nisamchk"); - - out_flag=error=warning_printed=error_printed=recreate=0; - datafile=0; - isam_file_name=filename; /* For error messages */ - if (!(info=nisam_open(filename, - (testflag & T_DESCRIPT) ? O_RDONLY : O_RDWR, - (testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED : - (testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED : - HA_OPEN_ABORT_IF_LOCKED))) - { - /* Avoid twice printing of isam file name */ - error_printed=1; - switch (my_errno) { - case HA_ERR_CRASHED: - print_error("'%s' is not a ISAM-table",filename); - break; - case HA_ERR_OLD_FILE: - print_error("'%s' is a old type of ISAM-table", filename); - break; - case HA_ERR_END_OF_FILE: - print_error("Couldn't read compleat header from '%s'", filename); - break; - case EAGAIN: - print_error("'%s' is locked. Use -w to wait until unlocked",filename); - break; - case ENOENT: - print_error("File '%s' doesn't exist",filename); - break; - case EACCES: - print_error("You don't have permission to use '%s'",filename); - break; - default: - print_error("%d when opening ISAM-table '%s'", - my_errno,filename); - break; - } - DBUG_RETURN(1); - } - share=info->s; - share->base.options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */ - share->r_locks=0; - if ((testflag & (T_REP_BY_SORT | T_REP | T_STATISTICS | - T_SORT_RECORDS | T_SORT_INDEX)) && - ((testflag & T_UNPACK && share->data_file_type == COMPRESSED_RECORD) || - share->state_length != sizeof(share->state) || - uint2korr(share->state.header.base_info_length) != - sizeof(share->base) || - (max_key && ! share->state.keys && share->base.keys) || - test_if_almost_full(info) || - info->s->state.header.file_version[3] != nisam_file_magic[3])) - { - if (recreate_database(&info,filename)) - { - VOID(fprintf(stderr, - "ISAM-table '%s' is not fixed because of errors\n", - filename)); - return(-1); - } - recreate=1; - if (!(testflag & (T_REP | T_REP_BY_SORT))) - { - testflag|=T_REP_BY_SORT; /* if only STATISTICS */ - if (!(testflag & T_SILENT)) - printf("- '%s' has old table-format. Recreating index\n",filename); - if (!rep_quick) - rep_quick=1; - } - share=info->s; - share->r_locks=0; - } - - if (testflag & T_DESCRIPT) - { - total_files++; - total_records+=share->state.records; total_deleted+=share->state.del; - descript(info,filename); - } - else - { - if (testflag & (T_REP+T_REP_BY_SORT+T_OPT+T_SORT_RECORDS+T_SORT_INDEX)) - lock_type = F_WRLCK; /* table is changed */ - else - lock_type= F_RDLCK; - if (info->lock_type == F_RDLCK) - info->lock_type=F_UNLCK; /* Read only table */ - if (_nisam_readinfo(info,lock_type,0)) - { - print_error("Can't lock indexfile of '%s', error: %d", - filename,my_errno); - error_printed=0; - goto end2; - } - share->w_locks++; /* Mark (for writeinfo) */ - if (lock_file(info->dfile,0L,lock_type,"datafile of",filename)) - goto end; - info->lock_type= F_EXTRA_LCK; /* Simulate as locked */ - info->tmp_lock_type=lock_type; - datafile=info->dfile; - if (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX)) - { - if (testflag & (T_REP+T_REP_BY_SORT)) - share->state.keys=min(share->base.keys,max_key); - VOID(fn_format(fixed_name,filename,"",N_NAME_IEXT, - 4+ (opt_follow_links ? 16 : 0))); - - if (rep_quick && (error=chk_del(info,testflag & ~T_VERBOSE))) - print_error("Quick-recover aborted; Run recovery without switch 'q'"); - else - { - if (testflag & T_REP_BY_SORT && - (share->state.keys || (rep_quick && !max_key && ! recreate))) - error=rep_by_sort(info,fixed_name); - else if (testflag & (T_REP | T_REP_BY_SORT)) - error=rep(info,fixed_name); - } - if (!error && testflag & T_SORT_RECORDS) - { - if (out_flag & O_NEW_DATA) - { /* Change temp file to org file */ - VOID(lock_file(datafile,0L,F_UNLCK,"datafile of",filename)); - VOID(my_close(datafile,MYF(MY_WME))); /* Close old file */ - VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */ - error|=change_to_newfile(fixed_name,N_NAME_DEXT,DATA_TMP_EXT); - if ((info->dfile=my_open(fn_format(temp_filename,fixed_name,"", - N_NAME_DEXT,2+4), - O_RDWR | O_SHARE, - MYF(MY_WME))) <= 0 || - lock_file(info->dfile,0L,F_WRLCK,"datafile",temp_filename)) - error=1; - out_flag&= ~O_NEW_DATA; /* We are using new datafile */ - read_cache.file=info->dfile; - } - if (! error) - error=sort_records(info,fixed_name,opt_sort_key, - test(!(testflag & T_REP))); - datafile=info->dfile; /* This is now locked */ - } - if (!error && testflag & T_SORT_INDEX) - error=sort_index(info,fixed_name); - } - else - { - if (!(testflag & T_SILENT) || testflag & T_INFO) - printf("Checking ISAM file: %s\n",filename); - if (!(testflag & T_SILENT)) - printf("Data records: %7ld Deleted blocks: %7ld\n", - share->state.records,share->state.del); - share->state.keys=min(share->state.keys,max_key); - error =chk_size(info); - error|=chk_del(info,testflag); - error|=chk_key(info); - if (!rep_quick) - { - if (testflag & T_EXTEND) - VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE, - use_buffers,0,0)); - VOID(init_io_cache(&read_cache,datafile,(uint) read_buffer_length, - READ_CACHE,share->pack.header_length,1, - MYF(MY_WME))); - lock_memory(); - error|=chk_data_link(info,testflag & T_EXTEND); - error|=flush_blocks(share->kfile); - VOID(end_io_cache(&read_cache)); - } - } - } -end: - if (!(testflag & T_DESCRIPT)) - { - if (info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) - error|=update_state_info(info, - ((testflag & (T_REP | T_REP_BY_SORT)) ? - UPDATE_TIME | UPDATE_STAT : 0) | - ((testflag & T_SORT_RECORDS) ? - UPDATE_SORT : 0)); - VOID(lock_file(share->kfile,0L,F_UNLCK,"indexfile",filename)); - if (datafile > 0) - VOID(lock_file(datafile,0L,F_UNLCK,"datafile of",filename)); - info->update&= ~(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - } - share->w_locks--; -end2: - if (datafile && datafile != info->dfile) - VOID(my_close(datafile,MYF(MY_WME))); - if (nisam_close(info)) - { - print_error("%d when closing ISAM-table '%s'",my_errno,filename); - DBUG_RETURN(1); - } - if (error == 0) - { - if (out_flag & O_NEW_DATA) - error|=change_to_newfile(fixed_name,N_NAME_DEXT,DATA_TMP_EXT); - if (out_flag & O_NEW_INDEX) - error|=change_to_newfile(fixed_name,N_NAME_IEXT,INDEX_TMP_EXT); - } - VOID(fflush(stdout)); VOID(fflush(stderr)); - if (error_printed) - { - if (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX)) - VOID(fprintf(stderr, - "ISAM-table '%s' is not fixed because of errors\n", - filename)); - else if (! (error_printed & 2) && !(testflag & T_FORCE_CREATE)) - VOID(fprintf(stderr, - "ISAM-table '%s' is corrupted\nFix it using switch \"-r\" or \"-o\"\n", - filename)); - } - else if (warning_printed && - ! (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX+ - T_FORCE_CREATE))) - VOID(fprintf(stderr, "ISAM-table '%s' is useable but should be fixed\n", - filename)); - VOID(fflush(stderr)); - DBUG_RETURN(error); -} /* nisamchk */ - - -static my_bool -get_one_option(int optid, const struct my_option *opt __attribute__((unused)), - char *argument) - -{ - switch(optid) { - case 'a': - testflag|= T_STATISTICS; - break; - case 's': /* silent */ - if (testflag & T_SILENT) - testflag|=T_VERY_SILENT; - testflag|= T_SILENT; - testflag&= ~T_WRITE_LOOP; - break; - case 'w': - testflag|= T_WAIT_FOREVER; - break; - case 'd': /* description if isam-file */ - testflag|= T_DESCRIPT; - break; - case 'e': /* extend check */ - testflag|= T_EXTEND; - break; - case 'i': - testflag|= T_INFO; - break; - case 'f': - tmpfile_createflag= O_RDWR | O_TRUNC; - testflag|=T_FORCE_CREATE; - break; - case 'l': - opt_follow_links=0; - break; - case 'r': /* Repair table */ - testflag= (testflag & ~T_REP) | T_REP_BY_SORT; - break; - case 'o': - testflag= (testflag & ~T_REP_BY_SORT) | T_REP; - my_disable_async_io=1; /* More safety */ - break; - case 'u': - testflag|= T_UNPACK | T_REP_BY_SORT; - break; - case 'v': /* Verbose */ - testflag|= T_VERBOSE; - verbose++; - break; - case 'R': /* Sort records */ - testflag|= T_SORT_RECORDS; - if (opt_sort_key >= N_MAXKEY) - { - fprintf(stderr, - "The value of the sort key is bigger than max key: %d.\n", - N_MAXKEY); - exit(1); - } - break; - case 'S': /* Sort index */ - testflag|= T_SORT_INDEX; - break; - case '#': - DBUG_PUSH(argument ? argument : "d:t:o,/tmp/isamchk.trace"); - break; - case 'V': - print_version(); - exit(0); - case '?': - usage(); - exit(0); - } - return 0; -} - - /* Read options */ - -static void get_options(register int *argc, register char ***argv) -{ - int ho_error; - - load_defaults("my",load_default_groups,argc,argv); - defaults_alloc= *argv; - if (isatty(fileno(stdout))) - testflag|=T_WRITE_LOOP; - - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) - exit(ho_error); - - if (*argc == 0) - { - usage(); - exit(-1); - } - if ((testflag & T_UNPACK) && (rep_quick || (testflag & T_SORT_RECORDS))) - { - VOID(fprintf(stderr, - "%s: --unpack can't be used with --quick or --sort-records\n", - my_progname)); - exit(1); - } - if (default_charset) - { - if (!(default_charset_info= get_charset_by_name(default_charset, MYF(MY_WME)))) - exit(1); - } - return; -} /* get options */ - - - /* Check delete links */ - -static int chk_del( reg1 N_INFO *info, uint test_flag) -{ - reg2 ulong i; - uint j,delete_link_length; - ulong empty,next_link; - uchar buff[8]; - DBUG_ENTER("chk_del"); - if (!(test_flag & T_SILENT)) puts("- check delete-chain"); - - record_checksum=0L; - key_file_blocks=info->s->base.keystart; - for (j =0 ; j < info->s->state.keys ; j++) - if (check_k_link(info,j)) - goto wrong; - delete_link_length=(info->s->base.options & HA_OPTION_PACK_RECORD) ? 8 : 5; - - next_link=info->s->state.dellink; - if (info->s->state.del == 0) - { - if (test_flag & T_VERBOSE) - { - puts("No recordlinks"); - } - } - else - { - if (test_flag & T_VERBOSE) - printf("Recordlinks: "); - empty=0; - for (i= info->s->state.del ; i > 0L && next_link != NI_POS_ERROR ; i--) - { - if (test_flag & T_VERBOSE) printf("%10lu",next_link); - if (next_link >= info->s->state.data_file_length) - goto wrong; - if (my_pread(info->dfile,(char*) buff,delete_link_length, - next_link,MYF(MY_NABP))) - { - if (test_flag & T_VERBOSE) puts(""); - print_error("Can't read delete-link at filepos: %lu", - (ulong) next_link); - DBUG_RETURN(1); - } - if (*buff != '\0') - { - if (test_flag & T_VERBOSE) puts(""); - print_error("Record at pos: %lu is not remove-marked", - (ulong) next_link); - goto wrong; - } - if (info->s->base.options & HA_OPTION_PACK_RECORD) - { - next_link=uint4korr(buff+4); - empty+=uint3korr(buff+1); - } - else - { - record_checksum+=next_link; - next_link=uint4korr(buff+1); - empty+=info->s->base.reclength; - } - if (next_link == (uint32) ~0) /* Fix for 64 bit long */ - next_link=NI_POS_ERROR; - } - if (empty != info->s->state.empty) - { - if (test_flag & T_VERBOSE) puts(""); - print_warning("Not used space is supposed to be: %lu but is: %lu", - (ulong) info->s->state.empty,(ulong) empty); - info->s->state.empty=empty; - } - if (i != 0 || next_link != NI_POS_ERROR) - goto wrong; - - if (test_flag & T_VERBOSE) puts("\n"); - } - DBUG_RETURN(0); -wrong: - if (test_flag & T_VERBOSE) puts(""); - print_error("delete-link-chain corrupted"); - DBUG_RETURN(1); -} /* chk_del */ - - - /* Kontrollerar l{nkarna i nyckelfilen */ - -static int check_k_link( register N_INFO *info, uint nr) -{ - ulong next_link,records; - DBUG_ENTER("check_k_link"); - - if (testflag & T_VERBOSE) - printf("index %2d: ",nr+1); - - next_link=info->s->state.key_del[nr]; - records= (info->s->state.key_file_length / - info->s->keyinfo[nr].base.block_length); - while (next_link != NI_POS_ERROR && records > 0) - { - if (testflag & T_VERBOSE) printf("%10lu",next_link); - if (next_link > info->s->state.key_file_length || - next_link & (info->s->blocksize-1)) - DBUG_RETURN(1); - if (my_pread(info->s->kfile,(char*) &next_link,sizeof(long),next_link, - MYF(MY_NABP))) - DBUG_RETURN(1); - records--; - key_file_blocks+=info->s->keyinfo[nr].base.block_length; - } - if (testflag & T_VERBOSE) - { - if (next_link != NI_POS_ERROR) - printf("%10lu\n",next_link); - else - puts(""); - } - DBUG_RETURN (next_link != NI_POS_ERROR); -} /* check_k_link */ - - - /* Kontrollerar storleken p} filerna */ - -static int chk_size(register N_INFO *info) -{ - int error=0; - register my_off_t skr,size; - DBUG_ENTER("chk_size"); - - if (!(testflag & T_SILENT)) puts("- check file-size"); - - size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)); - if ((skr=(my_off_t) info->s->state.key_file_length) != size) - { - if (skr > size) - { - error=1; - print_error("Size of indexfile is: %-8lu Should be: %lu", - (ulong) size, (ulong) skr); - } - else - print_warning("Size of indexfile is: %-8lu Should be: %lu", - (ulong) size,(ulong) skr); - } - if (!(testflag & T_VERY_SILENT) && - ! (info->s->base.options & HA_OPTION_COMPRESS_RECORD) && - info->s->state.key_file_length > - (ulong) (ulong_to_double(info->s->base.max_key_file_length)*0.9)) - print_warning("Keyfile is almost full, %10lu of %10lu used", - info->s->state.key_file_length, - info->s->base.max_key_file_length-1); - - size=my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)); - skr=(my_off_t) info->s->state.data_file_length; - if (info->s->base.options & HA_OPTION_COMPRESS_RECORD) - skr+= MEMMAP_EXTRA_MARGIN; -#ifdef USE_RELOC - if (info->data_file_type == STATIC_RECORD && - skr < (my_off_t) info->s->base.reloc*info->s->base.min_pack_length) - skr=(my_off_t) info->s->base.reloc*info->s->base.min_pack_length; -#endif - if (skr != size) - { - info->s->state.data_file_length=(ulong) size; /* Skip other errors */ - if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN) - { - error=1; - print_error("Size of datafile is: %-8lu Should be: %lu", - (ulong) size,(ulong) skr); - } - else - { - print_warning("Size of datafile is: %-8lu Should be: %lu", - (ulong) size,(ulong) skr); - - } - } - if (!(testflag & T_VERY_SILENT) && - !(info->s->base.options & HA_OPTION_COMPRESS_RECORD) && - info->s->state.data_file_length > - (ulong) (ulong_to_double(info->s->base.max_data_file_length)*0.9)) - print_warning("Datafile is almost full, %10lu of %10lu used", - info->s->state.data_file_length, - info->s->base.max_data_file_length-1); - DBUG_RETURN(error); -} /* chk_size */ - - - /* Kontrollerar nycklarna */ - -static int chk_key( register N_INFO *info) -{ - uint key; - ulong keys,all_keydata,all_totaldata,key_totlength,length, - init_checksum,old_record_checksum; - ISAM_SHARE *share=info->s; - N_KEYDEF *keyinfo; - DBUG_ENTER("chk_key"); - - if (!(testflag & T_SILENT)) puts("- check index reference"); - - all_keydata=all_totaldata=key_totlength=old_record_checksum=0; - init_checksum=record_checksum; - if (!(share->base.options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) - old_record_checksum=calc_checksum(share->state.records+share->state.del-1)* - share->base.reclength; - for (key= 0,keyinfo= &share->keyinfo[0]; key < share->state.keys ; - key++,keyinfo++) - { - record_checksum=init_checksum; - unique_count=0L; - if ((!(testflag & T_SILENT)) && share->state.keys >1) - printf ("- check data record references index: %d\n",key+1); - if (share->state.key_root[key] == NI_POS_ERROR && - share->state.records == 0) - continue; - if (!_nisam_fetch_keypage(info,keyinfo,share->state.key_root[key],info->buff, - 0)) - { - print_error("Can't read indexpage from filepos: %lu", - (ulong) share->state.key_root[key]); - DBUG_RETURN(-1); - } - key_file_blocks+=keyinfo->base.block_length; - keys=keydata=totaldata=key_blocks=0; max_level=0; - if (chk_index(info,keyinfo,share->state.key_root[key],info->buff,&keys,1)) - DBUG_RETURN(-1); - if (keys != share->state.records) - { - print_error("Found %lu keys of %lu",(ulong) keys, - (ulong) share->state.records); - DBUG_RETURN(-1); - } - if (!key && (share->base.options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) - old_record_checksum=record_checksum; - else if (old_record_checksum != record_checksum) - { - if (key) - print_error("Key %u doesn't point at same records that key 1", - key+1); - else - print_error("Key 1 doesn't point at all records"); - DBUG_RETURN(-1); - } - length=(ulong) isam_key_length(info,keyinfo)*keys + key_blocks*2; - if (testflag & T_INFO && totaldata != 0L && keys != 0L) - printf("Key: %2d: Keyblocks used: %3d%% Packed: %4d%% Max levels: %2d\n", - key+1, - (int) (keydata*100.0/totaldata), - (int) ((long) (length-keydata)*100.0/(double) length), - max_level); - all_keydata+=keydata; all_totaldata+=totaldata; key_totlength+=length; - share->base.rec_per_key[key]= - unique_count ? ((share->state.records+unique_count/2)/ - unique_count) : 1L; - } - if (testflag & T_INFO) - { - if (all_totaldata != 0L && share->state.keys != 1) - printf("Total: Keyblocks used: %3d%% Packed: %4d%%\n\n", - (int) (all_keydata*100.0/all_totaldata), - (int) ((long) (key_totlength-all_keydata)*100.0/ - (double) key_totlength)); - else if (all_totaldata != 0L && share->state.keys) - puts(""); - } - if (key_file_blocks != share->state.key_file_length) - print_warning("Some data are unreferenced in keyfile"); - record_checksum-=init_checksum; /* Remove delete links */ - if (testflag & T_STATISTICS) - DBUG_RETURN(update_state_info(info,UPDATE_STAT)); - DBUG_RETURN(0); -} /* chk_key */ - - - /* Check if index is ok */ - -static int chk_index(N_INFO *info, N_KEYDEF *keyinfo, ulong page, uchar *buff, - ulong *keys,uint level) -{ - int flag; - uint used_length,comp_flag,nod_flag; - uchar key[N_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*endpos; - ulong next_page,record; - DBUG_ENTER("chk_index"); - DBUG_DUMP("buff",(byte*) buff,getint(buff)); - - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length))) - { - print_error("Not Enough memory"); - DBUG_RETURN(-1); - } - - if (keyinfo->base.flag & HA_NOSAME) - comp_flag=SEARCH_FIND; /* Not dupplicates */ - else - comp_flag=SEARCH_SAME; /* Keys in positionorder */ - nod_flag=test_if_nod(buff); - used_length=getint(buff); - keypos=buff+2+nod_flag; - endpos=buff+used_length; - - keydata+=used_length; totaldata+=keyinfo->base.block_length; /* INFO */ - key_blocks++; - if (level > max_level) - max_level=level; - - if (used_length > keyinfo->base.block_length) - { - print_error("Wrong pageinfo at page: %lu",(ulong) page); - goto err; - } - for ( ;; ) - { - if (nod_flag) - { - next_page=_nisam_kpos(nod_flag,keypos); - if (next_page > info->s->state.key_file_length || - (nod_flag && (next_page & (info->s->blocksize -1)))) - { - my_off_t max_length=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)); - print_error("Wrong pagepointer: %lu at page: %lu", - (ulong) next_page,(ulong) page); - - if (next_page+info->s->blocksize > max_length) - goto err; - info->s->state.key_file_length=(ulong) (max_length & - ~ (my_off_t) - (info->s->blocksize-1)); - } - if (!_nisam_fetch_keypage(info,keyinfo,next_page,temp_buff,0)) - { - print_error("Can't read key from filepos: %lu",(ulong) next_page); - goto err; - } - key_file_blocks+=keyinfo->base.block_length; - if (chk_index(info,keyinfo,next_page,temp_buff,keys,level+1)) - goto err; - } - if (keypos >= endpos || - (*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key) == 0) - break; - if ((*keys)++ && - (flag=_nisam_key_cmp(keyinfo->seg,info->lastkey,key,0,comp_flag)) >=0) - { - DBUG_DUMP("old",(byte*) info->lastkey, - _nisam_keylength(keyinfo,info->lastkey)); - DBUG_DUMP("new",(byte*) key,_nisam_keylength(keyinfo,key)); - - if (comp_flag == SEARCH_FIND && flag == 0) - print_error("Found dupplicated key at page %lu",(ulong) page); - else - print_error("Key in wrong position at page %lu",(ulong) page); - goto err; - } - if (testflag & T_STATISTICS) - { - if (*keys == 1L || - _nisam_key_cmp(keyinfo->seg,info->lastkey,key,0,SEARCH_FIND)) - unique_count++; - } - VOID(_nisam_move_key(keyinfo,(uchar*) info->lastkey,key)); - record= _nisam_dpos(info,nod_flag,keypos); - if (record >= info->s->state.data_file_length) - { - print_error("Found key at page %lu that points to record outside datafile",page); - DBUG_PRINT("test",("page: %lu record: %lu filelength: %lu", - (ulong) page,(ulong) record, - (ulong) info->s->state.data_file_length)); - DBUG_DUMP("key",(byte*) info->lastkey,info->s->base.max_key_length); - goto err; - } - record_checksum+=record; - } - if (keypos != endpos) - { - print_error("Keyblock size at page %lu is not correct. Block length: %d key length: %d",(ulong) page, used_length, (keypos - buff)); - goto err; - } - my_afree((byte*) temp_buff); - DBUG_RETURN(0); - err: - my_afree((byte*) temp_buff); - DBUG_RETURN(1); -} /* chk_index */ - - - /* Calculate a checksum of 1+2+3+4...N = N*(N+1)/2 without overflow */ - -static ulong calc_checksum(count) -ulong count; -{ - ulong sum,a,b; - DBUG_ENTER("calc_checksum"); - - sum=0; - a=count; b=count+1; - if (a & 1) - b>>=1; - else - a>>=1; - while (b) - { - if (b & 1) - sum+=a; - a<<=1; b>>=1; - } - DBUG_PRINT("exit",("sum: %lx",sum)); - DBUG_RETURN(sum); -} /* calc_checksum */ - - - /* Calc length of key in normal isam */ - -static uint isam_key_length( N_INFO *info, reg1 N_KEYDEF *keyinfo) -{ - uint length; - N_KEYSEG *keyseg; - DBUG_ENTER("isam_key_length"); - - length= info->s->rec_reflength; - for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++) - length+= keyseg->base.length; - - DBUG_PRINT("exit",("length: %d",length)); - DBUG_RETURN(length); -} /* key_length */ - - - /* Check that record-link is ok */ - -static int chk_data_link(info,extend) -reg1 N_INFO *info; -int extend; -{ - int error,got_error,flag; - uint key,left_length,b_type; - ulong records,del_blocks,used,empty,pos,splitts,start_recpos, - del_length,link_used,intern_record_checksum,start_block; - byte *record,*to; - N_KEYDEF *keyinfo; - BLOCK_INFO block_info; - DBUG_ENTER("chk_data_link"); - - if (! (info->s->base.options & (HA_OPTION_PACK_RECORD | - HA_OPTION_COMPRESS_RECORD)) && - ! extend) - DBUG_RETURN(0); - - if (!(testflag & T_SILENT)) - { - if (extend) - puts("- check records and index references"); - else - puts("- check record links"); - } - - if (!(record= (byte*) my_alloca(info->s->base.reclength))) - { - print_error("Not Enough memory"); - DBUG_RETURN(-1); - } - records=used=link_used=splitts=del_blocks=del_length= - intern_record_checksum=crc=0L; - LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to); - got_error=error=0; - empty=pos=info->s->pack.header_length; - - while (pos < info->s->state.data_file_length) - { - switch (info->s->data_file_type) { - case STATIC_RECORD: - if (my_b_read(&read_cache,(byte*) record,info->s->base.reclength)) - goto err; - start_recpos=pos; - pos+=info->s->base.reclength; - splitts++; - if (*record == '\0') - { - del_blocks++; - del_length+=info->s->base.reclength; - continue; /* Record removed */ - } - used+=info->s->base.reclength; - break; - case DYNAMIC_RECORD: - flag=block_info.second_read=0; - block_info.next_filepos=pos; - do - { - if (_nisam_read_cache(&read_cache,(byte*) block_info.header, - (start_block=block_info.next_filepos), - sizeof(block_info.header),test(! flag) | 2)) - goto err; - b_type=_nisam_get_block_info(&block_info,-1,start_block); - if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | - BLOCK_FATAL_ERROR)) - { - if (b_type & BLOCK_SYNC_ERROR) - { - if (flag) - { - print_error("Unexpected byte: %d at link: %lu", - (int) block_info.header[0],(ulong) start_block); - goto err2; - } - pos=block_info.filepos+block_info.block_len; - goto next; - } - if (b_type & BLOCK_DELETED) - { - if (block_info.block_len < info->s->base.min_block_length || - block_info.block_len-4 > (uint) info->s->base.max_pack_length) - { - print_error("Deleted block with impossible length %u at %lu", - block_info.block_len,(ulong) pos); - goto err2; - } - del_blocks++; - del_length+=block_info.block_len; - pos=block_info.filepos+block_info.block_len; - splitts++; - goto next; - } - print_error("Wrong bytesec: %d-%d-%d at linkstart: %lu", - block_info.header[0],block_info.header[1], - block_info.header[2],(ulong) start_block); - goto err2; - } - if (info->s->state.data_file_length < block_info.filepos+ - block_info.block_len) - { - print_error("Recordlink that points outside datafile at %lu", - (ulong) pos); - got_error=1; - break; - } - splitts++; - if (!flag++) /* First block */ - { - start_recpos=pos; - pos=block_info.filepos+block_info.block_len; - if (block_info.rec_len > (uint) info->s->base.max_pack_length) - { - print_error("Found too long record at %lu",(ulong) start_recpos); - got_error=1; - break; - } - if (info->s->base.blobs) - { - if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len))) - { - print_error("Not enough memory for blob at %lu", - (ulong) start_recpos); - got_error=1; - break; - } - } - else - to= info->rec_buff; - left_length=block_info.rec_len; - } - if (left_length < block_info.data_len) - { - print_error("Found too long record at %lu",(ulong) start_recpos); - got_error=1; break; - } - if (_nisam_read_cache(&read_cache,(byte*) to,block_info.filepos, - (uint) block_info.data_len, test(flag == 1))) - goto err; - to+=block_info.data_len; - link_used+= block_info.filepos-start_block; - used+= block_info.filepos - start_block + block_info.data_len; - empty+=block_info.block_len-block_info.data_len; - left_length-=block_info.data_len; - if (left_length) - { - if (b_type & BLOCK_LAST) - { - print_error("Record link to short for record at %lu", - (ulong) start_recpos); - got_error=1; - break; - } - if (info->s->state.data_file_length < block_info.next_filepos) - { - print_error("Found next-recordlink that points outside datafile at %lu", - (ulong) block_info.filepos); - got_error=1; - break; - } - } - } while (left_length); - if (! got_error) - { - if (_nisam_rec_unpack(info,record,info->rec_buff,block_info.rec_len) == - MY_FILE_ERROR) - { - print_error("Found wrong record at %lu",(ulong) start_recpos); - got_error=1; - } - if (testflag & (T_EXTEND | T_VERBOSE)) - { - if (_nisam_rec_check(info,record)) - { - print_error("Found wrong packed record at %lu", - (ulong) start_recpos); - got_error=1; - } - } - } - else if (!flag) - pos=block_info.filepos+block_info.block_len; - break; - case COMPRESSED_RECORD: - if (_nisam_read_cache(&read_cache,(byte*) block_info.header,pos, 3,1)) - goto err; - start_recpos=pos; - splitts++; - VOID(_nisam_pack_get_block_info(&block_info,info->s->pack.ref_length,-1, - start_recpos)); - pos=start_recpos+info->s->pack.ref_length+block_info.rec_len; - if (block_info.rec_len < (uint) info->s->min_pack_length || - block_info.rec_len > (uint) info->s->max_pack_length) - { - print_error("Found block with wrong recordlength: %d at %lu", - block_info.rec_len,(ulong) start_recpos); - got_error=1; - break; - } - if (_nisam_read_cache(&read_cache,(byte*) info->rec_buff, - block_info.filepos, block_info.rec_len,1)) - goto err; - if (_nisam_pack_rec_unpack(info,record,info->rec_buff,block_info.rec_len)) - { - print_error("Found wrong record at %lu",(ulong) start_recpos); - got_error=1; - } - crc^=_nisam_checksum(record,info->s->base.reclength); - link_used+=info->s->pack.ref_length; - used+=block_info.rec_len+info->s->pack.ref_length; - } - if (! got_error) - { - intern_record_checksum+=start_recpos; - records++; - if (testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0) - { - printf("%lu\r",(ulong) records); VOID(fflush(stdout)); - } - - if (extend) - { - for (key=0,keyinfo= info->s->keyinfo; key<info->s->state.keys; - key++,keyinfo++) - { - VOID(_nisam_make_key(info,key,info->lastkey,record,start_recpos)); - if (_nisam_search(info,keyinfo,info->lastkey,0,SEARCH_SAME, - info->s->state.key_root[key])) - { - print_error("Record at: %10lu Can't find key for index: %2d", - start_recpos,key+1); - if (error++ > MAXERR || !(testflag & T_VERBOSE)) - goto err2; - } - } - } - } - else - { - got_error=0; - if (error++ > MAXERR || !(testflag & T_VERBOSE)) - goto err2; - } - next:; /* Next record */ - } - if (testflag & T_WRITE_LOOP) - { - VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); - } - if (records != info->s->state.records) - { - print_error("Record-count is not ok; is %-10lu Should be: %lu", - (ulong) records,(ulong) info->s->state.records); - error=1; - } - else if (record_checksum != intern_record_checksum && info->s->state.keys) - { - print_error("Keypointers and records don't match"); - error=1; - } - if (used+empty+del_length != info->s->state.data_file_length) - { - print_warning("Found %lu record-data and %lu unused data and %lu deleted-data\nTotal %lu, Should be: %lu", - (ulong) used,(ulong) empty,(ulong) del_length, - (ulong) (used+empty+del_length), - (ulong) info->s->state.data_file_length); - } - if (del_blocks != info->s->state.del) - { - print_warning("Found %10lu deleted blocks Should be: %lu", - (ulong) del_blocks,(ulong) info->s->state.del); - } - if (splitts != info->s->state.splitt) - { - print_warning("Found %10lu parts Should be: %lu parts", - (ulong) splitts,(ulong) info->s->state.splitt); - } - if ((info->s->base.options & HA_OPTION_COMPRESS_RECORD) && - crc != info->s->state.uniq) - print_warning("Wrong checksum for records; Restore uncompressed table"); - - if (testflag & T_INFO) - { - if (warning_printed || error_printed) - puts(""); - if (used != 0 && ! error_printed) - { - printf("Records:%17lu M.recordlength:%8lu Packed:%14.0f%%\n", - records, (used-link_used)/records, - (info->s->base.blobs ? 0 : - (ulong_to_double(info->s->base.reclength*records)-used)/ - ulong_to_double(info->s->base.reclength*records)*100.0)); - printf("Recordspace used:%8.0f%% Empty space:%11d%% Blocks/Record: %6.2f\n", - (ulong_to_double(used-link_used)/ulong_to_double(used-link_used+empty)*100.0), - (!records ? 100 : (int) (ulong_to_double(del_length+empty)/used*100.0)), - ulong_to_double(splitts - del_blocks) / records); - } - printf("Record blocks:%12lu Delete blocks:%10lu\n", - splitts-del_blocks,del_blocks); - printf("Record data: %12lu Deleted data :%10lu\n", - used-link_used,del_length); - printf("Lost space: %12lu Linkdata: %10lu\n", - empty,link_used); - } - my_afree((gptr) record); - DBUG_RETURN (error); - err: - print_error("got error: %d when reading datafile",my_errno); - err2: - my_afree((gptr) record); - DBUG_RETURN(1); -} /* chk_data_link */ - - - /* Recover old table by reading each record and writing all keys */ - /* Save new datafile-name in temp_filename */ - -static int rep(info,name) -reg1 N_INFO *info; -my_string name; -{ - int error,got_error; - uint i; - ulong start_records,new_header_length,del; - File new_file; - ISAM_SHARE *share=info->s; - DBUG_ENTER("rep"); - - start_records=share->state.records; - new_header_length=(testflag & T_UNPACK) ? 0L : share->pack.header_length; - got_error=1; - new_file= -1; - if (!(testflag & T_SILENT)) - { - printf("- recovering ISAM-table '%s'\n",name); - printf("Data records: %lu\n",(ulong) share->state.records); - } - - VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,use_buffers,0,0)); - if (init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length, - READ_CACHE,share->pack.header_length,1,MYF(MY_WME))) - goto err; - if (!rep_quick) - if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length, - WRITE_CACHE, new_header_length, 1, - MYF(MY_WME | MY_WAIT_IF_FULL))) - goto err; - info->opt_flag|=WRITE_CACHE_USED; - sort_info.start_recpos=0; - sort_info.buff=0; sort_info.buff_length=0; - if (!(sort_info.record=(byte*) my_alloca((uint) share->base.reclength))) - { - print_error("Not Enough memory"); - goto err; - } - - if (!rep_quick) - { - if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT, - 2+4), - 0,tmpfile_createflag,MYF(0))) < 0) - { - print_error("Can't create new tempfile: '%s'",temp_filename); - goto err; - } - if (filecopy(new_file,info->dfile,0L,new_header_length,"datafile-header")) - goto err; - share->state.dellink= NI_POS_ERROR; - info->rec_cache.file=new_file; - if (testflag & T_UNPACK) - share->base.options&= ~HA_OPTION_COMPRESS_RECORD; - } - - sort_info.info=info; - sort_info.pos=sort_info.max_pos=share->pack.header_length; - sort_info.filepos=new_header_length; - read_cache.end_of_file=sort_info.filelength=(ulong) - my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)); - sort_info.dupp=0; - sort_info.fix_datafile= (my_bool) (! rep_quick); - sort_info.max_records=LONG_MAX; - if ((sort_info.new_data_file_type=share->data_file_type) == - COMPRESSED_RECORD && testflag & T_UNPACK) - { - if (share->base.options & HA_OPTION_PACK_RECORD) - sort_info.new_data_file_type = DYNAMIC_RECORD; - else - sort_info.new_data_file_type = STATIC_RECORD; - } - - del=share->state.del; - share->state.records=share->state.del=share->state.empty= - share->state.splitt=0; - info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - for (i=0 ; i < N_MAXKEY ; i++) - share->state.key_del[i]=share->state.key_root[i]= NI_POS_ERROR; - share->state.key_file_length=share->base.keystart; - - lock_memory(); /* Everything is alloced */ - while (!(error=sort_get_next_record())) - { - if (writekeys(info,(byte*) sort_info.record,sort_info.filepos)) - { - if (my_errno != HA_ERR_FOUND_DUPP_KEY) goto err; - DBUG_DUMP("record",(byte*) sort_info.record,share->base.pack_reclength); - print_info("Dupplicate key %2d for record at %10lu against new record at %10lu",info->errkey+1,sort_info.start_recpos,info->int_pos); - if (testflag & T_VERBOSE) - { - VOID(_nisam_make_key(info,(uint) info->errkey,info->lastkey, - sort_info.record,0L)); - _nisam_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey); - } - sort_info.dupp++; - if (rep_quick == 1) - { - error_printed=1; - goto err; - } - continue; - } - if (sort_write_record()) - goto err; - } - if (error > 0 || write_data_suffix(info) || - flush_io_cache(&info->rec_cache) || read_cache.error < 0) - goto err; - - if (testflag & T_WRITE_LOOP) - { - VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); - } - if (my_chsize(share->kfile, share->state.key_file_length, 0, MYF(0))) - { - print_warning("Can't change size of indexfile, error: %d",my_errno); - goto err; - } - - if (rep_quick && del+sort_info.dupp != share->state.del) - { - print_error("Couldn't fix table with quick recovery: Found wrong number of deleted records"); - print_error("Run recovery again without -q"); - got_error=1; - goto err; - } - - if (!rep_quick) - { - info->dfile=new_file; - share->state.data_file_length=sort_info.filepos; - share->state.splitt=share->state.records; /* Only hole records */ - out_flag|=O_NEW_DATA; /* Data in new file */ - share->state.version=(ulong) time((time_t*) 0); /* Force reopen */ - } - else - share->state.data_file_length=sort_info.max_pos; - - if (!(testflag & T_SILENT)) - { - if (start_records != share->state.records) - printf("Data records: %lu\n",(ulong) share->state.records); - if (sort_info.dupp) - print_warning("%lu records have been removed",(ulong) sort_info.dupp); - } - - got_error=0; -err: - if (got_error) - { - if (! error_printed) - print_error("%d for record at pos %lu",my_errno, - (ulong) sort_info.start_recpos); - if (new_file >= 0) - { - VOID(my_close(new_file,MYF(0))); - VOID(my_delete(temp_filename,MYF(MY_WME))); - } - } - if (sort_info.record) - { - my_afree(sort_info.record); - } - my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); - VOID(end_io_cache(&read_cache)); - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - VOID(end_io_cache(&info->rec_cache)); - got_error|=flush_blocks(share->kfile); - if (!got_error && testflag & T_UNPACK) - { - share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; - share->pack.header_length=0; - share->data_file_type=sort_info.new_data_file_type; - } - DBUG_RETURN(got_error); -} /* rep */ - - - /* Uppdaterar nyckelfilen i samband med reparation */ - -static int writekeys(register N_INFO *info,byte *buff,ulong filepos) -{ - register uint i; - uchar *key; - DBUG_ENTER("writekeys"); - - key=info->lastkey+info->s->base.max_key_length; - for (i=0 ; i < info->s->state.keys ; i++) - { - VOID(_nisam_make_key(info,i,key,buff,filepos)); - if (_nisam_ck_write(info,i,key)) goto err; - } - DBUG_RETURN(0); - - err: - if (my_errno == HA_ERR_FOUND_DUPP_KEY) - { - info->errkey=(int) i; /* This key was found */ - while ( i-- > 0 ) - { - VOID(_nisam_make_key(info,i,key,buff,filepos)); - if (_nisam_ck_delete(info,i,key)) break; - } - } - DBUG_PRINT("error",("errno: %d",my_errno)); - DBUG_RETURN(-1); -} /* writekeys */ - - - /* Write info about table */ - -static void descript(info,name) -reg1 N_INFO *info; -my_string name; -{ - uint key,field,start,len; - reg3 N_KEYDEF *keyinfo; - reg2 N_KEYSEG *keyseg; - reg4 const char *text; - char buff[40],length[10],*pos,*end; - enum en_fieldtype type; - ISAM_SHARE *share=info->s; - DBUG_ENTER("describe"); - - printf("\nISAM file: %s\n",name); - if (testflag & T_VERBOSE) - { - printf("Isam-version: %d\n",(int) share->state.header.file_version[3]); - if (share->base.create_time) - { - get_date(buff,1,share->base.create_time); - printf("Creation time: %s\n",buff); - } - if (share->base.isamchk_time) - { - get_date(buff,1,share->base.isamchk_time); - printf("Recover time: %s\n",buff); - } - } - printf("Data records: %10lu Deleted blocks: %10lu\n", - share->state.records,share->state.del); - if (testflag & T_SILENT) - DBUG_VOID_RETURN; /* This is enough */ - - if (testflag & T_VERBOSE) - { -#ifdef USE_RELOC - printf("Init-relocation: %10lu\n",share->base.reloc); -#endif - printf("Datafile Parts: %10lu Deleted data: %10lu\n", - share->state.splitt,share->state.empty); - printf("Datafile pointer (bytes):%6d Keyfile pointer (bytes):%6d\n", - share->rec_reflength,share->base.key_reflength); - if (info->s->base.reloc == 1L && info->s->base.records == 1L) - puts("This is a one-record table"); - else - { - if (share->base.max_data_file_length != NI_POS_ERROR || - share->base.max_key_file_length != NI_POS_ERROR) - printf("Max datafile length: %10lu Max keyfile length: %10lu\n", - share->base.max_data_file_length-1, - share->base.max_key_file_length-1); - } - } - - printf("Recordlength: %10d\n",(int) share->base.reclength); - VOID(fputs("Record format: ",stdout)); - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - puts("Compressed"); - else if (share->base.options & HA_OPTION_PACK_RECORD) - puts("Packed"); - else - puts("Fixed length"); - if (share->state.keys != share->base.keys) - printf("Using only %d keys of %d possibly keys\n",share->state.keys, - share->base.keys); - - puts("\ntable description:"); - printf("Key Start Len Index Type"); - if (testflag & T_VERBOSE) - printf(" Root Blocksize Rec/key"); - VOID(putchar('\n')); - - for (key=0, keyinfo= &share->keyinfo[0] ; key < share->base.keys; - key++,keyinfo++) - { - keyseg=keyinfo->seg; - if (keyinfo->base.flag & HA_NOSAME) text="unique "; - else text="multip."; - - pos=buff; - if (keyseg->base.flag & HA_REVERSE_SORT) - *pos++ = '-'; - pos=strmov(pos,type_names[keyseg->base.type]); - *pos++ = ' '; - *pos=0; - if (keyinfo->base.flag & HA_PACK_KEY) - pos=strmov(pos,packed_txt); - if (keyseg->base.flag & HA_SPACE_PACK) - pos=strmov(pos,diff_txt); - printf("%-4d%-6d%-3d %-8s%-21s", - key+1,keyseg->base.start+1,keyseg->base.length,text,buff); - if (testflag & T_VERBOSE) - printf(" %9ld %9d %9ld", - share->state.key_root[key],keyinfo->base.block_length, - share->base.rec_per_key[key]); - VOID(putchar('\n')); - while ((++keyseg)->base.type) - { - pos=buff; - if (keyseg->base.flag & HA_REVERSE_SORT) - *pos++ = '-'; - pos=strmov(pos,type_names[keyseg->base.type]); - *pos++= ' '; - if (keyseg->base.flag & HA_SPACE_PACK) - pos=strmov(pos,diff_txt); - *pos=0; - printf(" %-6d%-3d %-24s\n", - keyseg->base.start+1,keyseg->base.length,buff); - } - } - if (verbose > 1) - { - printf("\nField Start Length Type"); - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - printf(" Huff tree Bits"); - VOID(putchar('\n')); - if (verbose > 2 && share->base.pack_bits) - printf("- %-7d%-35s\n",share->base.pack_bits,"bit field"); - - start=1; - for (field=0 ; field < share->base.fields ; field++) - { - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - type=share->rec[field].base_type; - else - type=(enum en_fieldtype) share->rec[field].base.type; - end=strmov(buff,field_pack[type]); -#ifndef NOT_PACKED_DATABASES - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - { - if (share->rec[field].pack_type & PACK_TYPE_SELECTED) - end=strmov(end,", not_always"); - if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS) - end=strmov(end,", no empty"); - if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL) - { - sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits); - end=strend(end); - } - } - if (buff[0] == ',') - strmov(buff,buff+2); -#endif - len=(uint) (int10_to_str((long) share->rec[field].base.length,length,10) - - length); - if (type == FIELD_BLOB) - { - length[len]='+'; - VOID(int10_to_str((long) sizeof(char*),length+len+1,10)); - } - printf("%-6d%-6d%-7s%-35s",field+1,start,length,buff); -#ifndef NOT_PACKED_DATABASES - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - { - if (share->rec[field].huff_tree) - printf("%3d %2d", - (uint) (share->rec[field].huff_tree-share->decode_trees)+1, - share->rec[field].huff_tree->quick_table_bits); - } -#endif - VOID(putchar('\n')); - start+=share->rec[field].base.length; - if (type == FIELD_BLOB) - start+=sizeof(char*); - } - } - DBUG_VOID_RETURN; -} /* describe */ - - - /* Change all key-pointers that points to a records */ - -static int movepoint(info,record,oldpos,newpos,prot_key) -register N_INFO *info; -byte *record; -ulong oldpos,newpos; -uint prot_key; -{ - register uint i; - uchar *key; - DBUG_ENTER("movepoint"); - - key=info->lastkey+info->s->base.max_key_length; - for (i=0 ; i < info->s->state.keys; i++) - { - if (i != prot_key) - { - VOID(_nisam_make_key(info,i,key,record,oldpos)); - if (info->s->keyinfo[i].base.flag & HA_NOSAME) - { /* Change pointer direct */ - uint nod_flag; - N_KEYDEF *keyinfo; - keyinfo=info->s->keyinfo+i; - if (_nisam_search(info,keyinfo,key,USE_HOLE_KEY, - (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF), - info->s->state.key_root[i])) - DBUG_RETURN(-1); - nod_flag=test_if_nod(info->buff); - _nisam_dpointer(info,info->int_keypos-nod_flag- - info->s->rec_reflength,newpos); - if (_nisam_write_keypage(info,keyinfo,info->int_pos,info->buff)) - DBUG_RETURN(-1); - } - else - { /* Change old key to new */ - if (_nisam_ck_delete(info,i,key)) - DBUG_RETURN(-1); - VOID(_nisam_make_key(info,i,key,record,newpos)); - if (_nisam_ck_write(info,i,key)) - DBUG_RETURN(-1); - } - } - } - DBUG_RETURN(0); -} /* movepoint */ - - - /* Tell system that we want all memory for our cache */ - -static void lock_memory(void) -{ -#ifdef SUN_OS /* Key-cacheing thrases on sun 4.1 */ - int success; - - success = mlockall(MCL_CURRENT); /* or plock(DATLOCK); */ - - if (geteuid() == 0 && success != 0) - print_warning("Failed to lock memory. errno %d",my_errno); -#endif -} /* lock_memory */ - - - /* Flush all changed blocks to disk */ - -static int flush_blocks(file) -File file; -{ - if (flush_key_blocks(dflt_key_cache,file,FLUSH_RELEASE)) - { - print_error("%d when trying to write bufferts",my_errno); - return(1); - } - end_key_cache(dflt_key_cache,1); - return 0; -} /* flush_blocks */ - - - /* Sort records according to one key */ - -static int sort_records(info,name,sort_key,write_info) -register N_INFO *info; -my_string name; -uint sort_key; -int write_info; -{ - int got_error; - uint key; - N_KEYDEF *keyinfo; - File new_file; - uchar *temp_buff; - ulong old_record_count; - ISAM_SHARE *share=info->s; - DBUG_ENTER("sort_records"); - - keyinfo= &share->keyinfo[sort_key]; - got_error=1; - temp_buff=0; record_buff=0; - new_file= -1; - - if (sort_key >= share->state.keys) - { - print_error("Can't sort table '%s' on key %d. It has only %d keys", - name,sort_key+1,share->state.keys); - error_printed=0; - DBUG_RETURN(-1); - } - if (!(testflag & T_SILENT)) - { - printf("- Sorting records in ISAM-table '%s'\n",name); - if (write_info) - printf("Data records: %7lu Deleted: %7lu\n", - share->state.records,share->state.del); - } - if (share->state.key_root[sort_key] == NI_POS_ERROR) - DBUG_RETURN(0); /* Nothing to do */ - - init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,use_buffers, 0, 0); - if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length, - WRITE_CACHE,share->pack.header_length,1, - MYF(MY_WME | MY_WAIT_IF_FULL))) - goto err; - info->opt_flag|=WRITE_CACHE_USED; - - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length))) - { - print_error("Not Enough memory"); - goto err; - } - if (!(record_buff=(byte*) my_alloca((uint) share->base.reclength))) - { - print_error("Not Enough memory"); - goto err; - } - if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT,2+4), - 0,tmpfile_createflag,MYF(0))) <= 0) - { - print_error("Can't create new tempfile: '%s'",temp_filename); - goto err; - } - if (filecopy(new_file,info->dfile,0L,share->pack.header_length, - "datafile-header")) - goto err; - info->rec_cache.file=new_file; /* Use this file for cacheing*/ - - lock_memory(); - for (key=0 ; key < share->state.keys ; key++) - share->keyinfo[key].base.flag|= HA_SORT_ALLOWS_SAME; - - if (my_pread(share->kfile,(byte*) temp_buff, - (uint) keyinfo->base.block_length, - share->state.key_root[sort_key], - MYF(MY_NABP+MY_WME))) - { - print_error("Can't read indexpage from filepos: %lu", - (ulong) share->state.key_root[sort_key]); - goto err; - } - - /* Setup param for sort_write_record */ - bzero((char*) &sort_info,sizeof(sort_info)); - sort_info.info=info; - sort_info.new_data_file_type=share->data_file_type; - sort_info.fix_datafile=1; - sort_info.filepos=share->pack.header_length; - sort_info.record=record_buff; - old_record_count=share->state.records; - share->state.records=0; - - if (sort_record_index(info,keyinfo,share->state.key_root[sort_key],temp_buff, - sort_key,new_file) || - write_data_suffix(info) || - flush_io_cache(&info->rec_cache)) - goto err; - - if (share->state.records != old_record_count) - { - print_error("found %lu of %lu records", - (ulong) share->state.records,(ulong) old_record_count); - goto err; - } - - /* Put same locks as old file */ - if (lock_file(new_file,0L,F_WRLCK,"tempfile",temp_filename)) - goto err; - VOID(lock_file(info->dfile,0L,F_UNLCK,"datafile of",name)); - VOID(my_close(info->dfile,MYF(MY_WME))); - out_flag|=O_NEW_DATA; /* Data in new file */ - - info->dfile=new_file; /* Use new indexfile */ - share->state.del=share->state.empty=0; - share->state.dellink= NI_POS_ERROR; - share->state.data_file_length=sort_info.filepos; - share->state.splitt=share->state.records; /* Only hole records */ - share->state.version=(ulong) time((time_t*) 0); - - info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - - if (testflag & T_WRITE_LOOP) - { - VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); - } - got_error=0; - -err: - if (got_error && new_file >= 0) - { - VOID(my_close(new_file,MYF(MY_WME))); - VOID(my_delete(temp_filename,MYF(MY_WME))); - } - if (temp_buff) - { - my_afree((gptr) temp_buff); - } - if (record_buff) - { - my_afree(record_buff); - } - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - VOID(end_io_cache(&info->rec_cache)); - share->base.sortkey=sort_key; - DBUG_RETURN(flush_blocks(share->kfile) | got_error); -} /* sort_records */ - - - /* Sort records recursive using one index */ - -static int sort_record_index(info,keyinfo,page,buff,sort_key,new_file) -N_INFO *info; -N_KEYDEF *keyinfo; -ulong page; -uchar *buff; -uint sort_key; -File new_file; -{ - uint nod_flag,used_length; - uchar *temp_buff,*keypos,*endpos; - ulong next_page,rec_pos; - uchar lastkey[N_MAX_KEY_BUFF]; - DBUG_ENTER("sort_record_index"); - - nod_flag=test_if_nod(buff); - temp_buff=0; - - if (nod_flag) - { - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length))) - { - print_error("Not Enough memory"); - DBUG_RETURN(-1); - } - } - used_length=getint(buff); - keypos=buff+2+nod_flag; - endpos=buff+used_length; - for ( ;; ) - { - _sanity(__FILE__,__LINE__); - if (nod_flag) - { - next_page=_nisam_kpos(nod_flag,keypos); - if (my_pread(info->s->kfile,(byte*) temp_buff, - (uint) keyinfo->base.block_length, next_page, - MYF(MY_NABP+MY_WME))) - { - print_error("Can't read keys from filepos: %lu",(ulong) next_page); - goto err; - } - if (sort_record_index(info,keyinfo,next_page,temp_buff,sort_key, - new_file)) - goto err; - } - _sanity(__FILE__,__LINE__); - if (keypos >= endpos || - (*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey) == 0) - break; - rec_pos= _nisam_dpos(info,nod_flag,keypos); - - if ((*info->s->read_rnd)(info,record_buff,rec_pos,0)) - { - print_error("%d when reading datafile",my_errno); - goto err; - } - if (rec_pos != sort_info.filepos) - { - _nisam_dpointer(info,keypos-nod_flag-info->s->rec_reflength, - sort_info.filepos); - if (movepoint(info,record_buff,rec_pos,sort_info.filepos,sort_key)) - { - print_error("%d when updating key-pointers",my_errno); - goto err; - } - } - if (sort_write_record()) - goto err; - } - bzero((byte*) buff+used_length,keyinfo->base.block_length-used_length); - if (my_pwrite(info->s->kfile,(byte*) buff,(uint) keyinfo->base.block_length, - page,MYF_RW)) - { - print_error("%d when updating keyblock",my_errno); - goto err; - } - if (temp_buff) - my_afree((gptr) temp_buff); - DBUG_RETURN(0); -err: - if (temp_buff) - my_afree((gptr) temp_buff); - DBUG_RETURN(1); -} /* sort_record_index */ - - - /* Sort index for more efficent reads */ - -static int sort_index(info,name) -register N_INFO *info; -my_string name; -{ - reg2 uint key; - reg1 N_KEYDEF *keyinfo; - File new_file; - ulong index_pos[N_MAXKEY]; - DBUG_ENTER("sort_index"); - - if (!(testflag & T_SILENT)) - printf("- Sorting index for ISAM-table '%s'\n",name); - - if ((new_file=my_create(fn_format(temp_filename,name,"",INDEX_TMP_EXT,2+4), - 0,tmpfile_createflag,MYF(0))) <= 0) - { - print_error("Can't create new tempfile: '%s'",temp_filename); - DBUG_RETURN(-1); - } - if (filecopy(new_file,info->s->kfile,0L,(ulong) info->s->base.keystart, - "headerblock")) - goto err; - - new_file_pos=info->s->base.keystart; - for (key= 0,keyinfo= &info->s->keyinfo[0]; key < info->s->state.keys ; - key++,keyinfo++) - { - if (info->s->state.key_root[key] != NI_POS_ERROR) - { - index_pos[key]=new_file_pos; /* Write first block here */ - if (!_nisam_fetch_keypage(info,keyinfo,info->s->state.key_root[key], - info->buff,0)) - { - print_error("Can't read indexpage from filepos: %lu", - (ulong) info->s->state.key_root[key]); - goto err; - } - if (sort_one_index(info,keyinfo,info->buff,new_file)) - goto err; - } - else - index_pos[key]= NI_POS_ERROR; /* No blocks */ - } - - /* Put same locks as old file */ - if (lock_file(new_file,0L,F_WRLCK,"tempfile",temp_filename)) - goto err; - info->s->state.version=(ulong) time((time_t*) 0); - VOID(_nisam_writeinfo(info,1)); /* This unlocks table */ - VOID(my_close(info->s->kfile,MYF(MY_WME))); - out_flag|=O_NEW_INDEX; /* Data in new file */ - - info->s->kfile=new_file; - info->s->state.key_file_length=new_file_pos; - info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - for (key=0 ; key < info->s->state.keys ; key++) - { - info->s->state.key_root[key]=index_pos[key]; - info->s->state.key_del[key]= NI_POS_ERROR; - } - DBUG_RETURN(0); - -err: - VOID(my_close(new_file,MYF(MY_WME))); - VOID(my_delete(temp_filename,MYF(MY_WME))); - DBUG_RETURN(-1); -} /* sort_index */ - - - /* Sort records recursive using one index */ - -static int sort_one_index(info,keyinfo,buff,new_file) -N_INFO *info; -N_KEYDEF *keyinfo; -uchar *buff; -File new_file; -{ - uint length,nod_flag,used_length; - uchar *temp_buff,*keypos,*endpos; - ulong new_page_pos,next_page; - DBUG_ENTER("sort_one_index"); - - temp_buff=0; - new_page_pos=new_file_pos; - new_file_pos+=keyinfo->base.block_length; - - if ((nod_flag=test_if_nod(buff))) - { - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length))) - { - print_error("Not Enough memory"); - DBUG_RETURN(-1); - } - - used_length=getint(buff); - keypos=buff+2+nod_flag; - endpos=buff+used_length; - for ( ;; ) - { - if (nod_flag) - { - next_page=_nisam_kpos(nod_flag,keypos); - _nisam_kpointer(info,keypos-nod_flag,new_file_pos); /* Save new pos */ - if (!_nisam_fetch_keypage(info,keyinfo,next_page,temp_buff,0)) - { - print_error("Can't read keys from filepos: %lu", - (ulong) next_page); - goto err; - } - if (sort_one_index(info,keyinfo,temp_buff,new_file)) - goto err; - } - if (keypos >= endpos || - ((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,info->lastkey)) == 0) - break; - } - my_afree((gptr) temp_buff); - } - - /* Fill block with zero and write it to new file */ - - length=getint(buff); - bzero((byte*) buff+length,keyinfo->base.block_length-length); - if (my_pwrite(new_file,(byte*) buff,(uint) keyinfo->base.block_length, - new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL))) - { - print_error("Can't write indexblock, error: %d",my_errno); - goto err; - } - DBUG_RETURN(0); -err: - if (temp_buff) - my_afree((gptr) temp_buff); - DBUG_RETURN(1); -} /* sort_one_index */ - - - /* Change to use new file */ - /* Copy stats from old file to new file, deletes orginal and */ - /* changes new file name to old file name */ - -static int change_to_newfile(filename,old_ext,new_ext) -const char *filename,*old_ext,*new_ext; -{ - char old_filename[FN_REFLEN],new_filename[FN_REFLEN]; - - return my_redel(fn_format(old_filename,filename,"",old_ext,2+4), - fn_format(new_filename,filename,"",new_ext,2+4), - MYF(MY_WME+MY_LINK_WARNING)); -} /* change_to_newfile */ - - - /* Locks a hole file */ - /* Gives error-message if file can't be locked */ - -static int lock_file(file,start,lock_type,filetype,filename) -File file; -ulong start; -int lock_type; -const char *filetype,*filename; -{ -#ifndef NO_LOCKING - if (my_lock(file,lock_type,start,F_TO_EOF, - testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) : - MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT))) - { - print_error(" %d when %s %s '%s'",my_errno, - lock_type == F_UNLCK ? "unlocking": "locking", - filetype,filename); - error_printed=2; /* Don't give that data is crashed */ - return 1; - } -#endif - return 0; -} /* lock_file */ - - - /* Copy a block between two files */ - -static int filecopy(File to,File from,ulong start,ulong length, - const char *type) -{ - char tmp_buff[IO_SIZE],*buff; - ulong buff_length; - DBUG_ENTER("filecopy"); - - buff_length=min(write_buffer_length,length); - if (!(buff=my_malloc(buff_length,MYF(0)))) - { - buff=tmp_buff; buff_length=IO_SIZE; - } - - VOID(my_seek(from,start,MY_SEEK_SET,MYF(0))); - while (length > buff_length) - { - if (my_read(from,(byte*) buff,buff_length,MYF(MY_NABP)) || - my_write(to,(byte*) buff,buff_length,MYF(MY_NABP | MY_WAIT_IF_FULL))) - goto err; - length-= buff_length; - } - if (my_read(from,(byte*) buff,(uint) length,MYF(MY_NABP)) || - my_write(to,(byte*) buff,(uint) length,MYF(MY_NABP | MY_WAIT_IF_FULL))) - goto err; - if (buff != tmp_buff) - my_free(buff,MYF(0)); - DBUG_RETURN(0); -err: - if (buff != tmp_buff) - my_free(buff,MYF(0)); - print_error("Can't copy %s to tempfile, error %d",type,my_errno); - DBUG_RETURN(1); -} - - - /* Fix table using sorting */ - /* saves new table in temp_filename */ - -static int rep_by_sort(info,name) -reg1 N_INFO *info; -my_string name; -{ - int got_error; - uint i,length; - ulong start_records,new_header_length,del; - File new_file; - SORT_PARAM sort_param; - ISAM_SHARE *share=info->s; - DBUG_ENTER("rep_by_sort"); - - start_records=share->state.records; - got_error=1; - new_file= -1; - new_header_length=(testflag & T_UNPACK) ? 0 : share->pack.header_length; - if (!(testflag & T_SILENT)) - { - printf("- recovering ISAM-table '%s'\n",name); - printf("Data records: %lu\n",(ulong) start_records); - } - bzero((char*) &sort_info,sizeof(sort_info)); - if (!(sort_info.key_block=alloc_key_blocks((uint) sort_key_blocks, - share->base.max_block)) - || init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length, - READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) || - (! rep_quick && - init_io_cache(&info->rec_cache,info->dfile,(uint) write_buffer_length, - WRITE_CACHE,new_header_length,1, - MYF(MY_WME | MY_WAIT_IF_FULL)))) - goto err; - sort_info.key_block_end=sort_info.key_block+sort_key_blocks; - info->opt_flag|=WRITE_CACHE_USED; - info->rec_cache.file=info->dfile; /* for sort_delete_record */ - - if (!(sort_info.record=(byte*) my_alloca((uint) share->base.reclength))) - { - print_error("Not enough memory for extra record"); - goto err; - } - if (!rep_quick) - { - if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT, - 2+4), - 0,tmpfile_createflag,MYF(0))) < 0) - { - print_error("Can't create new tempfile: '%s'",temp_filename); - goto err; - } - if (filecopy(new_file,info->dfile,0L,new_header_length,"datafile-header")) - goto err; - if (testflag & T_UNPACK) - share->base.options&= ~HA_OPTION_COMPRESS_RECORD; - share->state.dellink= NI_POS_ERROR; - info->rec_cache.file=new_file; - } - - info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - for (i=0 ; i < N_MAXKEY ; i++) - share->state.key_del[i]=share->state.key_root[i]= NI_POS_ERROR; - share->state.key_file_length=share->base.keystart; - - sort_info.info=info; - if ((sort_info.new_data_file_type=share->data_file_type) == - COMPRESSED_RECORD && testflag & T_UNPACK) - { - if (share->base.options & HA_OPTION_PACK_RECORD) - sort_info.new_data_file_type = DYNAMIC_RECORD; - else - sort_info.new_data_file_type = STATIC_RECORD; - } - - sort_info.filepos=new_header_length; - sort_info.dupp=0; - read_cache.end_of_file=sort_info.filelength= - (ulong) my_seek(read_cache.file,0L,MY_SEEK_END,MYF(0)); - - if (share->data_file_type == DYNAMIC_RECORD) - length=max(share->base.min_pack_length+1,share->base.min_block_length); - else if (share->data_file_type == COMPRESSED_RECORD) - length=share->base.min_block_length; - else - length=share->base.reclength; - sort_param.max_records=sort_info.max_records=sort_info.filelength/length+1; - sort_param.key_cmp=sort_key_cmp; - sort_param.key_write=sort_key_write; - sort_param.key_read=sort_key_read; - sort_param.lock_in_memory=lock_memory; - del=share->state.del; - - for (sort_info.key=0 ; sort_info.key < share->state.keys ; sort_info.key++) - { - if ((!(testflag & T_SILENT))) - printf ("- Fixing index %d\n",sort_info.key+1); - sort_info.max_pos=sort_info.pos=share->pack.header_length; - sort_info.keyinfo=share->keyinfo+sort_info.key; - sort_info.keyseg=sort_info.keyinfo->seg; - sort_info.fix_datafile= (my_bool) (sort_info.key == 0 && ! rep_quick); - sort_info.unique=0; - sort_param.key_length=share->rec_reflength; - for (i=0 ; sort_info.keyseg[i].base.type ; i++) - sort_param.key_length+=sort_info.keyseg[i].base.length+ - (sort_info.keyseg[i].base.flag & HA_SPACE_PACK ? 1 : 0); - share->state.records=share->state.del=share->state.empty=share->state.splitt=0; - - if (_create_index_by_sort(&sort_param, - (pbool) (!(testflag & T_VERBOSE)), - (uint) sort_buffer_length)) - goto err; - /* Set for next loop */ - sort_param.max_records=sort_info.max_records=share->state.records; - share->base.rec_per_key[sort_info.key]= - sort_info.unique ? ((sort_info.max_records+sort_info.unique/2)/ - sort_info.unique) - : 1L; - - if (sort_info.fix_datafile) - { - info->dfile=new_file; - share->state.data_file_length=sort_info.filepos; - share->state.splitt=share->state.records; /* Only hole records */ - share->state.version=(ulong) time((time_t*) 0); - out_flag|=O_NEW_DATA; /* Data in new file */ - read_cache.end_of_file=sort_info.filepos; - if (write_data_suffix(info) || end_io_cache(&info->rec_cache)) - goto err; - share->data_file_type=sort_info.new_data_file_type; - share->pack.header_length=new_header_length; - } - else - share->state.data_file_length=sort_info.max_pos; - - if (flush_pending_blocks()) - goto err; - - read_cache.file=info->dfile; /* re-init read cache */ - reinit_io_cache(&read_cache,READ_CACHE,share->pack.header_length,1,1); - } - - if (testflag & T_WRITE_LOOP) - { - VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); - } - - if (rep_quick && del+sort_info.dupp != share->state.del) - { - print_error("Couldn't fix table with quick recovery: Found wrong number of deleted records"); - print_error("Run recovery again without -q"); - got_error=1; - goto err; - } - - if (rep_quick != 1) - { - ulong skr=share->state.data_file_length+ - (share->base.options & HA_OPTION_COMPRESS_RECORD ? - MEMMAP_EXTRA_MARGIN : 0); -#ifdef USE_RELOC - if (share->data_file_type == STATIC_RECORD && - skr < share->base.reloc*share->base.min_pack_length) - skr=share->base.reloc*share->base.min_pack_length; -#endif - if (skr != sort_info.filelength) - if (my_chsize(info->dfile, skr, 0, MYF(0))) - print_warning("Can't change size of datafile, error: %d",my_errno); - } - if (my_chsize(share->kfile, share->state.key_file_length, 0, MYF(0))) - print_warning("Can't change size of indexfile, error: %d",my_errno); - - if (!(testflag & T_SILENT)) - { - if (start_records != share->state.records) - printf("Data records: %lu\n",(ulong) share->state.records); - if (sort_info.dupp) - print_warning("%lu records have been removed",(ulong) sort_info.dupp); - } - got_error=0; - -err: - if (got_error) - { - if (! error_printed) - print_error("%d when fixing table",my_errno); - if (new_file >= 0) - { - VOID(end_io_cache(&info->rec_cache)); - VOID(my_close(new_file,MYF(0))); - VOID(my_delete(temp_filename,MYF(MY_WME))); - } - } - if (sort_info.key_block) - my_free((gptr) sort_info.key_block,MYF(0)); - if (sort_info.record) - { - my_afree(sort_info.record); - } - VOID(end_io_cache(&read_cache)); - VOID(end_io_cache(&info->rec_cache)); - info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - if (!got_error && testflag & T_UNPACK) - { - share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; - share->pack.header_length=0; - } - DBUG_RETURN(got_error); -} /* rep_by_sort */ - - - /* Read next record and return next key */ - -static int sort_key_read(key) -void *key; -{ - int error; - N_INFO *info; - DBUG_ENTER("sort_key_read"); - - info=sort_info.info; - - if ((error=sort_get_next_record())) - DBUG_RETURN(error); - if (info->s->state.records == sort_info.max_records) - { - print_error("Found too many records; Can`t continue"); - DBUG_RETURN(1); - } - VOID(_nisam_make_key(info,sort_info.key,key,sort_info.record, - sort_info.filepos)); - DBUG_RETURN(sort_write_record()); -} /* sort_key_read */ - - - /* Read next record from file using parameters in sort_info */ - /* Return -1 if end of file, 0 if ok and > 0 if error */ - -static int sort_get_next_record() -{ - int searching; - uint found_record,b_type,left_length; - ulong pos; - byte *to; - BLOCK_INFO block_info; - N_INFO *info; - ISAM_SHARE *share; - DBUG_ENTER("sort_get_next_record"); - - info=sort_info.info; - share=info->s; - switch (share->data_file_type) { - case STATIC_RECORD: - for (;;) - { - if (my_b_read(&read_cache,sort_info.record,share->base.reclength)) - DBUG_RETURN(-1); - sort_info.start_recpos=sort_info.pos; - if (!sort_info.fix_datafile) - sort_info.filepos=sort_info.pos; - sort_info.max_pos=(sort_info.pos+=share->base.reclength); - share->state.splitt++; - if (*sort_info.record) - DBUG_RETURN(0); - if (!sort_info.fix_datafile) - { - share->state.del++; - share->state.empty+=share->base.reclength; - } - } - case DYNAMIC_RECORD: - LINT_INIT(to); - pos=sort_info.pos; - searching=(sort_info.fix_datafile && (testflag & T_EXTEND)); - for (;;) - { - found_record=block_info.second_read= 0; - left_length=1; - do - { - if (pos > sort_info.max_pos) - sort_info.max_pos=pos; - if (found_record && pos == search_after_block) - print_info("Block: %lu used by record at %lu", - search_after_block, - sort_info.start_recpos); - if (_nisam_read_cache(&read_cache,(byte*) block_info.header,pos, - BLOCK_INFO_HEADER_LENGTH, test(! found_record) | 2)) - { - if (found_record) - { - print_info("Can't read whole record at %lu (errno: %d)", - (ulong) sort_info.start_recpos,errno); - goto try_next; - } - DBUG_RETURN(-1); - } - if (searching && ! sort_info.fix_datafile) - { - error_printed=1; - DBUG_RETURN(1); /* Something wrong with data */ - } - if (((b_type=_nisam_get_block_info(&block_info,-1,pos)) & - (BLOCK_ERROR | BLOCK_FATAL_ERROR)) || - ((b_type & BLOCK_FIRST) && - (block_info.rec_len < (uint) share->base.min_pack_length || - block_info.rec_len > (uint) share->base.max_pack_length))) - { - uint i; - if (testflag & T_VERBOSE || searching == 0) - print_info("Wrong bytesec: %3d-%3d-%3d at %10lu; Skipped", - block_info.header[0],block_info.header[1], - block_info.header[2],pos); - if (found_record) - goto try_next; - block_info.second_read=0; - searching=1; - for (i=1 ; i < 11 ; i++) /* Skip from read string */ - if (block_info.header[i] >= 1 && block_info.header[i] <= 16) - break; - pos+=(ulong) i; - continue; - } - if (block_info.block_len+ (uint) (block_info.filepos-pos) < - share->base.min_block_length || - block_info.block_len-4 > (uint) share->base.max_pack_length) - { - if (!searching) - print_info("Found block with impossible length %u at %lu; Skipped", - block_info.block_len+ (uint) (block_info.filepos-pos), - (ulong) pos); - if (found_record) - goto try_next; - searching=1; - pos++; - block_info.second_read=0; - continue; - } - if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR)) - { - if (!sort_info.fix_datafile && (b_type & BLOCK_DELETED)) - { - share->state.empty+=block_info.block_len; - share->state.del++; - share->state.splitt++; - } - if (found_record) - goto try_next; - /* Check if impossible big deleted block */ - if (block_info.block_len > share->base.max_pack_length +4) - searching=1; - if (searching) - pos++; - else - pos=block_info.filepos+block_info.block_len; - block_info.second_read=0; - continue; - } - - share->state.splitt++; - if (! found_record++) - { - sort_info.find_length=left_length=block_info.rec_len; - sort_info.start_recpos=pos; - if (!sort_info.fix_datafile) - sort_info.filepos=sort_info.start_recpos; - if (sort_info.fix_datafile && (testflag & T_EXTEND)) - sort_info.pos=block_info.filepos+1; - else - sort_info.pos=block_info.filepos+block_info.block_len; - if (share->base.blobs) - { - if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len))) - { - print_error("Not enough memory for blob at %lu", - (ulong) sort_info.start_recpos); - DBUG_RETURN(-1); - } - } - else - to= info->rec_buff; - } - if (left_length < block_info.data_len || ! block_info.data_len) - { - print_info("Found block with too small length at %lu; Skipped", - (ulong) sort_info.start_recpos); - goto try_next; - } - if (block_info.filepos + block_info.data_len > read_cache.end_of_file) - { - print_info("Found block that points outside data file at %lu", - (ulong) sort_info.start_recpos); - goto try_next; - } - if (_nisam_read_cache(&read_cache,to,block_info.filepos, - block_info.data_len, test(found_record == 1))) - { - print_info("Read error for block at: %lu (error: %d); Skipped", - (ulong) block_info.filepos,my_errno); - goto try_next; - } - left_length-=block_info.data_len; - to+=block_info.data_len; - pos=block_info.next_filepos; - if (pos == NI_POS_ERROR && left_length) - { - print_info("Wrong block with wrong total length starting at %lu", - (ulong) sort_info.start_recpos); - goto try_next; - } - if (pos + BLOCK_INFO_HEADER_LENGTH > read_cache.end_of_file) - { - print_info("Found link that points at %lu (outside data file) at %lu", - (ulong) pos,(ulong) sort_info.start_recpos); - goto try_next; - } - } while (left_length); - - if (_nisam_rec_unpack(info,sort_info.record,info->rec_buff, - sort_info.find_length) != MY_FILE_ERROR) - { - if (read_cache.error < 0) - DBUG_RETURN(1); - if ((testflag & (T_EXTEND | T_REP)) || searching) - { - if (_nisam_rec_check(info, sort_info.record)) - { - print_info("Found wrong packed record at %lu", - (ulong) sort_info.start_recpos); - goto try_next; - } - } - DBUG_RETURN(0); - } - if (!searching) - { - print_info("Found wrong packed record at %lu", - (ulong) sort_info.start_recpos); - } - try_next: - pos=sort_info.start_recpos+1; - searching=1; - } - case COMPRESSED_RECORD: - for (searching=0 ;; searching=1, sort_info.pos++) - { - if (_nisam_read_cache(&read_cache,(byte*) block_info.header,sort_info.pos, - share->pack.ref_length,1)) - DBUG_RETURN(-1); - if (searching && ! sort_info.fix_datafile) - { - error_printed=1; - DBUG_RETURN(1); /* Something wrong with data */ - } - sort_info.start_recpos=sort_info.pos; - VOID(_nisam_pack_get_block_info(&block_info,share->pack.ref_length,-1, - sort_info.pos)); - if (!block_info.rec_len && - sort_info.pos + MEMMAP_EXTRA_MARGIN == read_cache.end_of_file) - DBUG_RETURN(-1); - if (block_info.rec_len < (uint) share->min_pack_length || - block_info.rec_len > (uint) share->max_pack_length) - { - if (! searching) - print_info("Found block with wrong recordlength: %d at %lu\n", - block_info.rec_len, (ulong) sort_info.pos); - continue; - } - if (_nisam_read_cache(&read_cache,(byte*) info->rec_buff, - block_info.filepos, block_info.rec_len,1)) - { - if (! searching) - print_info("Couldn't read hole record from %lu", - (ulong) sort_info.pos); - continue; - } - if (_nisam_pack_rec_unpack(info,sort_info.record,info->rec_buff, - block_info.rec_len)) - { - if (! searching) - print_info("Found wrong record at %lu",(ulong) sort_info.pos); - continue; - } - if (!sort_info.fix_datafile) - sort_info.filepos=sort_info.pos; - sort_info.max_pos=(sort_info.pos+=share->pack.ref_length+ - block_info.rec_len); - share->state.splitt++; - info->packed_length=block_info.rec_len; - DBUG_RETURN(0); - } - } - DBUG_RETURN(1); /* Impossible */ -} - - - /* Write record to new file */ - -static int sort_write_record() -{ - int flag; - uint block_length,reclength; - byte *from; - uchar *block_buff[3]; - N_INFO *info; - ISAM_SHARE *share; - DBUG_ENTER("sort_write_record"); - - info=sort_info.info; - share=info->s; - if (sort_info.fix_datafile) - { - switch (sort_info.new_data_file_type) { - case STATIC_RECORD: - if (my_b_write(&info->rec_cache,sort_info.record, share->base.reclength)) - { - print_error("%d when writing to datafile",my_errno); - DBUG_RETURN(1); - } - sort_info.filepos+=share->base.reclength; - break; - case DYNAMIC_RECORD: - if (! info->blobs) - from=info->rec_buff; - else - { - /* must be sure that local buffer is big enough */ - reclength=info->s->base.pack_reclength+ - _calc_total_blob_length(info,sort_info.record)+ - ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+ - DYN_DELETE_BLOCK_HEADER; - if (sort_info.buff_length < reclength) - { - if (!(sort_info.buff=my_realloc(sort_info.buff, (uint) reclength, - MYF(MY_FREE_ON_ERROR | - MY_ALLOW_ZERO_PTR)))) - DBUG_RETURN(1); - sort_info.buff_length=reclength; - } - from=sort_info.buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER); - } - reclength=_nisam_rec_pack(info,from,sort_info.record); - block_length=reclength+ 3 +test(reclength > 65532L); - if (block_length < share->base.min_block_length) - block_length=share->base.min_block_length; - flag=0; - info->update|=HA_STATE_WRITE_AT_END; - if (_nisam_write_part_record(info,0L,block_length,NI_POS_ERROR, - &from,&reclength,&flag)) - { - print_error("%d when writing to datafile",my_errno); - DBUG_RETURN(1); - } - sort_info.filepos+=block_length; - break; - case COMPRESSED_RECORD: - reclength=info->packed_length; - save_integer((byte*) block_buff,share->pack.ref_length,reclength); - if (my_b_write(&info->rec_cache,(byte*) block_buff,share->pack.ref_length) - || my_b_write(&info->rec_cache,(byte*) info->rec_buff,reclength)) - { - print_error("%d when writing to datafile",my_errno); - DBUG_RETURN(1); - } - sort_info.filepos+=reclength+share->pack.ref_length; - break; - } - } - share->state.records++; - if (testflag & T_WRITE_LOOP && share->state.records % WRITE_COUNT == 0) - { - printf("%lu\r",(ulong) share->state.records); VOID(fflush(stdout)); - } - DBUG_RETURN(0); -} /* sort_write_record */ - - - /* Compare two keys from _create_index_by_sort */ - -static int sort_key_cmp(const void *not_used __attribute__((unused)), - const void *a,const void *b) -{ - return (_nisam_key_cmp(sort_info.keyseg,*((uchar**) a),*((uchar**) b),0, - SEARCH_SAME)); -} /* sort_key_cmp */ - - -static int sort_key_write( const void *a) -{ - int cmp=sort_info.key_block->inited ? - _nisam_key_cmp(sort_info.keyseg,sort_info.key_block->lastkey,(uchar*) a, - 0,SEARCH_FIND) : -1L; - if ((sort_info.keyinfo->base.flag & HA_NOSAME) && - cmp == 0) - { - sort_info.dupp++; - print_warning("Dupplicate key for record at %10lu against record at %10lu", - sort_info.info->lastpos=get_record_for_key(sort_info.info, - sort_info.keyinfo, - (uchar*) a), - get_record_for_key(sort_info.info,sort_info.keyinfo, - sort_info.key_block->lastkey)); - if (testflag & T_VERBOSE) - _nisam_print_key(stdout,sort_info.keyseg,(uchar*) a); - return(sort_delete_record()); - } - if (cmp) - sort_info.unique++; -#ifndef DBUG_OFF - if (cmp > 0) - { - print_error("Fatal intern error: Keys are not in order from sort"); - return(1); - } -#endif - return (sort_insert_key(sort_info.key_block,(uchar*) a,NI_POS_ERROR)); -} /* sort_key_write */ - - - /* get pointer to record from a key */ - -static ulong get_record_for_key( N_INFO *info, N_KEYDEF *keyinfo, uchar *key) -{ - return _nisam_dpos(info,0,key+_nisam_keylength(keyinfo,key)); -} /* get_record_for_key */ - - - /* Insert a key in sort-key-blocks */ - -static int sort_insert_key(reg1 ISAM_SORT_KEY_BLOCKS *key_block, - uchar *key, ulong prev_block) -{ - uint a_length,t_length,nod_flag; - ulong filepos; - uchar *anc_buff,*lastkey; - S_PARAM s_temp; - N_INFO *info; - DBUG_ENTER("sort_insert_key"); - - anc_buff=key_block->buff; - info=sort_info.info; - lastkey=key_block->lastkey; - nod_flag= (key_block == sort_info.key_block ? 0 : - sort_info.info->s->base.key_reflength); - - if (!key_block->inited) - { - key_block->inited=1; - if (key_block == sort_info.key_block_end) - { - print_error("To many keyblocklevels; Try increasing sort_key_blocks"); - DBUG_RETURN(1); - } - a_length=2+nod_flag; - key_block->end_pos=anc_buff+2; - lastkey=0; /* No previous key in block */ - } - else - a_length=getint(anc_buff); - - /* Save pointer to previous block */ - if (nod_flag) - _nisam_kpointer(info,key_block->end_pos,prev_block); - - t_length=_nisam_get_pack_key_length(sort_info.keyinfo,nod_flag, - (uchar*) 0,lastkey,key,&s_temp); - _nisam_store_key(sort_info.keyinfo,key_block->end_pos+nod_flag,&s_temp); - a_length+=t_length; - putint(anc_buff,a_length,nod_flag); - key_block->end_pos+=t_length; - if (a_length <= sort_info.keyinfo->base.block_length) - { - VOID(_nisam_move_key(sort_info.keyinfo,key_block->lastkey,key)); - key_block->last_length=a_length-t_length; - DBUG_RETURN(0); - } - - /* Fill block with end-zero and write filled block */ - putint(anc_buff,key_block->last_length,nod_flag); - bzero((byte*) anc_buff+key_block->last_length, - sort_info.keyinfo->base.block_length- key_block->last_length); - if ((filepos=_nisam_new(info,sort_info.keyinfo)) == NI_POS_ERROR) - return 1; - if (my_pwrite(info->s->kfile,(byte*) anc_buff, - (uint) sort_info.keyinfo->base.block_length,filepos,MYF_RW)) - DBUG_RETURN(1); - DBUG_DUMP("buff",(byte*) anc_buff,getint(anc_buff)); - - /* Write separator-key to block in next level */ - if (sort_insert_key(key_block+1,key_block->lastkey,filepos)) - DBUG_RETURN(1); - - /* clear old block and write new key in it */ - key_block->inited=0; - DBUG_RETURN(sort_insert_key(key_block,key,prev_block)); -} /* sort_insert_key */ - - - /* Delete record when we found a dupplicated key */ - -static int sort_delete_record() -{ - uint i; - int old_file,error; - uchar *key; - N_INFO *info; - DBUG_ENTER("sort_delete_record"); - - if (rep_quick == 1) - { - VOID(fputs("Quick-recover aborted; Run recovery without switch 'q' or with switch -qq\n",stderr)); - error_printed=1; - DBUG_RETURN(1); - } - info=sort_info.info; - if (info->s->base.options & HA_OPTION_COMPRESS_RECORD) - { - VOID(fputs("Recover aborted; Can't run standard recovery on compressed tables\nwith errors in data-file\nUse switch '--safe-recover' to fix it\n",stderr)); - error_printed=1; - DBUG_RETURN(1); - } - - old_file=info->dfile; - info->dfile=info->rec_cache.file; - if (sort_info.key) - { - key=info->lastkey+info->s->base.max_key_length; - if ((*info->s->read_rnd)(info,sort_info.record,info->lastpos,0) < 0) - { - print_error("Can't read record to be removed"); - info->dfile=old_file; - DBUG_RETURN(1); - } - - for (i=0 ; i < sort_info.key ; i++) - { - VOID(_nisam_make_key(info,i,key,sort_info.record,info->lastpos)); - if (_nisam_ck_delete(info,i,key)) - { - print_error("Can't delete key %d from record to be removed",i+1); - info->dfile=old_file; - DBUG_RETURN(1); - } - } - } - error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info); - info->dfile=old_file; /* restore actual value */ - info->s->state.records--; - DBUG_RETURN(error); -} /* sort_delete_record */ - - - /* Fix all pending blocks and flush everything to disk */ - -static int flush_pending_blocks() -{ - uint nod_flag,length; - ulong filepos; - N_INFO *info; - ISAM_SORT_KEY_BLOCKS *key_block; - DBUG_ENTER("flush_pending_blocks"); - - filepos= NI_POS_ERROR; /* if empty file */ - info=sort_info.info; - nod_flag=0; - for (key_block=sort_info.key_block ; key_block->inited ; key_block++) - { - key_block->inited=0; - length=getint(key_block->buff); - if (nod_flag) - _nisam_kpointer(info,key_block->end_pos,filepos); - if ((filepos=_nisam_new(info,sort_info.keyinfo)) == NI_POS_ERROR) - DBUG_RETURN(1); - bzero((byte*) key_block->buff+length, - sort_info.keyinfo->base.block_length-length); - if (my_pwrite(info->s->kfile,(byte*) key_block->buff, - (uint) sort_info.keyinfo->base.block_length,filepos,MYF_RW)) - DBUG_RETURN(1); - DBUG_DUMP("buff",(byte*) key_block->buff,length); - nod_flag=1; - } - info->s->state.key_root[sort_info.key]=filepos; /* Last is root for tree */ - DBUG_RETURN(0); -} /* flush_pending_blocks */ - - - /* alloc space and pointers for key_blocks */ - -static ISAM_SORT_KEY_BLOCKS *alloc_key_blocks(uint blocks, uint buffer_length) -{ - reg1 uint i; - ISAM_SORT_KEY_BLOCKS *block; - DBUG_ENTER("alloc_key_blocks"); - - if (!(block=(ISAM_SORT_KEY_BLOCKS*) my_malloc((sizeof(ISAM_SORT_KEY_BLOCKS)+ - buffer_length+IO_SIZE)*blocks, - MYF(0)))) - { - print_error("Not Enough memory for sort-key-blocks"); - return(0); - } - for (i=0 ; i < blocks ; i++) - { - block[i].inited=0; - block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i; - } - DBUG_RETURN(block); -} /* alloc_key_blocks */ - - - /* print warnings and errors */ - /* VARARGS */ - -static void print_info(const char * fmt,...) -{ - va_list args; - - va_start(args,fmt); - VOID(vfprintf(stdout, fmt, args)); - VOID(fputc('\n',stdout)); - va_end(args); - return; -} - -/* VARARGS */ - -static void print_warning(const char * fmt,...) -{ - va_list args; - DBUG_ENTER("print_warning"); - - if (!warning_printed && !error_printed) - { - fflush(stdout); - if (testflag & T_SILENT) - fprintf(stderr,"%s: ISAM file %s\n",my_progname,isam_file_name); - } - warning_printed=1; - va_start(args,fmt); - fprintf(stderr,"%s: warning: ",my_progname); - VOID(vfprintf(stderr, fmt, args)); - VOID(fputc('\n',stderr)); - va_end(args); - DBUG_VOID_RETURN; -} - -/* VARARGS */ - -void print_error(const char *fmt,...) -{ - va_list args; - DBUG_ENTER("print_error"); - DBUG_PRINT("enter",("format: %s",fmt)); - - if (!warning_printed && !error_printed) - { - fflush(stdout); - if (testflag & T_SILENT) - fprintf(stderr,"%s: ISAM file %s\n",my_progname,isam_file_name); - } - error_printed|=1; - va_start(args,fmt); - fprintf(stderr,"%s: error: ",my_progname); - VOID(vfprintf(stderr, fmt, args)); - VOID(fputc('\n',stderr)); - va_end(args); - DBUG_VOID_RETURN; -} - - /* Check if file is almost full */ - -static int test_if_almost_full(N_INFO *info) -{ - double diff= 0.9; - if (info->s->base.options & HA_OPTION_COMPRESS_RECORD) - { /* Fix problem with pack_isam */ - diff=1.0; - if (info->s->base.rec_reflength == 4) - info->s->base.max_data_file_length= (uint32) ~0L; - else - info->s->base.max_data_file_length= - 1L << (info->s->base.rec_reflength); - } - return (my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)) > - (ulong) (info->s->base.max_key_file_length*diff) || - my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) > - (ulong) (info->s->base.max_data_file_length*diff)); -} - - /* Recreate table with bigger more alloced record-data */ - -static int recreate_database(N_INFO **org_info, char *filename) -{ - int error; - N_INFO info; - ISAM_SHARE share; - N_KEYDEF *keyinfo; - N_RECINFO *recinfo,*rec,*end; - uint unpack; - ulong max_records; - char name[FN_REFLEN]; - - error=1; /* Default error */ - info= **org_info; - share= *(*org_info)->s; - unpack= (share.base.options & HA_OPTION_COMPRESS_RECORD) && - (testflag & T_UNPACK); - if (!(keyinfo=(N_KEYDEF*) my_alloca(sizeof(N_KEYDEF)*share.base.keys))) - return 0; - memcpy((byte*) keyinfo,(byte*) share.keyinfo, - (size_t) (sizeof(N_KEYDEF)*share.base.keys)); - if (!(recinfo=(N_RECINFO*) - my_alloca(sizeof(N_RECINFO)*(share.base.fields+1)))) - { - my_afree((gptr) keyinfo); - return 1; - } - memcpy((byte*) recinfo,(byte*) share.rec, - (size_t) (sizeof(N_RECINFO)*(share.base.fields+1))); - for (rec=recinfo,end=recinfo+share.base.fields; rec != end ; rec++) - { - if (rec->base.type == (int) FIELD_BLOB) - rec->base.length+=sizeof(char*); - else if (unpack && !(share.base.options & HA_OPTION_PACK_RECORD)) - rec->base.type=(int) FIELD_NORMAL; - } - - if (share.base.options & HA_OPTION_COMPRESS_RECORD) - share.base.records=max_records=share.state.records; - else if (share.base.min_pack_length) - max_records=(ulong) (my_seek(info.dfile,0L,MY_SEEK_END,MYF(0)) / - (ulong) share.base.min_pack_length); - else - max_records=0; - unpack= (share.base.options & HA_OPTION_COMPRESS_RECORD) && - (testflag & T_UNPACK); - share.base.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD; - VOID(nisam_close(*org_info)); - if (nisam_create(fn_format(name,filename,"",N_NAME_IEXT, - 4+ (opt_follow_links ? 16 : 0)), - share.base.keys,keyinfo,recinfo, - max(max_records,share.base.records),share.base.reloc, - HA_DONT_TOUCH_DATA, - share.base.options | - (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD - : 0), - (ulong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0)))) - { - print_error("Got error %d when trying to recreate indexfile",my_errno); - goto end; - } - *org_info=nisam_open(name,O_RDWR, - (testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED : - (testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED : - HA_OPEN_ABORT_IF_LOCKED); - if (!*org_info) - { - print_error("Got error %d when trying to open re-created indexfile", - my_errno); - goto end; - } - /* We are modifing */ - (*org_info)->s->base.options&= ~HA_OPTION_READ_ONLY_DATA; - VOID(_nisam_readinfo(*org_info,F_WRLCK,0)); - (*org_info)->s->state.records=share.state.records; - if (share.base.create_time) - (*org_info)->s->base.create_time=share.base.create_time; - (*org_info)->s->state.uniq=(*org_info)->this_uniq= - share.state.uniq; - (*org_info)->s->state.del=share.state.del; - (*org_info)->s->state.dellink=share.state.dellink; - (*org_info)->s->state.empty=share.state.empty; - (*org_info)->s->state.data_file_length=share.state.data_file_length; - if (update_state_info(*org_info,UPDATE_TIME | UPDATE_STAT)) - goto end; - error=0; -end: - my_afree((gptr) keyinfo); - my_afree((gptr) recinfo); - return error; -} - - /* Store long in 1,2,3 or 4 bytes */ - -static void save_integer( byte *pos, uint pack_length, ulong value) -{ - switch (pack_length) { - case 4: int4store(pos,value); break; - case 3: int3store(pos,value); break; - case 2: int2store(pos,(uint) value); break; - case 1: pos[0]= (char) (uchar) value; break; - default: break; - } - return; -} - - /* write suffix to data file if neaded */ - -static int write_data_suffix( N_INFO *info) -{ - if (info->s->base.options & HA_OPTION_COMPRESS_RECORD && - sort_info.fix_datafile) - { - char buff[MEMMAP_EXTRA_MARGIN]; - bzero(buff,sizeof(buff)); - if (my_b_write(&info->rec_cache,buff,sizeof(buff))) - { - print_error("%d when writing to datafile",my_errno); - return 1; - } - read_cache.end_of_file+=sizeof(buff); - } - return 0; -} - - - /* Update state and isamchk_time of indexfile */ - -static int update_state_info( N_INFO *info, uint update) -{ - ISAM_SHARE *share=info->s; - uint base_pos=uint2korr(info->s->state.header.base_pos); - - if (update & (UPDATE_STAT | UPDATE_SORT | UPDATE_TIME)) - { - if (offsetof(N_BASE_INFO,rec_per_key) > - uint2korr(share->state.header.base_info_length)) - { - VOID(fputs("Internal error: Trying to change base of old table\n", - stderr)); - } - else - { - if (update & UPDATE_TIME) - { - share->base.isamchk_time= (long) time((time_t*) 0); - if (!share->base.create_time) - share->base.create_time=share->base.isamchk_time; - if (my_pwrite(share->kfile,(gptr) &share->base.create_time, - sizeof(long)*2, - base_pos+offsetof(N_BASE_INFO,create_time), - MYF(MY_NABP))) - goto err; - } - if (update & (UPDATE_STAT | UPDATE_SORT)) - { - if (my_pwrite(share->kfile,(gptr) share->base.rec_per_key, - sizeof(long)*share->state.keys+sizeof(uint), - base_pos+offsetof(N_BASE_INFO,rec_per_key), - MYF(MY_NABP))) - goto err; - } - } - } - { /* Force update of status */ - int error; - uint r_locks=share->r_locks,w_locks=share->w_locks; - share->r_locks=share->w_locks=0; - error=_nisam_writeinfo(info,2); - share->r_locks=r_locks; share->w_locks=w_locks; - if (!error) - return 0; - } -err: - print_error("%d when updating keyfile",my_errno); - return 1; -} diff --git a/isam/isamdef.h b/isam/isamdef.h deleted file mode 100644 index 7d89730fe32..00000000000 --- a/isam/isamdef.h +++ /dev/null @@ -1,418 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Denna fil includeras i alla isam-filer */ - -#define ISAM_LIBRARY -#include <nisam.h> /* Structs & some defines */ -#ifdef THREAD -#include <my_pthread.h> -#include <thr_lock.h> -#else -#include <my_no_pthread.h> -#endif -#include <keycache.h> - -#ifdef my_write -#undef my_write /* We want test if disk full */ -#endif -#undef HA_SORT_ALLOWS_SAME -#define HA_SORT_ALLOWS_SAME 128 /* Can't be > 128 in NISAM */ - -#ifdef __WATCOMC__ -#pragma pack(2) -#define uint uint16 /* Same format as in MSDOS */ -#endif -#ifdef __ZTC__ -#pragma ZTC align 2 -#define uint uint16 /* Same format as in MSDOS */ -#endif -#if defined(__WIN__) && defined(_MSC_VER) -#pragma pack(push,isamdef,2) -#define uint uint16 -#endif - -typedef struct st_state_info -{ - struct { /* Fileheader */ - uchar file_version[4]; - uchar options[2]; - uchar header_length[2]; - uchar state_info_length[2]; - uchar base_info_length[2]; - uchar base_pos[2]; - uchar not_used[2]; - } header; - - ulong records; /* Antal record i databasen */ - ulong del; /* Antalet borttagna poster */ - ulong dellink; /* L{nk till n{sta borttagna */ - ulong key_file_length; - ulong data_file_length; - ulong splitt; /* Antal splittrade delar */ - ulong empty; /* Outnyttjat utrymme */ - ulong process; /* Vem som senast uppdatera */ - ulong loop; /* not used anymore */ - ulong uniq; /* Unik nr i denna process */ - ulong key_root[N_MAXKEY]; /* Pekare till rootblocken */ - ulong key_del[N_MAXKEY]; /* Del-l{nkar f|r n-block */ - ulong sec_index_changed; /* Updated when new sec_index */ - ulong sec_index_used; /* 1 bit for each sec index in use */ - ulong version; /* timestamp of create */ - uint keys; /* Keys in use for database */ -} N_STATE_INFO; - - -typedef struct st_base_info -{ - ulong keystart; /* Var nycklarna b|rjar */ - ulong records,reloc; /* Parameter vid skapandet */ - ulong max_pack_length; /* Max possibly length of packed rec.*/ - ulong max_data_file_length; - ulong max_key_file_length; - uint reclength; /* length of unpacked record */ - uint options; /* Options used */ - uint pack_reclength; /* Length of full packed rec. */ - uint min_pack_length; - uint min_block_length; - uint rec_reflength; /* = 2 or 3 or 4 */ - uint key_reflength; /* = 2 or 3 or 4 */ - uint keys; /* Keys defined for database */ - uint blobs; /* Number of blobs */ - uint max_block; /* Max blockl{ngd anv{nd */ - uint max_key_length; /* L{ngsta nyckel-l{ngden */ - uint fields, /* Antal f{lt i databasen */ - pack_fields, /* Packade f{lt i databasen */ - pack_bits; /* Length of packed bits */ - time_t create_time; /* Time when created database */ - time_t isamchk_time; /* Time for last recover */ - ulong rec_per_key[N_MAXKEY]; /* for sql optimizing */ - uint sortkey; /* sorted by this key */ -} N_BASE_INFO; - - -#ifdef __ZTC__ -#pragma ZTC align -#undef uint -#endif -#ifdef __WATCOMC__ -#pragma pack() -#undef uint -#endif -#if defined(__WIN__) && defined(_MSC_VER) -#pragma pack(pop,isamdef) -#undef uint -#endif - - /* Structs used intern in database */ - -typedef struct st_n_blob /* Info of record */ -{ - uint offset; /* Offset to blob in record */ - uint pack_length; /* Type of packed length */ - uint length; /* Calc:ed for each record */ -} N_BLOB; - - -typedef struct st_isam_pack { - ulong header_length; - uint ref_length; -} N_PACK; - - -typedef struct st_isam_share { /* Shared between opens */ - N_STATE_INFO state; - N_BASE_INFO base; - N_KEYDEF *keyinfo; /* Nyckelinfo */ - N_RECINFO *rec; /* Pointer till recdata */ - N_PACK pack; /* Data about packed records */ - N_BLOB *blobs; /* Pointer to blobs */ - char *filename; /* Name of indexfile */ - byte *file_map; /* mem-map of file if possible */ - ulong this_process; /* processid */ - ulong last_process; /* For table-change-check */ - ulong last_version; /* Version on start */ - uint rec_reflength; /* rec_reflength in use now */ - int kfile; /* Shared keyfile */ - int mode; /* mode of file on open */ - int reopen; /* How many times reopened */ - uint state_length; - uint w_locks,r_locks; /* Number of read/write locks */ - uint min_pack_length; /* Theese is used by packed data */ - uint max_pack_length; - uint blocksize; /* blocksize of keyfile */ - my_bool changed,not_flushed; /* If changed since lock */ - int rnd; /* rnd-counter */ - DECODE_TREE *decode_trees; - uint16 *decode_tables; - enum data_file_type data_file_type; - int (*read_record)(struct st_isam_info*, ulong, byte*); - int (*write_record)(struct st_isam_info*, const byte*); - int (*update_record)(struct st_isam_info*, ulong, const byte*); - int (*delete_record)(struct st_isam_info*); - int (*read_rnd)(struct st_isam_info*, byte*, ulong, int); - int (*compare_record)(struct st_isam_info*, const byte *); -#ifdef THREAD - THR_LOCK lock; - pthread_mutex_t intern_lock; /* Locking for use with _locking */ -#endif -} ISAM_SHARE; - - -typedef uint bit_type; - -typedef struct st_bit_buff { /* Used for packing of record */ - bit_type current_byte; - uint bits; - uchar *pos,*end; - uint error; -} BIT_BUFF; - - -typedef struct st_isam_info { - ISAM_SHARE *s; /* Shared between open:s */ - N_BLOB *blobs; /* Pointer to blobs */ - int dfile; /* The datafile */ - BIT_BUFF bit_buff; - uint options; - uint opt_flag; /* Optim. for space/speed */ - uint update; /* If file changed since open */ - char *filename; /* parameter to open filename */ - ulong this_uniq; /* uniq filenumber or thread */ - ulong last_uniq; /* last uniq number */ - ulong this_loop; /* counter for this open */ - ulong last_loop; /* last used counter */ - ulong lastpos, /* Last record position */ - nextpos; /* Position to next record */ - ulong int_pos; /* Intern variabel */ - ulong dupp_key_pos; /* Position to record with dupp key */ - ulong last_search_keypage; - ulong save_lastpos; - uint packed_length; /* Length of found, packed record */ - uint alloced_rec_buff_length; /* Max recordlength malloced */ - uchar *buff, /* Temp area for key */ - *lastkey; /* Last used search key */ - byte *rec_buff, /* Tempbuff for recordpack */ - *rec_alloc; /* Malloced area for record */ - uchar *int_keypos, /* Intern variabel */ - *int_maxpos; /* Intern variabel */ - int lastinx; /* Last used index */ - int errkey; /* Got last error on this key */ - uint data_changed; /* Somebody has changed data */ - int lock_type; /* How database was locked */ - int tmp_lock_type; /* When locked by readinfo */ - int was_locked; /* Was locked in panic */ - myf lock_wait; /* is 0 or MY_DONT_WAIT */ - my_bool page_changed; - my_bool buff_used; - uint save_update; /* When using KEY_READ */ - int save_lastinx; - int (*read_record)(struct st_isam_info*, ulong, byte*); - LIST open_list; - IO_CACHE rec_cache; /* When cacheing records */ -#ifdef THREAD - THR_LOCK_DATA lock; -#endif -} N_INFO; - - - /* Some defines used by isam-funktions */ - -#define USE_HOLE_KEY 0 /* Use hole key in _nisam_search() */ -#define F_EXTRA_LCK -1 - - /* bits in opt_flag */ -#define MEMMAP_USED 32 -#define REMEMBER_OLD_POS 64 - -#define getint(x) ((uint) (uint16) *((int16*) (x)) & 32767) -#define putint(x,y,nod) (*((uint16*) (x))= ((nod ? (uint16) 32768 : 0)+(uint16) (y))) -#ifdef WORDS_BIGENDIAN -#define test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0) -#else -#define test_if_nod(x) (x[1] & 128 ? info->s->base.key_reflength : 0) -#endif - -#define N_MIN_BLOCK_LENGTH 8 /* Because of delete-link */ -#define N_EXTEND_BLOCK_LENGTH 20 /* Don't use to small record-blocks */ -#define N_SPLITT_LENGTH ((N_EXTEND_BLOCK_LENGTH+3)*2) -#define MAX_DYN_BLOCK_HEADER 11 /* Max prefix of record-block */ -#define DYN_DELETE_BLOCK_HEADER 8 /* length of delete-block-header */ -#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */ -#define INDEX_BLOCK_MARGIN 16 /* Safety margin for .ISM tables */ - -#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */ -#define PACK_TYPE_SPACE_FIELDS 2 -#define PACK_TYPE_ZERO_FILL 4 - -#ifdef THREAD -extern pthread_mutex_t THR_LOCK_isam; -#endif - - /* Some extern variables */ - -extern LIST *nisam_open_list; -extern uchar NEAR nisam_file_magic[],NEAR nisam_pack_file_magic[]; -extern uint NEAR nisam_read_vec[],nisam_quick_table_bits; -extern File nisam_log_file; - - /* This is used by _nisam_get_pack_key_length och _nisam_store_key */ - -typedef struct st_s_param -{ - uint ref_length,key_length, - n_ref_length, - n_length, - totlength, - part_of_prev_key,prev_length; - uchar *key, *prev_key; -} S_PARAM; - - /* Prototypes for intern functions */ - -extern int _nisam_read_dynamic_record(N_INFO *info,ulong filepos,byte *buf); -extern int _nisam_write_dynamic_record(N_INFO*, const byte*); -extern int _nisam_update_dynamic_record(N_INFO*, ulong, const byte*); -extern int _nisam_delete_dynamic_record(N_INFO *info); -extern int _nisam_cmp_dynamic_record(N_INFO *info,const byte *record); -extern int _nisam_read_rnd_dynamic_record(N_INFO *, byte *,ulong, int); -extern int _nisam_write_blob_record(N_INFO*, const byte*); -extern int _nisam_update_blob_record(N_INFO*, ulong, const byte*); -extern int _nisam_read_static_record(N_INFO *info,ulong filepos,byte *buf); -extern int _nisam_write_static_record(N_INFO*, const byte*); -extern int _nisam_update_static_record(N_INFO*, ulong, const byte*); -extern int _nisam_delete_static_record(N_INFO *info); -extern int _nisam_cmp_static_record(N_INFO *info,const byte *record); -extern int _nisam_read_rnd_static_record(N_INFO*, byte *,ulong, int); -extern int _nisam_ck_write(N_INFO *info,uint keynr,uchar *key); -extern int _nisam_enlarge_root(N_INFO *info,uint keynr,uchar *key); -extern int _nisam_insert(N_INFO *info,N_KEYDEF *keyinfo,uchar *key, - uchar *anc_buff,uchar *key_pos,uchar *key_buff, - uchar *father_buff, uchar *father_keypos, - ulong father_page); -extern int _nisam_splitt_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key, - uchar *buff,uchar *key_buff); -extern uchar *_nisam_find_half_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *page, - uchar *key); -extern uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo,uint nod_flag, - uchar *key_pos,uchar *key_buff, - uchar *key, S_PARAM *s_temp); -extern void _nisam_store_key(N_KEYDEF *keyinfo,uchar *key_pos, - S_PARAM *s_temp); -extern int _nisam_ck_delete(N_INFO *info,uint keynr,uchar *key); -extern int _nisam_readinfo(N_INFO *info,int lock_flag,int check_keybuffer); -extern int _nisam_writeinfo(N_INFO *info, uint flag); -extern int _nisam_test_if_changed(N_INFO *info); -extern int _nisam_check_index(N_INFO *info,int inx); -extern int _nisam_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint key_len,uint nextflag,ulong pos); -extern int _nisam_bin_search(struct st_isam_info *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff); -extern int _nisam_seq_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff); -extern ulong _nisam_kpos(uint nod_flag,uchar *after_key); -extern void _nisam_kpointer(N_INFO *info,uchar *buff,ulong pos); -extern ulong _nisam_dpos(N_INFO *info, uint nod_flag,uchar *after_key); -extern void _nisam_dpointer(N_INFO *info, uchar *buff,ulong pos); -extern int _nisam_key_cmp(N_KEYSEG *keyseg,uchar *a,uchar *b, - uint key_length,uint nextflag); -extern uint _nisam_get_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key); -extern uint _nisam_get_static_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key); -extern uchar *_nisam_get_last_key(N_INFO *info,N_KEYDEF *keyinfo,uchar *keypos,uchar *lastkey,uchar *endpos); -extern uint _nisam_keylength(N_KEYDEF *keyinfo,uchar *key); -extern uchar *_nisam_move_key(N_KEYDEF *keyinfo,uchar *to,uchar *from); -extern int _nisam_search_next(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint nextflag,ulong pos); -extern int _nisam_search_first(N_INFO *info,N_KEYDEF *keyinfo,ulong pos); -extern int _nisam_search_last(N_INFO *info,N_KEYDEF *keyinfo,ulong pos); -extern uchar *_nisam_fetch_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page, - uchar *buff,int return_buffer); -extern int _nisam_write_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page, - uchar *buff); -extern int _nisam_dispose(N_INFO *info,N_KEYDEF *keyinfo,my_off_t pos); -extern ulong _nisam_new(N_INFO *info,N_KEYDEF *keyinfo); -extern uint _nisam_make_key(N_INFO *info,uint keynr,uchar *key, - const char *record,ulong filepos); -extern uint _nisam_pack_key(N_INFO *info,uint keynr,uchar *key,uchar *old,uint key_length); -extern int _nisam_read_key_record(N_INFO *info,ulong filepos,byte *buf); -extern int _nisam_read_cache(IO_CACHE *info,byte *buff,ulong pos, - uint length,int re_read_if_possibly); -extern byte *fix_rec_buff_for_blob(N_INFO *info,uint blob_length); -extern uint _nisam_rec_unpack(N_INFO *info,byte *to,byte *from, - uint reclength); -my_bool _nisam_rec_check(N_INFO *info,const char *from); -extern int _nisam_write_part_record(N_INFO *info,ulong filepos,uint length, - ulong next_filepos,byte **record, - uint *reclength,int *flag); -extern void _nisam_print_key(FILE *stream,N_KEYSEG *keyseg,const uchar *key); -extern my_bool _nisam_read_pack_info(N_INFO *info,pbool fix_keys); -extern int _nisam_read_pack_record(N_INFO *info,ulong filepos,byte *buf); -extern int _nisam_read_rnd_pack_record(N_INFO*, byte *,ulong, int); -extern int _nisam_pack_rec_unpack(N_INFO *info,byte *to,byte *from, - uint reclength); -extern ulong _nisam_checksum(const byte *mem, uint count); - -typedef struct st_sortinfo { - uint key_length; - ulong max_records; - int (*key_cmp)(const void *, const void *, const void *); - int (*key_read)(void *buff); - int (*key_write)(const void *buff); - void (*lock_in_memory)(void); -} SORT_PARAM; - -int _create_index_by_sort(SORT_PARAM *info,pbool no_messages, - uint sortbuff_size); - -#define BLOCK_INFO_HEADER_LENGTH 11 - -typedef struct st_block_info { /* Parameter to _nisam_get_block_info */ - uchar header[BLOCK_INFO_HEADER_LENGTH]; - uint rec_len; - uint data_len; - uint block_len; - ulong filepos; /* Must be ulong on Alpha! */ - ulong next_filepos; - uint second_read; -} BLOCK_INFO; - - /* bits in return from _nisam_get_block_info */ - -#define BLOCK_FIRST 1 -#define BLOCK_LAST 2 -#define BLOCK_DELETED 4 -#define BLOCK_ERROR 8 /* Wrong data */ -#define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */ -#define BLOCK_FATAL_ERROR 32 /* hardware-error */ - -enum nisam_log_commands { - LOG_OPEN,LOG_WRITE,LOG_UPDATE,LOG_DELETE,LOG_CLOSE,LOG_EXTRA,LOG_LOCK -}; - -#define nisam_log_simple(a,b,c,d) if (nisam_log_file >= 0) _nisam_log(a,b,c,d) -#define nisam_log_command(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_command(a,b,c,d,e) -#define nisam_log_record(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_record(a,b,c,d,e) - -extern uint _nisam_get_block_info(BLOCK_INFO *,File, ulong); -extern uint _nisam_rec_pack(N_INFO *info,byte *to,const byte *from); -extern uint _nisam_pack_get_block_info(BLOCK_INFO *, uint, File, ulong); -extern uint _calc_total_blob_length(N_INFO *info,const byte *record); -extern void _nisam_log(enum nisam_log_commands command,N_INFO *info, - const byte *buffert,uint length); -extern void _nisam_log_command(enum nisam_log_commands command, - N_INFO *info, const byte *buffert, - uint length, int result); -extern void _nisam_log_record(enum nisam_log_commands command,N_INFO *info, - const byte *record,ulong filepos, - int result); -extern my_bool _nisam_memmap_file(N_INFO *info); -extern void _nisam_unmap_file(N_INFO *info); diff --git a/isam/isamlog.c b/isam/isamlog.c deleted file mode 100644 index 5cc204b26aa..00000000000 --- a/isam/isamlog.c +++ /dev/null @@ -1,853 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* write whats in isam.log */ - -#ifndef USE_MY_FUNC -#define USE_MY_FUNC -#endif - -#include "isamdef.h" -#include <my_tree.h> -#include <stdarg.h> -#ifdef HAVE_GETRUSAGE -#include <sys/resource.h> -#endif - -#define FILENAME(A) (A ? A->show_name : "Unknown") - -struct isamlog_file_info { - long process; - int filenr,id; - my_string name,show_name,record; - N_INFO *isam; - bool closed,used; - ulong accessed; -}; - -struct test_if_open_param { - my_string name; - int max_id; -}; - -struct st_access_param -{ - ulong min_accessed; - struct isamlog_file_info *found; -}; - -#define NO_FILEPOS (ulong) ~0L - -extern int main(int argc,char * *argv); -static void get_options(int *argc,char ***argv); -static int examine_log(my_string file_name,char **table_names); -static int read_string(IO_CACHE *file,gptr *to,uint length); -static int file_info_compare(void *a,void *b); -static int test_if_open(struct isamlog_file_info *key,element_count count, - struct test_if_open_param *param); -static void fix_blob_pointers(N_INFO *isam,byte *record); -static uint set_maximum_open_files(uint); -static int test_when_accessed(struct isamlog_file_info *key,element_count count, - struct st_access_param *access_param); -static void file_info_free(struct isamlog_file_info *info); -static int close_some_file(TREE *tree); -static int reopen_closed_file(TREE *tree,struct isamlog_file_info *file_info); -static int find_record_with_key(struct isamlog_file_info *file_info, - byte *record); -static void printf_log(const char *str,...); -static bool cmp_filename(struct isamlog_file_info *file_info,my_string name); - -static uint verbose=0,update=0,test_info=0,max_files=0,re_open_count=0, - recover=0,prefix_remove=0,opt_processes=0; -static my_string log_filename=0,filepath=0,write_filename=0,record_pos_file=0; -static ulong com_count[10][3],number_of_commands=(ulong) ~0L,start_offset=0, - record_pos= NO_FILEPOS,isamlog_filepos,isamlog_process; -static const char *command_name[]= -{"open","write","update","delete","close","extra","lock","re-open",NullS}; - - -int main(int argc, char **argv) -{ - int error,i,first; - ulong total_count,total_error,total_recover; - MY_INIT(argv[0]); - - log_filename=nisam_log_filename; - get_options(&argc,&argv); - /* Nr of isam-files */ - max_files=(set_maximum_open_files(min(max_files,8))-6)/2; - - if (update) - printf("Trying to %s ISAM files according to log '%s'\n", - (recover ? "recover" : "update"),log_filename); - error= examine_log(log_filename,argv); - if (update && ! error) - puts("Tables updated successfully"); - total_count=total_error=total_recover=0; - for (i=first=0 ; command_name[i] ; i++) - { - if (com_count[i][0]) - { - if (!first++) - { - if (verbose || update) - puts(""); - puts("Commands Used count Errors Recover errors"); - } - printf("%-12s%9ld%10ld%17ld\n",command_name[i],com_count[i][0], - com_count[i][1],com_count[i][2]); - total_count+=com_count[i][0]; - total_error+=com_count[i][1]; - total_recover+=com_count[i][2]; - } - } - if (total_count) - printf("%-12s%9ld%10ld%17ld\n","Total",total_count,total_error, - total_recover); - if (re_open_count) - printf("Had to do %d re-open because of too few possibly open files\n", - re_open_count); - VOID(nisam_panic(HA_PANIC_CLOSE)); - my_end(test_info ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); - exit(error); - return 0; /* No compiler warning */ -} /* main */ - - -static void get_options(register int *argc, register char ***argv) -{ - int help,version; - const char *pos,*usage; - char option; - - help=0; - usage="Usage: %s [-?iruvIPV] [-c #] [-f #] [-F filepath/] [-o #] [-R file recordpos] [-w write_file] [log-filename [table ...]] \n"; - pos= ""; - - while (--*argc > 0 && *(pos = *(++*argv)) == '-' ) { - while (*++pos) - { - version=0; - switch((option=*pos)) { - case '#': - DBUG_PUSH (++pos); - pos=" "; /* Skip rest of arg */ - break; - case 'c': - if (! *++pos) - { - if (!--*argc) - goto err; - else - pos= *(++*argv); - } - number_of_commands=(ulong) atol(pos); - pos=" "; - break; - case 'u': - update=1; - break; - case 'f': - if (! *++pos) - { - if (!--*argc) - goto err; - else - pos= *(++*argv); - } - max_files=(uint) atoi(pos); - pos=" "; - break; - case 'i': - test_info=1; - break; - case 'o': - if (! *++pos) - { - if (!--*argc) - goto err; - else - pos= *(++*argv); - } - start_offset=(ulong) atol(pos); - pos=" "; - break; - case 'p': - if (! *++pos) - { - if (!--*argc) - goto err; - else - pos= *(++*argv); - } - prefix_remove=atoi(pos); - break; - case 'r': - update=1; - recover++; - break; - case 'P': - opt_processes=1; - break; - case 'R': - if (! *++pos) - { - if (!--*argc) - goto err; - else - pos= *(++*argv); - } - record_pos_file=(char*) pos; - if (!--*argc) - goto err; - record_pos=(ulong) atol(*(++*argv)); - pos= " "; - break; - case 'v': - verbose++; - break; - case 'w': - if (! *++pos) - { - if (!--*argc) - goto err; - else - pos= *(++*argv); - } - write_filename=(char*) pos; - pos=" "; - break; - case 'F': - if (! *++pos) - { - if (!--*argc) - goto err; - else - pos= *(++*argv); - } - filepath= (char*) pos; - pos=" "; - break; - case 'V': - version=1; - /* Fall through */ - case 'I': - case '?': - printf("%s Ver 3.3 for %s at %s\n",my_progname,SYSTEM_TYPE, - MACHINE_TYPE); - puts("By Monty, for your professional use\n"); - if (version) - break; - puts("Write info about whats in a ISAM log file."); - printf("If no file name is given %s is used\n",log_filename); - puts(""); - printf(usage,my_progname); - puts(""); - puts("Options: -? or -I \"Info\" -V \"version\" -c \"do only # commands\""); - puts(" -f \"max open files\" -F \"filepath\" -i \"extra info\""); - puts(" -o \"offset\" -p # \"remove # components from path\""); - puts(" -r \"recover\" -R \"file recordposition\""); - puts(" -u \"update\" -v \"verbose\" -w \"write file\""); - puts(" -P \"processes\""); - puts("\nOne can give a second and a third '-v' for more verbose."); - puts("Normaly one does a update (-u)."); - puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted."); - puts("If one gives table names as arguments only these tables will be updated\n"); - help=1; - break; - default: - printf("illegal option: \"-%c\"\n",*pos); - break; - } - } - } - if (! *argc) - { - if (help) - exit(0); - (*argv)++; - } - if (*argc >= 1) - { - log_filename=(char*) pos; - (*argc)--; - (*argv)++; - } - return; - err: - VOID(fprintf(stderr,"option \"%c\" used without or with wrong argument\n", - option)); - exit(1); -} - - -static int examine_log(my_string file_name, char **table_names) -{ - uint command,result,files_open; - ulong access_time,length; - uint32 filepos; - int lock_command,ni_result; - char isam_file_name[FN_REFLEN]; - uchar head[20]; - gptr buff; - struct test_if_open_param open_param; - IO_CACHE cache; - File file; - FILE *write_file; - enum ha_extra_function extra_command; - TREE tree; - struct isamlog_file_info file_info,*curr_file_info; - char llbuff[22],llbuff2[22]; - DBUG_ENTER("examine_log"); - - if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0) - DBUG_RETURN(1); - write_file=0; - if (write_filename) - { - if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME)))) - { - my_close(file,MYF(0)); - DBUG_RETURN(1); - } - } - - init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0)); - bzero((gptr) com_count,sizeof(com_count)); - init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1, - (tree_element_free) file_info_free, NULL); - VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE, - 0,0)); - files_open=0; access_time=0; - while (access_time++ != number_of_commands && - !my_b_read(&cache,(byte*) head,9)) - { - isamlog_filepos=my_b_tell(&cache)-9L; - file_info.filenr=uint2korr(head+1); - isamlog_process=file_info.process=(long) uint4korr(head+3); - if (!opt_processes) - file_info.process=0; - result=uint2korr(head+7); - if ((curr_file_info=(struct isamlog_file_info*) - tree_search(&tree, &file_info, tree.custom_arg))) - { - curr_file_info->accessed=access_time; - if (update && curr_file_info->used && curr_file_info->closed) - { - if (reopen_closed_file(&tree,curr_file_info)) - { - command=sizeof(com_count)/sizeof(com_count[0][0])/3; - result=0; - goto com_err; - } - } - } - command=(uint) head[0]; - if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 && - (!table_names[0] || (curr_file_info && curr_file_info->used))) - { - com_count[command][0]++; - if (result) - com_count[command][1]++; - } - switch ((enum nisam_log_commands) command) { - case LOG_OPEN: - if (!table_names[0]) - { - com_count[command][0]--; /* Must be counted explicite */ - if (result) - com_count[command][1]--; - } - - if (curr_file_info) - printf("\nWarning: %s is opened with same process and filenumber\nMaybe you should use the -P option ?\n", - curr_file_info->show_name); - if (my_b_read(&cache,(byte*) head,2)) - goto err; - file_info.name=0; - file_info.show_name=0; - file_info.record=0; - if (read_string(&cache,(gptr*) &file_info.name,(uint) uint2korr(head))) - goto err; - { - uint i; - char *pos,*to; - - /* Fix if old DOS files to new format */ - for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++) - *pos= '/'; - - pos=file_info.name; - for (i=0 ; i < prefix_remove ; i++) - { - char *next; - if (!(next=strchr(pos,'/'))) - break; - pos=next+1; - } - to=isam_file_name; - if (filepath) - to=convert_dirname(isam_file_name, filepath, NullS); - strmov(to,pos); - fn_ext(isam_file_name)[0]=0; /* Remove extension */ - } - open_param.name=file_info.name; - open_param.max_id=0; - VOID(tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param, - left_root_right)); - file_info.id=open_param.max_id+1; - file_info.show_name=my_memdup(isam_file_name, - (uint) strlen(isam_file_name)+6, - MYF(MY_WME)); - if (file_info.id > 1) - sprintf(strend(file_info.show_name),"<%d>",file_info.id); - file_info.closed=1; - file_info.accessed=access_time; - file_info.used=1; - if (table_names[0]) - { - char **name; - file_info.used=0; - for (name=table_names ; *name ; name++) - { - if (!strcmp(*name,isam_file_name)) - file_info.used=1; /* Update/log only this */ - } - } - if (update && file_info.used) - { - if (files_open >= max_files) - { - if (close_some_file(&tree)) - goto com_err; - files_open--; - } - if (!(file_info.isam= nisam_open(isam_file_name,O_RDWR, - HA_OPEN_WAIT_IF_LOCKED))) - goto com_err; - if (!(file_info.record=my_malloc(file_info.isam->s->base.reclength, - MYF(MY_WME)))) - goto end; - files_open++; - file_info.closed=0; - } - VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg)); - if (file_info.used) - { - if (verbose && !record_pos_file) - printf_log("%s: open -> %d",file_info.show_name, file_info.filenr); - com_count[command][0]++; - if (result) - com_count[command][1]++; - } - break; - case LOG_CLOSE: - if (verbose && !record_pos_file && - (!table_names[0] || (curr_file_info && curr_file_info->used))) - printf_log("%s: %s -> %d",FILENAME(curr_file_info), - command_name[command],result); - if (curr_file_info) - { - if (!curr_file_info->closed) - files_open--; - VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg)); - } - break; - case LOG_EXTRA: - if (my_b_read(&cache,(byte*) head,sizeof(extra_command))) - goto err; - memcpy_fixed(&extra_command,head,sizeof(extra_command)); - if (verbose && !record_pos_file && - (!table_names[0] || (curr_file_info && curr_file_info->used))) - printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info), - command_name[command], (int) extra_command,result); - if (update && curr_file_info && !curr_file_info->closed) - { - if (nisam_extra(curr_file_info->isam,extra_command) != (int) result) - { - fflush(stdout); - VOID(fprintf(stderr, - "Warning: error %d, expected %d on command %s at %s\n", - my_errno,result,command_name[command], - llstr(isamlog_filepos,llbuff))); - fflush(stderr); - } - } - break; - case LOG_DELETE: - if (my_b_read(&cache,(byte*) head,sizeof(filepos))) - goto err; - memcpy_fixed(&filepos,head,sizeof(filepos)); - if (verbose && (!record_pos_file || - ((record_pos == filepos || record_pos == NO_FILEPOS) && - !cmp_filename(curr_file_info,record_pos_file))) && - (!table_names[0] || (curr_file_info && curr_file_info->used))) - printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info), - command_name[command],(long) filepos,result); - if (update && curr_file_info && !curr_file_info->closed) - { - if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos)) - { - if (!recover) - goto com_err; - com_count[command][2]++; /* Mark error */ - } - ni_result=nisam_delete(curr_file_info->isam,curr_file_info->record); - if ((ni_result == 0 && result) || - (ni_result && (uint) my_errno != result)) - { - if (!recover) - goto com_err; - if (ni_result) - com_count[command][2]++; /* Mark error */ - if (verbose) - printf_log("error: Got result %d from mi_delete instead of %d", - ni_result, result); - } - } - break; - case LOG_WRITE: - case LOG_UPDATE: - if (my_b_read(&cache,(byte*) head,8)) - goto err; - filepos=uint4korr(head); - length=uint4korr(head+4); - buff=0; - if (read_string(&cache,&buff,(uint) length)) - goto err; - if ((!record_pos_file || - ((record_pos == filepos || record_pos == NO_FILEPOS) && - !cmp_filename(curr_file_info,record_pos_file))) && - (!table_names[0] || (curr_file_info && curr_file_info->used))) - { - if (write_file && - (my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP)))) - goto end; - if (verbose) - printf_log("%s: %s at %ld, length=%ld -> %d", - FILENAME(curr_file_info), - command_name[command], filepos,length,result); - } - if (update && curr_file_info && !curr_file_info->closed) - { - if (curr_file_info->isam->s->base.blobs) - fix_blob_pointers(curr_file_info->isam,buff); - if ((enum nisam_log_commands) command == LOG_UPDATE) - { - if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos)) - { - if (!recover) - { - result=0; - goto com_err; - } - if (verbose) - printf_log("error: Didn't find row to update with mi_rrnd"); - if (recover == 1 || result || - find_record_with_key(curr_file_info,buff)) - { - com_count[command][2]++; /* Mark error */ - break; - } - } - ni_result=nisam_update(curr_file_info->isam,curr_file_info->record, - buff); - if ((ni_result == 0 && result) || - (ni_result && (uint) my_errno != result)) - { - if (!recover) - goto com_err; - if (verbose) - printf_log("error: Got result %d from mi_update instead of %d", - ni_result, result); - if (ni_result) - com_count[command][2]++; /* Mark error */ - } - } - else - { - ni_result=nisam_write(curr_file_info->isam,buff); - if ((ni_result == 0 && result) || - (ni_result && (uint) my_errno != result)) - { - if (!recover) - goto com_err; - if (ni_result) - com_count[command][2]++; /* Mark error */ - } - if (! recover && filepos != curr_file_info->isam->lastpos) - { - printf("error: Wrote at position: %s, should have been %s", - llstr(curr_file_info->isam->lastpos,llbuff), - llstr(filepos,llbuff2)); - goto end; - } - } - } - my_free(buff,MYF(0)); - break; - case LOG_LOCK: - if (my_b_read(&cache,(byte*) head,sizeof(lock_command))) - goto err; - memcpy_fixed(&lock_command,head,sizeof(lock_command)); - if (verbose && !record_pos_file && - (!table_names[0] || (curr_file_info && curr_file_info->used))) - printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info), - command_name[command],lock_command,result); - if (update && curr_file_info && !curr_file_info->closed) - { - if (nisam_lock_database(curr_file_info->isam,lock_command) != - (int) result) - goto com_err; - } - break; - default: - VOID(fprintf(stderr, - "Error: found unknown command %d in logfile, aborted\n", - command)); - fflush(stderr); - goto end; - } - } - end_key_cache(dflt_key_cache,1); - delete_tree(&tree); - VOID(end_io_cache(&cache)); - VOID(my_close(file,MYF(0))); - if (write_file && my_fclose(write_file,MYF(MY_WME))) - DBUG_RETURN(1); - DBUG_RETURN(0); - - err: - fflush(stdout); - VOID(fprintf(stderr,"Got error %d when reading from logfile\n",my_errno)); - fflush(stderr); - goto end; - com_err: - fflush(stdout); - VOID(fprintf(stderr,"Got error %d, expected %d on command %s at %s\n", - my_errno,result,command_name[command], - llstr(isamlog_filepos,llbuff))); - fflush(stderr); - end: - end_key_cache(dflt_key_cache,1); - delete_tree(&tree); - VOID(end_io_cache(&cache)); - VOID(my_close(file,MYF(0))); - if (write_file) - VOID(my_fclose(write_file,MYF(MY_WME))); - DBUG_RETURN(1); -} - - -static int read_string(IO_CACHE *file, reg1 gptr *to, reg2 uint length) -{ - DBUG_ENTER("read_string"); - - if (*to) - my_free((gptr) *to,MYF(0)); - if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) || - my_b_read(file,(byte*) *to,length)) - { - if (*to) - my_free(*to,MYF(0)); - *to= 0; - DBUG_RETURN(1); - } - *((char*) *to+length)= '\0'; - DBUG_RETURN (0); -} /* read_string */ - - -static int file_info_compare(void *a, void *b) -{ - long lint; - - if ((lint=((struct isamlog_file_info*) a)->process - - ((struct isamlog_file_info*) b)->process)) - return lint < 0L ? -1 : 1; - return (((struct isamlog_file_info*) a)->filenr - - ((struct isamlog_file_info*) b)->filenr); -} - - /* ARGSUSED */ - -static int test_if_open (struct isamlog_file_info *key, - element_count count __attribute__((unused)), - struct test_if_open_param *param) -{ - if (!strcmp(key->name,param->name) && key->id > param->max_id) - param->max_id=key->id; - return 0; -} - - -static void fix_blob_pointers( N_INFO *info, byte *record) -{ - byte *pos; - N_BLOB *blob,*end; - - pos=record+info->s->base.reclength; - for (end=info->blobs+info->s->base.blobs, blob= info->blobs; - blob != end ; - blob++) - { - bmove(record+blob->offset+blob->pack_length,&pos,sizeof(char*)); - pos+=_calc_blob_length(blob->pack_length,record+blob->offset); - } -} - -static uint set_maximum_open_files(uint maximum_files) -{ -#if defined(HAVE_GETRUSAGE) && defined(RLIMIT_NOFILE) - struct rlimit rlimit; - int old_max; - - if (maximum_files > MY_NFILE) - maximum_files=MY_NFILE; /* Don't crash my_open */ - - if (!getrlimit(RLIMIT_NOFILE,&rlimit)) - { - old_max=rlimit.rlim_max; - if (maximum_files && (int) maximum_files > old_max) - rlimit.rlim_max=maximum_files; - rlimit.rlim_cur=rlimit.rlim_max; - if (setrlimit(RLIMIT_NOFILE,&rlimit)) - { - if (old_max != (int) maximum_files) - { /* Set as much as we can */ - rlimit.rlim_max=rlimit.rlim_cur=old_max; - setrlimit(RLIMIT_NOFILE,&rlimit); - } - } - getrlimit(RLIMIT_NOFILE,&rlimit); /* Read if broken setrlimit */ - if (maximum_files && maximum_files < rlimit.rlim_cur) - VOID(fprintf(stderr,"Warning: Error from setrlimit: Max open files is %d\n",old_max)); - return rlimit.rlim_cur; - } -#endif - return min(maximum_files,MY_NFILE); -} - - /* close the file with hasn't been accessed for the longest time */ - /* ARGSUSED */ - -static int test_when_accessed (struct isamlog_file_info *key, - element_count count __attribute__((unused)), - struct st_access_param *access_param) -{ - if (key->accessed < access_param->min_accessed && ! key->closed) - { - access_param->min_accessed=key->accessed; - access_param->found=key; - } - return 0; -} - - -static void file_info_free(struct isamlog_file_info *fileinfo) -{ - DBUG_ENTER("file_info_free"); - if (update) - { - if (!fileinfo->closed) - VOID(nisam_close(fileinfo->isam)); - if (fileinfo->record) - my_free(fileinfo->record,MYF(0)); - } - my_free(fileinfo->name,MYF(0)); - my_free(fileinfo->show_name,MYF(0)); - DBUG_VOID_RETURN; -} - - - -static int close_some_file(TREE *tree) -{ - struct st_access_param access_param; - - access_param.min_accessed=LONG_MAX; - access_param.found=0; - - VOID(tree_walk(tree,(tree_walk_action) test_when_accessed, - (void*) &access_param,left_root_right)); - if (!access_param.found) - return 1; /* No open file that is possibly to close */ - if (nisam_close(access_param.found->isam)) - return 1; - access_param.found->closed=1; - return 0; -} - - -static int reopen_closed_file(TREE *tree, struct isamlog_file_info *fileinfo) -{ - char name[FN_REFLEN]; - if (close_some_file(tree)) - return 1; /* No file to close */ - strmov(name,fileinfo->show_name); - if (fileinfo->id > 1) - *strrchr(name,'<')='\0'; /* Remove "<id>" */ - - if (!(fileinfo->isam= nisam_open(name,O_RDWR,HA_OPEN_WAIT_IF_LOCKED))) - return 1; - fileinfo->closed=0; - re_open_count++; - return 0; -} - - /* Try to find record with uniq key */ - -static int find_record_with_key(struct isamlog_file_info *file_info, - byte *record) -{ - uint key; - N_INFO *info=file_info->isam; - uchar tmp_key[N_MAX_KEY_BUFF]; - - for (key=0 ; key < info->s->state.keys ; key++) - { - if (info->s->keyinfo[key].base.flag & HA_NOSAME) - { - VOID(_nisam_make_key(info,key,tmp_key,record,0L)); - return nisam_rkey(info,file_info->record,(int) key,(char*) tmp_key,0, - HA_READ_KEY_EXACT); - } - } - return 1; -} - - -static void printf_log(const char *format,...) -{ - char llbuff[21]; - va_list args; - va_start(args,format); - if (verbose > 2) - printf("%9s:",llstr(isamlog_filepos,llbuff)); - if (verbose > 1) - printf("%5ld ",isamlog_process); /* Write process number */ - (void) vprintf((char*) format,args); - putchar('\n'); - va_end(args); -} - - -static bool cmp_filename(struct isamlog_file_info *file_info,my_string name) -{ - if (!file_info) - return 1; - return strcmp(file_info->name,name) ? 1 : 0; -} diff --git a/isam/log.c b/isam/log.c deleted file mode 100644 index 78b56690401..00000000000 --- a/isam/log.c +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Logging of isamcommands and records on logfile */ - -#include "isamdef.h" -#if defined(MSDOS) || defined(__WIN__) -#include <errno.h> -#include <fcntl.h> -#ifndef __WIN__ -#include <process.h> -#endif -#endif -#ifdef VMS -#include <processes.h> -#endif - -#ifdef THREAD -#undef GETPID -#define GETPID() (log_type == 1 ? getpid() : (long) my_thread_id()); -#else -#define GETPID() getpid() -#endif - - /* Activate logging if flag is 1 and reset logging if flag is 0 */ - -static int log_type=0; - -int nisam_log(int activate_log) -{ - int error=0; - char buff[FN_REFLEN]; - DBUG_ENTER("nisam_log"); - - log_type=activate_log; - if (activate_log) - { - if (nisam_log_file < 0) - { - if ((nisam_log_file = my_create(fn_format(buff,nisam_log_filename, - "",".log",4), - 0,(O_RDWR | O_BINARY | O_APPEND),MYF(0))) - < 0) - DBUG_RETURN(1); - } - } - else if (nisam_log_file >= 0) - { - error=my_close(nisam_log_file,MYF(0)); - nisam_log_file= -1; - } - DBUG_RETURN(error); -} - - - /* Logging of records and commands on logfile */ - /* All logs starts with command(1) dfile(2) process(4) result(2) */ - -void _nisam_log(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length) -{ - char buff[11]; - int error,old_errno; - ulong pid=(ulong) GETPID(); - old_errno=my_errno; - bzero(buff,sizeof(buff)); - buff[0]=(char) command; - int2store(buff+1,info->dfile); - int4store(buff+3,pid); - int2store(buff+9,length); - - pthread_mutex_lock(&THR_LOCK_isam); - error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)); - VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0))); - VOID(my_write(nisam_log_file,buffert,length,MYF(0))); - if (!error) - error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)); - pthread_mutex_unlock(&THR_LOCK_isam); - my_errno=old_errno; -} - - -void _nisam_log_command(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length, int result) -{ - char buff[9]; - int error,old_errno; - ulong pid=(ulong) GETPID(); - - old_errno=my_errno; - buff[0]=(char) command; - int2store(buff+1,info->dfile); - int4store(buff+3,pid); - int2store(buff+7,result); - pthread_mutex_lock(&THR_LOCK_isam); - error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)); - VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0))); - if (buffert) - VOID(my_write(nisam_log_file,buffert,length,MYF(0))); - if (!error) - error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)); - pthread_mutex_unlock(&THR_LOCK_isam); - my_errno=old_errno; -} - - -void _nisam_log_record(enum nisam_log_commands command, N_INFO *info, const byte *record, ulong filepos, int result) -{ - char buff[17],*pos; - int error,old_errno; - uint length; - ulong pid=(ulong) GETPID(); - - old_errno=my_errno; - if (!info->s->base.blobs) - length=info->s->base.reclength; - else - length=info->s->base.reclength+ _calc_total_blob_length(info,record); - buff[0]=(char) command; - int2store(buff+1,info->dfile); - int4store(buff+3,pid); - int2store(buff+7,result); - int4store(buff+9,filepos); - int4store(buff+13,length); - pthread_mutex_lock(&THR_LOCK_isam); - error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)); - VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0))); - VOID(my_write(nisam_log_file,(byte*) record,info->s->base.reclength,MYF(0))); - if (info->s->base.blobs) - { - N_BLOB *blob,*end; - - for (end=info->blobs+info->s->base.blobs, blob= info->blobs; - blob != end ; - blob++) - { - bmove(&pos,record+blob->offset+blob->pack_length,sizeof(char*)); - VOID(my_write(nisam_log_file,pos,blob->length,MYF(0))); - } - } - if (!error) - error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)); - pthread_mutex_unlock(&THR_LOCK_isam); - my_errno=old_errno; -} diff --git a/isam/make-ccc b/isam/make-ccc deleted file mode 100755 index d9a95dbc14b..00000000000 --- a/isam/make-ccc +++ /dev/null @@ -1,3 +0,0 @@ -ccc -DHAVE_CONFIG_H -I. -I. -I.. -I./../include -I../include -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c _cache.c _dbug.c _dynrec.c _key.c _locking.c _packrec.c _page.c _search.c _statrec.c changed.c close.c create.c delete.c extra.c info.c log.c open.c panic.c range.c rfirst.c rkey.c rlast.c rnext.c rprev.c rrnd.c rsame.c rsamepos.c static.c update.c write.c -rm libnisam.a -ar -cr libnisam.a _cache.o diff --git a/isam/open.c b/isam/open.c deleted file mode 100644 index be62fd86192..00000000000 --- a/isam/open.c +++ /dev/null @@ -1,477 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* open a isam-database */ - -#include "isamdef.h" -#if defined(MSDOS) || defined(__WIN__) -#ifdef __WIN__ -#include <fcntl.h> -#else -#include <process.h> /* Prototype for getpid */ -#endif -#endif -#ifdef VMS -#include "static.c" -#endif - -static void setup_functions(ISAM_SHARE *info); -static void setup_key_functions(N_KEYDEF *keyinfo); - -#define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \ - pos+=size;} - -/****************************************************************************** -** Return the shared struct if the table is already open. -** In MySQL the server will handle version issues. -******************************************************************************/ - -static N_INFO *test_if_reopen(char *filename) -{ - LIST *pos; - - for (pos=nisam_open_list ; pos ; pos=pos->next) - { - N_INFO *info=(N_INFO*) pos->data; - ISAM_SHARE *share=info->s; - if (!strcmp(share->filename,filename) && share->last_version) - return info; - } - return 0; -} - - -/****************************************************************************** - open a isam database. - By default exit with error if database is locked - if handle_locking & HA_OPEN_WAIT_IF_LOCKED then wait if database is locked - if handle_locking & HA_OPEN_IGNORE_IF_LOCKED then continue, but count-vars - in st_i_info may be wrong. count-vars are automaticly fixed after next - isam request. -******************************************************************************/ - - -N_INFO *nisam_open(const char *name, int mode, uint handle_locking) -{ - int lock_error,kfile,open_mode,save_errno; - uint i,j,len,errpos,head_length,base_pos,offset,info_length,extra; - char name_buff[FN_REFLEN],*disk_cache,*disk_pos; - N_INFO info,*m_info,*old_info; - ISAM_SHARE share_buff,*share; - DBUG_ENTER("nisam_open"); - - LINT_INIT(m_info); - kfile= -1; - lock_error=1; - errpos=0; - head_length=sizeof(share_buff.state.header); - bzero((byte*) &info,sizeof(info)); - - VOID(fn_format(name_buff,name,"",N_NAME_IEXT,4+16+32)); - pthread_mutex_lock(&THR_LOCK_isam); - if (!(old_info=test_if_reopen(name_buff))) - { - share= &share_buff; - bzero((gptr) &share_buff,sizeof(share_buff)); - - if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0) - { - if ((errno != EROFS && errno != EACCES) || - mode != O_RDONLY || - (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0) - goto err; - } - errpos=1; - if (my_read(kfile,(char*) share->state.header.file_version,head_length, - MYF(MY_NABP))) - goto err; - - if (memcmp((byte*) share->state.header.file_version, - (byte*) nisam_file_magic, 3) || - share->state.header.file_version[3] == 0 || - (uchar) share->state.header.file_version[3] > 3) - { - DBUG_PRINT("error",("Wrong header in %s",name_buff)); - DBUG_DUMP("error_dump",(char*) share->state.header.file_version, - head_length); - my_errno=HA_ERR_CRASHED; - goto err; - } - if (uint2korr(share->state.header.options) & - ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS | - HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA | - HA_OPTION_TEMP_COMPRESS_RECORD)) - { - DBUG_PRINT("error",("wrong options: 0x%lx", - uint2korr(share->state.header.options))); - my_errno=HA_ERR_OLD_FILE; - goto err; - } - info_length=uint2korr(share->state.header.header_length); - base_pos=uint2korr(share->state.header.base_pos); - if (!(disk_cache=(char*) my_alloca(info_length))) - { - my_errno=ENOMEM; - goto err; - } - errpos=2; - - VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0))); -#ifndef NO_LOCKING - if (!(handle_locking & HA_OPEN_TMP_TABLE)) - { - if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF, - MYF(handle_locking & HA_OPEN_WAIT_IF_LOCKED ? - 0 : MY_DONT_WAIT))) && - !(handle_locking & HA_OPEN_IGNORE_IF_LOCKED)) - goto err; - } -#endif - errpos=3; - if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP))) - goto err; - len=uint2korr(share->state.header.state_info_length); - if (len != sizeof(N_STATE_INFO)) - { - DBUG_PRINT("warning", - ("saved_state_info_length: %d base_info_length: %d", - len,sizeof(N_STATE_INFO))); - } - if (len > sizeof(N_STATE_INFO)) - len=sizeof(N_STATE_INFO); - share->state_length=len; - memcpy(&share->state.header.file_version[0],disk_cache,(size_t) len); - len=uint2korr(share->state.header.base_info_length); - if (len != sizeof(N_BASE_INFO)) - { - DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d", - len,sizeof(N_BASE_INFO))); - if (len <= offsetof(N_BASE_INFO,sortkey)) - share->base.sortkey=(ushort) ~0; - } - memcpy((char*) (byte*) &share->base,disk_cache+base_pos, - (size_t) min(len,sizeof(N_BASE_INFO))); - disk_pos=disk_cache+base_pos+len; - share->base.options=uint2korr(share->state.header.options); - if (share->base.max_key_length > N_MAX_KEY_BUFF) - { - my_errno=HA_ERR_UNSUPPORTED; - goto err; - } - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - share->base.max_key_length+=2; /* For safety */ - - if (!my_multi_malloc(MY_WME, - &share,sizeof(*share), - &share->keyinfo,share->base.keys*sizeof(N_KEYDEF), - &share->rec,(share->base.fields+1)*sizeof(N_RECINFO), - &share->blobs,sizeof(N_BLOB)*share->base.blobs, - &share->filename,strlen(name_buff)+1, - NullS)) - goto err; - errpos=4; - *share=share_buff; - strmov(share->filename,name_buff); - - /* Fix key in used if old nisam-database */ - if (share->state_length <= offsetof(N_STATE_INFO,keys)) - share->state.keys=share->base.keys; - - share->blocksize=min(IO_SIZE,nisam_block_size); - for (i=0 ; i < share->base.keys ; i++) - { - get_next_element(&share->keyinfo[i].base,disk_pos,sizeof(N_SAVE_KEYDEF)); - setup_key_functions(share->keyinfo+i); - set_if_smaller(share->blocksize,share->keyinfo[i].base.block_length); - for (j=0 ; j <= share->keyinfo[i].base.keysegs ; j++) - { - get_next_element(&share->keyinfo[i].seg[j],disk_pos, - sizeof(N_SAVE_KEYSEG)); - } - } - if (!share->blocksize) - { - my_errno=HA_ERR_CRASHED; - goto err; - } - - for (i=j=offset=0 ; i < share->base.fields ; i++) - { - get_next_element(&share->rec[i].base,disk_pos,sizeof(N_SAVE_RECINFO)); -#ifndef NOT_PACKED_DATABASES - share->rec[i].pack_type=0; - share->rec[i].huff_tree=0; -#endif - if (share->rec[i].base.type == (int) FIELD_BLOB) - { - share->blobs[j].pack_length=share->rec[i].base.length; - share->blobs[j].offset=offset; - j++; - offset+=sizeof(char*); - } - offset+=share->rec[i].base.length; - } - share->rec[i].base.type=(int) FIELD_LAST; - -#ifndef NO_LOCKING - if (! lock_error) - { - VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE))); - lock_error=1; /* Database unlocked */ - } -#endif - - if ((info.dfile=my_open(fn_format(name_buff,name,"",N_NAME_DEXT,2+4), - mode | O_SHARE, - MYF(MY_WME))) < 0) - goto err; - errpos=5; - - share->kfile=kfile; - share->mode=open_mode; - share->this_process=(ulong) getpid(); - share->rnd= (int) share->this_process; /* rnd-counter for splitts */ -#ifndef DBUG_OFF - share->rnd=0; /* To make things repeatable */ -#endif - share->last_process= share->state.process; - if (!(share->last_version=share->state.version)) - share->last_version=1; /* Safety */ - share->rec_reflength=share->base.rec_reflength; /* May be changed */ - - share->data_file_type=STATIC_RECORD; - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - { - share->data_file_type = COMPRESSED_RECORD; - share->base.options|= HA_OPTION_READ_ONLY_DATA; - info.s=share; - if (_nisam_read_pack_info(&info, - (pbool) test(!(share->base.options & - (HA_OPTION_PACK_RECORD | - HA_OPTION_TEMP_COMPRESS_RECORD))))) - goto err; - } - else if (share->base.options & HA_OPTION_PACK_RECORD) - share->data_file_type = DYNAMIC_RECORD; - my_afree((gptr) disk_cache); - setup_functions(share); -#ifdef THREAD - thr_lock_init(&share->lock); - VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST)); -#endif - } - else - { - share= old_info->s; - if (mode == O_RDWR && share->mode == O_RDONLY) - { - my_errno=EACCES; /* Can't open in write mode*/ - goto err; - } - if ((info.dfile=my_open(fn_format(name_buff,old_info->filename,"", - N_NAME_DEXT,2+4), - mode | O_SHARE,MYF(MY_WME))) < 0) - { - my_errno=errno; - goto err; - } - errpos=5; - } - - /* alloc and set up private structure parts */ - if (!my_multi_malloc(MY_WME, - &m_info,sizeof(N_INFO), - &info.blobs,sizeof(N_BLOB)*share->base.blobs, - &info.buff,(share->base.max_block*2+ - share->base.max_key_length), - &info.lastkey,share->base.max_key_length*3+1, - &info.filename,strlen(name)+1, - NullS)) - goto err; - errpos=6; - strmov(info.filename,name); - memcpy(info.blobs,share->blobs,sizeof(N_BLOB)*share->base.blobs); - - info.s=share; - info.lastpos= NI_POS_ERROR; - info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND); - info.opt_flag=READ_CHECK_USED; - info.alloced_rec_buff_length=share->base.pack_reclength; - info.this_uniq= (ulong) info.dfile; /* Uniq number in process */ - info.this_loop=0; /* Update counter */ - info.last_uniq= share->state.uniq; - info.last_loop= share->state.loop; - info.options=share->base.options | - (mode == O_RDONLY ? HA_OPTION_READ_ONLY_DATA : 0); - info.lock_type=F_UNLCK; - info.errkey= -1; - pthread_mutex_lock(&share->intern_lock); - info.read_record=share->read_record; - share->reopen++; - if (share->base.options & HA_OPTION_READ_ONLY_DATA) - { - info.lock_type=F_RDLCK; - share->r_locks++; - info.this_uniq=share->state.uniq; /* Row checksum */ - } -#ifndef NO_LOCKING - if (handle_locking & HA_OPEN_TMP_TABLE) -#endif - { - share->w_locks++; /* We don't have to update status */ - info.lock_type=F_WRLCK; - } - pthread_mutex_unlock(&share->intern_lock); - - /* Allocate buffer for one record */ - - extra=0; - if (share->base.options & HA_OPTION_PACK_RECORD) - extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+ - DYN_DELETE_BLOCK_HEADER; - if (!(info.rec_alloc=(byte*) my_malloc(share->base.pack_reclength+extra+ - 6, - MYF(MY_WME | MY_ZEROFILL)))) - goto err; - if (extra) - info.rec_buff=info.rec_alloc+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER); - else - info.rec_buff=info.rec_alloc; - - *m_info=info; -#ifdef THREAD - thr_lock_data_init(&share->lock,&m_info->lock,NULL); -#endif - - m_info->open_list.data=(void*) m_info; - nisam_open_list=list_add(nisam_open_list,&m_info->open_list); - - pthread_mutex_unlock(&THR_LOCK_isam); - nisam_log_simple(LOG_OPEN,m_info,share->filename, - (uint) strlen(share->filename)); - DBUG_RETURN(m_info); - -err: - save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE; - switch (errpos) { - case 6: - my_free((gptr) m_info,MYF(0)); - /* fall through */ - case 5: - VOID(my_close(info.dfile,MYF(0))); - if (old_info) - break; /* Don't remove open table */ - /* fall through */ - case 4: - my_free((gptr) share,MYF(0)); - /* fall through */ - case 3: -#ifndef NO_LOCKING - if (! lock_error) - VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE))); -#endif - /* fall through */ - case 2: - my_afree((gptr) disk_cache); - /* fall through */ - case 1: - VOID(my_close(kfile,MYF(0))); - /* fall through */ - case 0: - default: - break; - } - pthread_mutex_unlock(&THR_LOCK_isam); - my_errno=save_errno; - DBUG_RETURN (NULL); -} /* nisam_open */ - - - /* Set up functions in structs */ - -static void setup_functions(register ISAM_SHARE *share) -{ - if (share->base.options & HA_OPTION_COMPRESS_RECORD) - { - share->read_record=_nisam_read_pack_record; - share->read_rnd=_nisam_read_rnd_pack_record; - } - else if (share->base.options & HA_OPTION_PACK_RECORD) - { - share->read_record=_nisam_read_dynamic_record; - share->read_rnd=_nisam_read_rnd_dynamic_record; - share->delete_record=_nisam_delete_dynamic_record; - share->compare_record=_nisam_cmp_dynamic_record; - - /* add bits used to pack data to pack_reclength for faster allocation */ - share->base.pack_reclength+= share->base.pack_bits; - if (share->base.blobs) - { - share->update_record=_nisam_update_blob_record; - share->write_record=_nisam_write_blob_record; - } - else - { - share->write_record=_nisam_write_dynamic_record; - share->update_record=_nisam_update_dynamic_record; - } - } - else - { - share->read_record=_nisam_read_static_record; - share->read_rnd=_nisam_read_rnd_static_record; - share->delete_record=_nisam_delete_static_record; - share->compare_record=_nisam_cmp_static_record; - share->update_record=_nisam_update_static_record; - share->write_record=_nisam_write_static_record; - } - return; -} - - -static void setup_key_functions(register N_KEYDEF *keyinfo) -{ - if (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)) - { - keyinfo->bin_search=_nisam_seq_search; - keyinfo->get_key=_nisam_get_key; - } - else - { - keyinfo->bin_search=_nisam_bin_search; - keyinfo->get_key=_nisam_get_static_key; - } - return; -} - -/* - Calculate a long checksum for a memoryblock. Used to verify pack_isam - - SYNOPSIS - checksum() - mem Pointer to memory block - count Count of bytes -*/ - -ulong _nisam_checksum(const byte *mem, uint count) -{ - ulong crc; - for (crc= 0; count-- ; mem++) - crc= ((crc << 1) + *((uchar*) mem)) + - test(crc & ((ulong) 1L << (8*sizeof(ulong)-1))); - return crc; -} - diff --git a/isam/pack_isam.c b/isam/pack_isam.c deleted file mode 100644 index aa83b2b2a96..00000000000 --- a/isam/pack_isam.c +++ /dev/null @@ -1,2042 +0,0 @@ -/* Copyright (C) 1979-2002 MySQL 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 */ - -/* Pack isam file */ - -#ifndef USE_MY_FUNC -#define USE_MY_FUNC /* We nead at least my_malloc */ -#endif - -#include "isamdef.h" -#include <queues.h> -#include <my_tree.h> -#include "mysys_err.h" -#ifdef MSDOS -#include <io.h> -#endif -#ifndef __GNU_LIBRARY__ -#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */ -#endif -#include <my_getopt.h> - -#if INT_MAX > 32767 -#define BITS_SAVED 32 -#else -#define BITS_SAVED 16 -#endif - -#define IS_OFFSET ((uint) 32768) /* Bit if offset or char in tree */ -#define HEAD_LENGTH 32 -#define ALLOWED_JOIN_DIFF 256 /* Diff allowed to join trees */ - -#define DATA_TMP_EXT ".TMD" -#define OLD_EXT ".OLD" -#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE - -struct st_file_buffer { - File file; - char *buffer,*pos,*end; - my_off_t pos_in_file; - int bits; - uint bytes; -}; - -struct st_huff_tree; -struct st_huff_element; - -typedef struct st_huff_counts { - uint field_length,max_zero_fill; - uint pack_type; - uint max_end_space,max_pre_space,length_bits,min_space; - enum en_fieldtype field_type; - struct st_huff_tree *tree; /* Tree for field */ - my_off_t counts[256]; - my_off_t end_space[8]; - my_off_t pre_space[8]; - my_off_t tot_end_space,tot_pre_space,zero_fields,empty_fields,bytes_packed; - TREE int_tree; - byte *tree_buff; - byte *tree_pos; -} HUFF_COUNTS; - -typedef struct st_huff_element HUFF_ELEMENT; - -struct st_huff_element { - my_off_t count; - union un_element { - struct st_nod { - HUFF_ELEMENT *left,*right; - } nod; - struct st_leaf { - HUFF_ELEMENT *null; - uint element_nr; /* Number of element */ - } leaf; - } a; -}; - - -typedef struct st_huff_tree { - HUFF_ELEMENT *root,*element_buffer; - HUFF_COUNTS *counts; - uint tree_number; - uint elements; - my_off_t bytes_packed; - uint tree_pack_length; - uint min_chr,max_chr,char_bits,offset_bits,max_offset,height; - ulong *code; - uchar *code_len; -} HUFF_TREE; - - -typedef struct st_isam_mrg { - N_INFO **file,**current,**end; - uint count; - uint min_pack_length; /* Theese is used by packed data */ - uint max_pack_length; - uint ref_length; - my_off_t records; -} MRG_INFO; - - -extern int main(int argc,char * *argv); -static void get_options(int *argc,char ***argv); -static N_INFO *open_isam_file(char *name,int mode); -static bool open_isam_files(MRG_INFO *mrg,char **names,uint count); -static int compress(MRG_INFO *file,char *join_name); -static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records); -static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees, - uint trees, - HUFF_COUNTS *huff_counts, - uint fields); -static int compare_tree(const uchar *s,const uchar *t); -static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts); -static void check_counts(HUFF_COUNTS *huff_counts,uint trees, - my_off_t records); -static int test_space_compress(HUFF_COUNTS *huff_counts,my_off_t records, - uint max_space_length,my_off_t *space_counts, - my_off_t tot_space_count, - enum en_fieldtype field_type); -static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts,uint trees); -static int make_huff_tree(HUFF_TREE *tree,HUFF_COUNTS *huff_counts); -static int compare_huff_elements(void *not_used, byte *a,byte *b); -static int save_counts_in_queue(byte *key,element_count count, - HUFF_TREE *tree); -static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,uint flag); -static uint join_same_trees(HUFF_COUNTS *huff_counts,uint trees); -static int make_huff_decode_table(HUFF_TREE *huff_tree,uint trees); -static void make_traverse_code_tree(HUFF_TREE *huff_tree, - HUFF_ELEMENT *element,uint size, - ulong code); -static int write_header(MRG_INFO *isam_file, uint header_length,uint trees, - my_off_t tot_elements,my_off_t filelength); -static void write_field_info(HUFF_COUNTS *counts, uint fields,uint trees); -static my_off_t write_huff_tree(HUFF_TREE *huff_tree,uint trees); -static uint *make_offset_code_tree(HUFF_TREE *huff_tree, - HUFF_ELEMENT *element, - uint *offset); -static uint max_bit(uint value); -static int compress_isam_file(MRG_INFO *file,HUFF_COUNTS *huff_counts); -static char *make_new_name(char *new_name,char *old_name); -static char *make_old_name(char *new_name,char *old_name); -static void init_file_buffer(File file,pbool read_buffer); -static int flush_buffer(uint neaded_length); -static void end_file_buffer(void); -static void write_bits(ulong value,uint bits); -static void flush_bits(void); -static void save_integer(byte *pos,uint pack_length,my_off_t value); -static void save_state(N_INFO *isam_file,MRG_INFO *mrg,my_off_t new_length, - ulong crc); -static int save_state_mrg(File file,MRG_INFO *isam_file,my_off_t new_length, - ulong crc); -static int mrg_close(MRG_INFO *mrg); -static int mrg_rrnd(MRG_INFO *info,byte *buf); -static void mrg_reset(MRG_INFO *mrg); - - -static int error_on_write=0,test_only=0,verbose=0,silent=0, - write_loop=0,force_pack=0,isamchk_neaded=0; -static my_bool backup, opt_wait; -static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL; -static uint tree_buff_length=8196-MALLOC_OVERHEAD,force_pack_ref_length; -static char tmp_dir[FN_REFLEN]={0},*join_table; -static my_off_t intervall_length; -static ulong crc; -static struct st_file_buffer file_buffer; -static QUEUE queue; -static HUFF_COUNTS *global_count; -static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static const char *load_default_groups[]= { "pack_isam",0 }; - - /* The main program */ - -int main(int argc, char **argv) -{ - int error,ok; - MRG_INFO merge; - MY_INIT(argv[0]); - - load_defaults("my",load_default_groups,&argc,&argv); - get_options(&argc,&argv); - - error=ok=isamchk_neaded=0; - if (join_table) - { /* Join files into one */ - if (open_isam_files(&merge,argv,(uint) argc) || - compress(&merge,join_table)) - error=1; - } - else while (argc--) - { - N_INFO *isam_file; - if (!(isam_file=open_isam_file(*argv++,O_RDWR))) - error=1; - else - { - merge.file= &isam_file; - merge.current=0; - merge.count=1; - if (compress(&merge,0)) - error=1; - else - ok=1; - } - } - if (ok && isamchk_neaded && !silent) - puts("Remember to run isamchk -rq on compressed databases"); - VOID(fflush(stdout)); VOID(fflush(stderr)); - my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); - exit(error ? 2 : 0); -#ifndef _lint - return 0; /* No compiler warning */ -#endif -} - - -static struct my_option my_long_options[] = -{ - {"backup", 'b', "Make a backup of the table as table_name.OLD", - (gptr*) &backup, (gptr*) &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", - 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"force", 'f', - "Force packing of table even if it's gets bigger or tempfile exists.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"join", 'j', - "Join all given tables into 'new_table_name'. All tables MUST have the identical layout.", - (gptr*) &join_table, (gptr*) &join_table, 0, GET_STR, REQUIRED_ARG, 0, 0, - 0, 0, 0, 0}, - {"help", '?', "Display this help and exit.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"packlength", 'p', "Force storage size of recordlength (1, 2 or 3)", - (gptr*) &force_pack_ref_length, (gptr*) &force_pack_ref_length, 0, - GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"silent", 's', "Be more silent.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0}, - {"tmpdir", 'T', "Use temporary directory to store temporary table", - (gptr*) &tmp_dir, (gptr*) &tmp_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, - 0, 0}, - {"test", 't', "Don't pack table, only test packing it", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0}, - {"verbose", 'v', "Write info about progress and packing result", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0}, - {"version", 'V', "output version information and exit", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0}, - {"wait", 'w', "Wait and retry if table is in use", (gptr*) &opt_wait, - (gptr*) &opt_wait, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} -}; - - -static void print_version(void) -{ - printf("%s Ver 5.10 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); -} - -static void usage(void) -{ - print_version(); - puts("Copyright (C) 2002 MySQL AB"); - puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); - puts("and you are welcome to modify and redistribute it under the GPL license\n"); - - puts("Pack a ISAM-table to take much smaller space"); - puts("Keys are not updated, so you must run isamchk -rq on any table"); - puts("that has keys after you have compressed it"); - puts("You should give the .ISM file as the filename argument"); - - printf("\nUsage: %s [OPTIONS] filename...\n", my_progname); - my_print_help(my_long_options); - print_defaults("my", load_default_groups); - my_print_variables(my_long_options); -} - - -static my_bool -get_one_option(int optid, const struct my_option *opt __attribute__((unused)), - char *argument) -{ - uint length; - - switch(optid) { - case 'f': - force_pack= 1; - tmpfile_createflag= O_RDWR | O_TRUNC; - break; - case 'p': - if (force_pack_ref_length > 3) - force_pack_ref_length= 0; - break; - case 's': - write_loop= verbose= 0; - silent= 1; - break; - case 't': - test_only= verbose= 1; - break; - case 'T': - length=(uint) (strmov(tmp_dir, argument) - tmp_dir); - if (length != dirname_length(tmp_dir)) - { - tmp_dir[length]= FN_LIBCHAR; - tmp_dir[length + 1]= 0; - } - break; - case 'v': - verbose= 1; - silent= 0; - break; - case '#': - DBUG_PUSH(argument ? argument : "d:t:o"); - break; - case 'V': print_version(); exit(0); - case 'I': - case '?': - usage(); - exit(0); - } - return 0; -} - - /* reads options */ - /* Initiates DEBUG - but no debugging here ! */ - -static void get_options(int *argc, char ***argv) -{ - int ho_error; - - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) - exit(ho_error); - - my_progname= argv[0][0]; - if (isatty(fileno(stdout))) - write_loop=1; - - if (!*argc) - { - usage(); - exit(1); - } - if (join_table) - { - backup=0; /* Not needed */ - tmp_dir[0]=0; - } - return; -} - - -static N_INFO *open_isam_file(char *name,int mode) -{ - N_INFO *isam_file; - ISAM_SHARE *share; - DBUG_ENTER("open_isam_file"); - - if (!(isam_file=nisam_open(name,mode,(opt_wait ? HA_OPEN_WAIT_IF_LOCKED : - HA_OPEN_ABORT_IF_LOCKED)))) - { - VOID(fprintf(stderr,"%s gave error %d on open\n",name,my_errno)); - DBUG_RETURN(0); - } - share=isam_file->s; - if (share->base.blobs) - { - VOID(fprintf(stderr,"%s has blobs, can't pack it\n",name)); - VOID(nisam_close(isam_file)); - DBUG_RETURN(0); - } - if (share->base.options & HA_OPTION_COMPRESS_RECORD && !join_table) - { - if (!force_pack) - { - VOID(fprintf(stderr,"%s is already compressed\n",name)); - VOID(nisam_close(isam_file)); - DBUG_RETURN(0); - } - if (verbose) - puts("Recompressing already compressed table"); - share->base.options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */ - } - if (! force_pack && share->state.records != 0 && - (share->state.records <= 1 || - share->state.data_file_length < 1024) && ! join_table) - { - VOID(fprintf(stderr,"%s is too small to compress\n",name)); - VOID(nisam_close(isam_file)); - DBUG_RETURN(0); - } - VOID(nisam_lock_database(isam_file,F_WRLCK)); - DBUG_RETURN(isam_file); -} - - -static bool open_isam_files(MRG_INFO *mrg,char **names,uint count) -{ - uint i,j; - mrg->count=0; - mrg->current=0; - mrg->file=(N_INFO**) my_malloc(sizeof(N_INFO*)*count,MYF(MY_FAE)); - for (i=0; i < count ; i++) - { - if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY))) - goto error; - } - /* Check that files are identical */ - for (j=0 ; j < count-1 ; j++) - { - N_RECINFO *m1,*m2,*end; - if (mrg->file[j]->s->base.reclength != mrg->file[j+1]->s->base.reclength || - mrg->file[j]->s->base.fields != mrg->file[j+1]->s->base.fields) - goto diff_file; - m1=mrg->file[j]->s->rec; - end=m1+mrg->file[j]->s->base.fields; - m2=mrg->file[j+1]->s->rec; - for ( ; m1 != end ; m1++,m2++) - { - if ((m1->base.type != m2->base.type && ! force_pack) || - m1->base.length != m2->base.length) - goto diff_file; - } - } - mrg->count=count; - return 0; - - diff_file: - fprintf(stderr,"%s: Tables '%s' and '%s' are not identical\n", - my_progname,names[j],names[j+1]); - error: - while (i--) - nisam_close(mrg->file[i]); - return 1; -} - - -static int compress(MRG_INFO *mrg,char *result_table) -{ - int error; - File new_file,join_isam_file; - N_INFO *isam_file; - ISAM_SHARE *share; - char org_name[FN_REFLEN],new_name[FN_REFLEN],temp_name[FN_REFLEN]; - uint i,header_length,fields,trees,used_trees; - my_off_t old_length,new_length,tot_elements; - HUFF_COUNTS *huff_counts; - HUFF_TREE *huff_trees; - DBUG_ENTER("compress"); - - isam_file=mrg->file[0]; /* Take this as an example */ - share=isam_file->s; - new_file=join_isam_file= -1; - trees=fields=0; - huff_trees=0; - huff_counts=0; - - /* Create temporary or join file */ - - if (backup) - VOID(fn_format(org_name,isam_file->filename,"",N_NAME_DEXT,2)); - else - VOID(fn_format(org_name,isam_file->filename,"",N_NAME_DEXT,2+4+16)); - if (!test_only && result_table) - { - /* Make a new indexfile based on first file in list */ - uint length; - char *buff; - strmov(org_name,result_table); /* Fix error messages */ - VOID(fn_format(new_name,result_table,"",N_NAME_IEXT,2)); - if ((join_isam_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME))) - < 0) - goto err; - length=share->base.keystart; - if (!(buff=my_malloc(length,MYF(MY_WME)))) - goto err; - if (my_pread(share->kfile,buff,length,0L,MYF(MY_WME | MY_NABP)) || - my_write(join_isam_file,buff,length, - MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) - { - my_free(buff,MYF(0)); - goto err; - } - my_free(buff,MYF(0)); - VOID(fn_format(new_name,result_table,"",N_NAME_DEXT,2)); - } - else if (!tmp_dir[0]) - VOID(make_new_name(new_name,org_name)); - else - VOID(fn_format(new_name,org_name,tmp_dir,DATA_TMP_EXT,1+2+4)); - if (!test_only && - (new_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME))) < 0) - goto err; - - /* Start calculating statistics */ - - mrg->records=0; - for (i=0 ; i < mrg->count ; i++) - mrg->records+=mrg->file[i]->s->state.records; - if (write_loop || verbose) - { - printf("Compressing %s: (%lu records)\n", - result_table ? new_name : org_name,(ulong) mrg->records); - } - trees=fields=share->base.fields; - huff_counts=init_huff_count(isam_file,mrg->records); - QUICK_SAFEMALLOC; - if (write_loop || verbose) - printf("- Calculating statistics\n"); - if (get_statistic(mrg,huff_counts)) - goto err; - NORMAL_SAFEMALLOC; - old_length=0; - for (i=0; i < mrg->count ; i++) - old_length+= (mrg->file[i]->s->state.data_file_length - - mrg->file[i]->s->state.empty); - - if (init_queue(&queue,256,0,0,compare_huff_elements,0)) - goto err; - check_counts(huff_counts,fields,mrg->records); - huff_trees=make_huff_trees(huff_counts,trees); - if ((int) (used_trees=join_same_trees(huff_counts,trees)) < 0) - goto err; - if (make_huff_decode_table(huff_trees,fields)) - goto err; - - init_file_buffer(new_file,0); - file_buffer.pos_in_file=HEAD_LENGTH; - if (! test_only) - VOID(my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0))); - - write_field_info(huff_counts,fields,used_trees); - if (!(tot_elements=write_huff_tree(huff_trees,trees))) - goto err; - header_length=(uint) file_buffer.pos_in_file+ - (uint) (file_buffer.pos-file_buffer.buffer); - - /* Compress file */ - if (write_loop || verbose) - printf("- Compressing file\n"); - error=compress_isam_file(mrg,huff_counts); - new_length=file_buffer.pos_in_file; - if (!error && !test_only) - { - char buff[MEMMAP_EXTRA_MARGIN]; /* End marginal for memmap */ - bzero(buff,sizeof(buff)); - error=my_write(file_buffer.file,buff,sizeof(buff), - MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; - } - if (!error) - error=write_header(mrg,header_length,used_trees,tot_elements, - new_length); - end_file_buffer(); - - if (verbose && mrg->records) - printf("Min record length: %6d Max length: %6d Mean total length: %6lu\n", - mrg->min_pack_length,mrg->max_pack_length, - (ulong) (new_length/mrg->records)); - - if (!test_only) - { - error|=my_close(new_file,MYF(MY_WME)); - if (!result_table) - { - error|=my_close(isam_file->dfile,MYF(MY_WME)); - isam_file->dfile= -1; /* Tell nisam_close file is closed */ - } - } - - free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields); - if (! test_only && ! error) - { - if (result_table) - { - error=save_state_mrg(join_isam_file,mrg,new_length,crc); - } - else - { - if (backup) - { - if (my_rename(org_name,make_old_name(temp_name,isam_file->filename), - MYF(MY_WME))) - error=1; - else - { - if (tmp_dir[0]) - { - if (!(error=my_copy(new_name,org_name,MYF(MY_WME)))) - VOID(my_delete(new_name,MYF(MY_WME))); - } - else - error=my_rename(new_name,org_name,MYF(MY_WME)); - if (!error) - VOID(my_copystat(temp_name,org_name,MYF(MY_COPYTIME))); - } - } - else - { - if (tmp_dir[0]) - { - - if (!(error=my_copy(new_name,org_name, - MYF(MY_WME | MY_HOLD_ORIGINAL_MODES - | MY_COPYTIME)))) - VOID(my_delete(new_name,MYF(MY_WME))); - } - else - error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME)); - } - if (! error) - save_state(isam_file,mrg,new_length,crc); - } - } - error|=mrg_close(mrg); - if (join_isam_file >= 0) - error|=my_close(join_isam_file,MYF(MY_WME)); - if (error) - { - VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name)); - DBUG_RETURN(-1); - } - if (write_loop || verbose) - { - if (old_length) - printf("%.4g%% \n", - my_off_t2double(old_length-new_length)*100.0/ - my_off_t2double(old_length)); - else - puts("Empty file saved in compressed format"); - } - DBUG_RETURN(0); - - err: - free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields); - if (new_file >= 0) - VOID(my_close(new_file,MYF(0))); - if (join_isam_file >= 0) - VOID(my_close(join_isam_file,MYF(0))); - mrg_close(mrg); - VOID(fprintf(stderr,"Aborted: %s is not compressed\n",org_name)); - DBUG_RETURN(-1); -} - - /* Init a huff_count-struct for each field and init it */ - -static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records) -{ - reg2 uint i; - reg1 HUFF_COUNTS *count; - if ((count = (HUFF_COUNTS*) my_malloc(info->s->base.fields*sizeof(HUFF_COUNTS), - MYF(MY_ZEROFILL | MY_WME)))) - { - for (i=0 ; i < info->s->base.fields ; i++) - { - enum en_fieldtype type; - count[i].field_length=info->s->rec[i].base.length; - type= count[i].field_type= (enum en_fieldtype) info->s->rec[i].base.type; - if (type == FIELD_INTERVALL || - type == FIELD_CONSTANT || - type == FIELD_ZERO) - type = FIELD_NORMAL; - if (count[i].field_length <= 8 && - (type == FIELD_NORMAL || - type == FIELD_SKIP_ZERO)) - count[i].max_zero_fill= count[i].field_length; - init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, - NULL, NULL); - if (records) - count[i].tree_pos=count[i].tree_buff = - my_malloc(count[i].field_length > 1 ? tree_buff_length : 2, - MYF(MY_WME)); - } - } - return count; -} - - - /* Free memory used by counts and trees */ - -static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees, uint trees, HUFF_COUNTS *huff_counts, uint fields) -{ - register uint i; - - if (huff_trees) - { - for (i=0 ; i < trees ; i++) - { - if (huff_trees[i].element_buffer) - my_free((gptr) huff_trees[i].element_buffer,MYF(0)); - if (huff_trees[i].code) - my_free((gptr) huff_trees[i].code,MYF(0)); - } - my_free((gptr) huff_trees,MYF(0)); - } - if (huff_counts) - { - for (i=0 ; i < fields ; i++) - { - if (huff_counts[i].tree_buff) - { - my_free((gptr) huff_counts[i].tree_buff,MYF(0)); - delete_tree(&huff_counts[i].int_tree); - } - } - my_free((gptr) huff_counts,MYF(0)); - } - delete_queue(&queue); /* This is safe to free */ - return; -} - - /* Read through old file and gather some statistics */ - -static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts) -{ - int error; - uint length,reclength; - byte *record,*pos,*next_pos,*end_pos,*start_pos; - my_off_t record_count; - HUFF_COUNTS *count,*end_count; - TREE_ELEMENT *element; - DBUG_ENTER("get_statistic"); - - reclength=mrg->file[0]->s->base.reclength; - record=(byte*) my_alloca(reclength); - end_count=huff_counts+mrg->file[0]->s->base.fields; - record_count=crc=0; - - mrg_reset(mrg); - while ((error=mrg_rrnd(mrg,record)) >= 0) - { - if (! error) - { - crc^=_nisam_checksum(record,reclength); - for (pos=record,count=huff_counts ; - count < end_count ; - count++, - pos=next_pos) - { - next_pos=end_pos=(start_pos=pos)+count->field_length; - - /* Put value in tree if there is room for it */ - if (count->tree_buff) - { - global_count=count; - if (!(element=tree_insert(&count->int_tree, pos, 0, - count->int_tree.custom_arg)) || - ((element->count == 1 && - count->tree_buff + tree_buff_length < - count->tree_pos + count->field_length) || - (count->field_length == 1 && - count->int_tree.elements_in_tree > 1))) - { - delete_tree(&count->int_tree); - my_free(count->tree_buff,MYF(0)); - count->tree_buff=0; - } - else - { - if (element->count == 1) - { /* New element */ - memcpy(count->tree_pos,pos,(size_t) count->field_length); - tree_set_pointer(element,count->tree_pos); - count->tree_pos+=count->field_length; - } - } - } - - /* Save character counters and space-counts and zero-field-counts */ - if (count->field_type == FIELD_NORMAL || - count->field_type == FIELD_SKIP_ENDSPACE) - { - for ( ; end_pos > pos ; end_pos--) - if (end_pos[-1] != ' ') - break; - if (end_pos == pos) - { - count->empty_fields++; - count->max_zero_fill=0; - continue; - } - length= (uint) (next_pos-end_pos); - count->tot_end_space+=length; - if (length < 8) - count->end_space[length]++; - if (count->max_end_space < length) - count->max_end_space = length; - } - if (count->field_type == FIELD_NORMAL || - count->field_type == FIELD_SKIP_PRESPACE) - { - for (pos=start_pos; pos < end_pos ; pos++) - if (pos[0] != ' ') - break; - if (end_pos == pos) - { - count->empty_fields++; - count->max_zero_fill=0; - continue; - } - length= (uint) (pos-start_pos); - count->tot_pre_space+=length; - if (length < 8) - count->pre_space[length]++; - if (count->max_pre_space < length) - count->max_pre_space = length; - } - if (count->field_length <= 8 && - (count->field_type == FIELD_NORMAL || - count->field_type == FIELD_SKIP_ZERO)) - { - uint i; - if (!memcmp((byte*) start_pos,zero_string,count->field_length)) - { - count->zero_fields++; - continue; - } -#ifdef BYTE_ORDER_HIGH_FIRST - for (i =0 ; i < count->max_zero_fill && ! start_pos[i] ; i++) ; - if (i < count->max_zero_fill) - count->max_zero_fill=i; -#else - for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ; i++) ; - if (i < count->max_zero_fill) - count->max_zero_fill=i; -#endif - } - for (pos=start_pos ; pos < end_pos ; pos++) - count->counts[(uchar) *pos]++; - } - record_count++; - if (write_loop && record_count % WRITE_COUNT == 0) - { - printf("%lu\r",(ulong) record_count); VOID(fflush(stdout)); - } - } - } - if (write_loop) - { - printf(" \r"); VOID(fflush(stdout)); - } - mrg->records=record_count; - my_afree((gptr) record); - DBUG_RETURN(0); -} - -static int compare_huff_elements(void *not_used __attribute__((unused)), - byte *a, byte *b) -{ - return *((my_off_t*) a) < *((my_off_t*) b) ? -1 : - (*((my_off_t*) a) == *((my_off_t*) b) ? 0 : 1); -} - - /* Check each tree if we should use pre-space-compress, end-space- - compress, empty-field-compress or zero-field-compress */ - -static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records) -{ - uint space_fields,fill_zero_fields,field_count[(int) FIELD_ZERO+1]; - my_off_t old_length,new_length,length; - DBUG_ENTER("check_counts"); - - bzero((gptr) field_count,sizeof(field_count)); - space_fields=fill_zero_fields=0; - - for (; trees-- ; huff_counts++) - { - huff_counts->field_type=FIELD_NORMAL; - huff_counts->pack_type=0; - - if (huff_counts->zero_fields || ! records) - { - my_off_t old_space_count; - if (huff_counts->zero_fields == records) - { - huff_counts->field_type= FIELD_ZERO; - huff_counts->bytes_packed=0; - huff_counts->counts[0]=0; - goto found_pack; - } - old_space_count=huff_counts->counts[' ']; - huff_counts->counts[' ']+=huff_counts->tot_end_space+ - huff_counts->tot_pre_space + - huff_counts->empty_fields * huff_counts->field_length; - old_length=calc_packed_length(huff_counts,0)+records/8; - length=huff_counts->zero_fields*huff_counts->field_length; - huff_counts->counts[0]+=length; - new_length=calc_packed_length(huff_counts,0); - if (old_length < new_length && huff_counts->field_length > 1) - { - huff_counts->field_type=FIELD_SKIP_ZERO; - huff_counts->counts[0]-=length; - huff_counts->bytes_packed=old_length- records/8; - goto found_pack; - } - huff_counts->counts[' ']=old_space_count; - } - huff_counts->bytes_packed=calc_packed_length(huff_counts,0); - if (huff_counts->empty_fields) - { - if (huff_counts->field_length > 2 && - huff_counts->empty_fields + (records - huff_counts->empty_fields)* - (1+max_bit(max(huff_counts->max_pre_space, - huff_counts->max_end_space))) < - records * max_bit(huff_counts->field_length)) - { - huff_counts->pack_type |= PACK_TYPE_SPACE_FIELDS; - } - else - { - length=huff_counts->empty_fields*huff_counts->field_length; - if (huff_counts->tot_end_space || ! huff_counts->tot_pre_space) - { - huff_counts->tot_end_space+=length; - huff_counts->max_end_space=huff_counts->field_length; - if (huff_counts->field_length < 8) - huff_counts->end_space[huff_counts->field_length]+= - huff_counts->empty_fields; - } - else - { - huff_counts->tot_pre_space+=length; - huff_counts->max_pre_space=huff_counts->field_length; - if (huff_counts->field_length < 8) - huff_counts->pre_space[huff_counts->field_length]+= - huff_counts->empty_fields; - } - } - } - if (huff_counts->tot_end_space) - { - huff_counts->counts[' ']+=huff_counts->tot_pre_space; - if (test_space_compress(huff_counts,records,huff_counts->max_end_space, - huff_counts->end_space, - huff_counts->tot_end_space,FIELD_SKIP_ENDSPACE)) - goto found_pack; - huff_counts->counts[' ']-=huff_counts->tot_pre_space; - } - if (huff_counts->tot_pre_space) - { - if (test_space_compress(huff_counts,records,huff_counts->max_pre_space, - huff_counts->pre_space, - huff_counts->tot_pre_space,FIELD_SKIP_PRESPACE)) - goto found_pack; - } - - found_pack: /* Found field-packing */ - - /* Test if we can use zero-fill */ - - if (huff_counts->max_zero_fill && - (huff_counts->field_type == FIELD_NORMAL || - huff_counts->field_type == FIELD_SKIP_ZERO)) - { - huff_counts->counts[0]-=huff_counts->max_zero_fill* - (huff_counts->field_type == FIELD_SKIP_ZERO ? - records - huff_counts->zero_fields : records); - huff_counts->pack_type|=PACK_TYPE_ZERO_FILL; - huff_counts->bytes_packed=calc_packed_length(huff_counts,0); - } - - /* Test if intervall-field is better */ - - if (huff_counts->tree_buff) - { - HUFF_TREE tree; - - tree.element_buffer=0; - if (!make_huff_tree(&tree,huff_counts) && - tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed) - { - if (tree.elements == 1) - huff_counts->field_type=FIELD_CONSTANT; - else - huff_counts->field_type=FIELD_INTERVALL; - huff_counts->pack_type=0; - } - else - { - my_free((gptr) huff_counts->tree_buff,MYF(0)); - delete_tree(&huff_counts->int_tree); - huff_counts->tree_buff=0; - } - if (tree.element_buffer) - my_free((gptr) tree.element_buffer,MYF(0)); - } - if (huff_counts->pack_type & PACK_TYPE_SPACE_FIELDS) - space_fields++; - if (huff_counts->pack_type & PACK_TYPE_ZERO_FILL) - fill_zero_fields++; - field_count[huff_counts->field_type]++; - } - if (verbose) - printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d table-lookup: %3d zero: %3d\n", - field_count[FIELD_NORMAL],space_fields, - field_count[FIELD_SKIP_ZERO],fill_zero_fields, - field_count[FIELD_SKIP_PRESPACE], - field_count[FIELD_SKIP_ENDSPACE], - field_count[FIELD_INTERVALL], - field_count[FIELD_ZERO]); - DBUG_VOID_RETURN; -} - - /* Test if we can use space-compression and empty-field-compression */ - -static int -test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records, - uint max_space_length, my_off_t *space_counts, - my_off_t tot_space_count, enum en_fieldtype field_type) -{ - int min_pos; - uint length_bits,i; - my_off_t space_count,min_space_count,min_pack,new_length,skipp; - - length_bits=max_bit(max_space_length); - - /* Default no end_space-packing */ - space_count=huff_counts->counts[(uint) ' ']; - min_space_count= (huff_counts->counts[(uint) ' ']+= tot_space_count); - min_pack=calc_packed_length(huff_counts,0); - min_pos= -2; - huff_counts->counts[(uint) ' ']=space_count; - - /* Test with allways space-count */ - new_length=huff_counts->bytes_packed+length_bits*records/8; - if (new_length+1 < min_pack) - { - min_pos= -1; - min_pack=new_length; - min_space_count=space_count; - } - /* Test with length-flag */ - for (skipp=0L, i=0 ; i < 8 ; i++) - { - if (space_counts[i]) - { - if (i) - huff_counts->counts[(uint) ' ']+=space_counts[i]; - skipp+=huff_counts->pre_space[i]; - new_length=calc_packed_length(huff_counts,0)+ - (records+(records-skipp)*(1+length_bits))/8; - if (new_length < min_pack) - { - min_pos=(int) i; - min_pack=new_length; - min_space_count=huff_counts->counts[(uint) ' ']; - } - } - } - - huff_counts->counts[(uint) ' ']=min_space_count; - huff_counts->bytes_packed=min_pack; - switch (min_pos) { - case -2: - return(0); /* No space-compress */ - case -1: /* Always space-count */ - huff_counts->field_type=field_type; - huff_counts->min_space=0; - huff_counts->length_bits=max_bit(max_space_length); - break; - default: - huff_counts->field_type=field_type; - huff_counts->min_space=(uint) min_pos; - huff_counts->pack_type|=PACK_TYPE_SELECTED; - huff_counts->length_bits=max_bit(max_space_length); - break; - } - return(1); /* Using space-compress */ -} - - - /* Make a huff_tree of each huff_count */ - -static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts, uint trees) -{ - uint tree; - HUFF_TREE *huff_tree; - DBUG_ENTER("make_huff_trees"); - - if (!(huff_tree=(HUFF_TREE*) my_malloc(trees*sizeof(HUFF_TREE), - MYF(MY_WME | MY_ZEROFILL)))) - DBUG_RETURN(0); - - for (tree=0 ; tree < trees ; tree++) - { - if (make_huff_tree(huff_tree+tree,huff_counts+tree)) - { - while (tree--) - my_free((gptr) huff_tree[tree].element_buffer,MYF(0)); - my_free((gptr) huff_tree,MYF(0)); - DBUG_RETURN(0); - } - } - DBUG_RETURN(huff_tree); -} - - /* Update huff_tree according to huff_counts->counts or - huff_counts->tree_buff */ - -static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) -{ - uint i,found,bits_packed,first,last; - my_off_t bytes_packed; - HUFF_ELEMENT *a,*b,*new; - - first=last=0; - if (huff_counts->tree_buff) - { - found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) / - huff_counts->field_length; - first=0; last=found-1; - } - else - { - for (i=found=0 ; i < 256 ; i++) - { - if (huff_counts->counts[i]) - { - if (! found++) - first=i; - last=i; - } - } - if (found < 2) - found=2; - } - - if (queue.max_elements < found) - { - delete_queue(&queue); - if (init_queue(&queue,found,0,0,compare_huff_elements,0)) - return -1; - } - - if (!huff_tree->element_buffer) - { - if (!(huff_tree->element_buffer= - (HUFF_ELEMENT*) my_malloc(found*2*sizeof(HUFF_ELEMENT),MYF(MY_WME)))) - return 1; - } - else - { - HUFF_ELEMENT *temp; - if (!(temp= - (HUFF_ELEMENT*) my_realloc((gptr) huff_tree->element_buffer, - found*2*sizeof(HUFF_ELEMENT), - MYF(MY_WME)))) - return 1; - huff_tree->element_buffer=temp; - } - - huff_counts->tree=huff_tree; - huff_tree->counts=huff_counts; - huff_tree->min_chr=first; - huff_tree->max_chr=last; - huff_tree->char_bits=max_bit(last-first); - huff_tree->offset_bits=max_bit(found-1)+1; - - if (huff_counts->tree_buff) - { - huff_tree->elements=0; - tree_walk(&huff_counts->int_tree, - (int (*)(void*, element_count,void*)) save_counts_in_queue, - (gptr) huff_tree, left_root_right); - huff_tree->tree_pack_length=(1+15+16+5+5+ - (huff_tree->char_bits+1)*found+ - (huff_tree->offset_bits+1)* - (found-2)+7)/8 + - (uint) (huff_tree->counts->tree_pos- - huff_tree->counts->tree_buff); - } - else - { - huff_tree->elements=found; - huff_tree->tree_pack_length=(9+9+5+5+ - (huff_tree->char_bits+1)*found+ - (huff_tree->offset_bits+1)* - (found-2)+7)/8; - - for (i=first, found=0 ; i <= last ; i++) - { - if (huff_counts->counts[i]) - { - new=huff_tree->element_buffer+(found++); - new->count=huff_counts->counts[i]; - new->a.leaf.null=0; - new->a.leaf.element_nr=i; - queue.root[found]=(byte*) new; - } - } - while (found < 2) - { /* Our huff_trees request at least 2 elements */ - new=huff_tree->element_buffer+(found++); - new->count=0; - new->a.leaf.null=0; - if (last) - new->a.leaf.element_nr=huff_tree->min_chr=last-1; - else - new->a.leaf.element_nr=huff_tree->max_chr=last+1; - queue.root[found]=(byte*) new; - } - } - queue.elements=found; - - for (i=found/2 ; i > 0 ; i--) - _downheap(&queue,i); - bytes_packed=0; bits_packed=0; - for (i=1 ; i < found ; i++) - { - a=(HUFF_ELEMENT*) queue_remove(&queue,0); - b=(HUFF_ELEMENT*) queue.root[1]; - new=huff_tree->element_buffer+found+i; - new->count=a->count+b->count; - bits_packed+=(uint) (new->count & 7); - bytes_packed+=new->count/8; - new->a.nod.left=a; /* lesser in left */ - new->a.nod.right=b; - queue.root[1]=(byte*) new; - queue_replaced(&queue); - } - huff_tree->root=(HUFF_ELEMENT*) queue.root[1]; - huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8; - return 0; -} - -static int compare_tree(register const uchar *s, register const uchar *t) -{ - uint length; - for (length=global_count->field_length; length-- ;) - if (*s++ != *t++) - return (int) s[-1] - (int) t[-1]; - return 0; -} - - /* Used by make_huff_tree to save intervall-counts in queue */ - -static int save_counts_in_queue(byte *key, element_count count, HUFF_TREE *tree) -{ - HUFF_ELEMENT *new; - - new=tree->element_buffer+(tree->elements++); - new->count=count; - new->a.leaf.null=0; - new->a.leaf.element_nr= (uint) (key- tree->counts->tree_buff) / - tree->counts->field_length; - queue.root[tree->elements]=(byte*) new; - return 0; -} - - - /* Calculate length of file if given counts should be used */ - /* Its actually a faster version of make_huff_tree */ - -static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, uint add_tree_lenght) -{ - uint i,found,bits_packed,first,last; - my_off_t bytes_packed; - HUFF_ELEMENT element_buffer[256]; - DBUG_ENTER("calc_packed_length"); - - first=last=0; - for (i=found=0 ; i < 256 ; i++) - { - if (huff_counts->counts[i]) - { - if (! found++) - first=i; - last=i; - queue.root[found]=(byte*) &huff_counts->counts[i]; - } - } - if (!found) - DBUG_RETURN(0); /* Empty tree */ - if (found < 2) - queue.root[++found]=(byte*) &huff_counts->counts[last ? 0 : 1]; - - queue.elements=found; - - bytes_packed=0; bits_packed=0; - if (add_tree_lenght) - bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+ - (max_bit(found-1)+1+1)*(found-2) +7)/8; - for (i=(found+1)/2 ; i > 0 ; i--) - _downheap(&queue,i); - for (i=0 ; i < found-1 ; i++) - { - HUFF_ELEMENT *a,*b,*new; - a=(HUFF_ELEMENT*) queue_remove(&queue,0); - b=(HUFF_ELEMENT*) queue.root[1]; - new=element_buffer+i; - new->count=a->count+b->count; - bits_packed+=(uint) (new->count & 7); - bytes_packed+=new->count/8; - queue.root[1]=(byte*) new; - queue_replaced(&queue); - } - DBUG_RETURN(bytes_packed+(bits_packed+7)/8); -} - - - /* Remove trees that don't give any compression */ - -static uint join_same_trees(HUFF_COUNTS *huff_counts, uint trees) -{ - uint k,tree_number; - HUFF_COUNTS count,*i,*j,*last_count; - - last_count=huff_counts+trees; - for (tree_number=0, i=huff_counts ; i < last_count ; i++) - { - if (!i->tree->tree_number) - { - i->tree->tree_number= ++tree_number; - if (i->tree_buff) - continue; /* Don't join intervall */ - for (j=i+1 ; j < last_count ; j++) - { - if (! j->tree->tree_number && ! j->tree_buff) - { - for (k=0 ; k < 256 ; k++) - count.counts[k]=i->counts[k]+j->counts[k]; - if (calc_packed_length(&count,1) <= - i->tree->bytes_packed + j->tree->bytes_packed+ - i->tree->tree_pack_length+j->tree->tree_pack_length+ - ALLOWED_JOIN_DIFF) - { - memcpy((byte*) i->counts,(byte*) count.counts, - sizeof(count.counts[0])*256); - my_free((gptr) j->tree->element_buffer,MYF(0)); - j->tree->element_buffer=0; - j->tree=i->tree; - bmove((byte*) i->counts,(byte*) count.counts, - sizeof(count.counts[0])*256); - if (make_huff_tree(i->tree,i)) - return (uint) -1; - } - } - } - } - } - if (verbose) - printf("Original trees: %d After join: %d\n",trees,tree_number); - return tree_number; /* Return trees left */ -} - - - /* Fill in huff_tree decode tables */ - -static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees) -{ - uint elements; - for ( ; trees-- ; huff_tree++) - { - if (huff_tree->tree_number > 0) - { - elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256; - if (!(huff_tree->code = - (ulong*) my_malloc(elements* - (sizeof(ulong)+sizeof(uchar)), - MYF(MY_WME | MY_ZEROFILL)))) - return 1; - huff_tree->code_len=(uchar*) (huff_tree->code+elements); - make_traverse_code_tree(huff_tree,huff_tree->root,32,0); - } - } - return 0; -} - - -static void make_traverse_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element, - uint size, ulong code) -{ - uint chr; - if (!element->a.leaf.null) - { - chr=element->a.leaf.element_nr; - huff_tree->code_len[chr]=(uchar) (32-size); - huff_tree->code[chr]= (code >> size); - if (huff_tree->height < 32-size) - huff_tree->height= 32-size; - } - else - { - size--; - make_traverse_code_tree(huff_tree,element->a.nod.left,size,code); - make_traverse_code_tree(huff_tree,element->a.nod.right,size, - code+((ulong) 1L << size)); - } - return; -} - - - /* Write header to new packed data file */ - -static int write_header(MRG_INFO *mrg,uint head_length,uint trees, - my_off_t tot_elements,my_off_t filelength) -{ - byte *buff=file_buffer.pos; - - bzero(buff,HEAD_LENGTH); - memcpy(buff,nisam_pack_file_magic,4); - int4store(buff+4,head_length); - int4store(buff+8, mrg->min_pack_length); - int4store(buff+12,mrg->max_pack_length); - int4store(buff+16,tot_elements); - int4store(buff+20,intervall_length); - int2store(buff+24,trees); - buff[26]=(char) mrg->ref_length; - /* Save record pointer length */ - buff[27]= (uchar) (filelength >= (1L << 24) ? 4 : - filelength >= (1L << 16) ? 3 : 2); - if (test_only) - return 0; - VOID(my_seek(file_buffer.file,0L,MY_SEEK_SET,MYF(0))); - return my_write(file_buffer.file,file_buffer.pos,HEAD_LENGTH, - MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; -} - - /* Write fieldinfo to new packed file */ - -static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees) -{ - reg1 uint i; - uint huff_tree_bits; - huff_tree_bits=max_bit(trees ? trees-1 : 0); - - for (i=0 ; i++ < fields ; counts++) - { - write_bits((ulong) (int) counts->field_type,4); - write_bits(counts->pack_type,4); - if (counts->pack_type & PACK_TYPE_ZERO_FILL) - write_bits(counts->max_zero_fill,4); - else - write_bits(counts->length_bits,4); - write_bits((ulong) counts->tree->tree_number-1,huff_tree_bits); - } - flush_bits(); - return; -} - - /* Write all huff_trees to new datafile. Return tot count of - elements in all trees - Returns 0 on error */ - -static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) -{ - uint i,int_length; - uint *packed_tree,*offset,length; - my_off_t elements; - - for (i=length=0 ; i < trees ; i++) - if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length) - length=huff_tree[i].elements; - if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2))) - { - my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2); - return 0; - } - - intervall_length=0; - for (elements=0; trees-- ; huff_tree++) - { - if (huff_tree->tree_number == 0) - continue; /* Deleted tree */ - elements+=huff_tree->elements; - huff_tree->max_offset=2; - if (huff_tree->elements <= 1) - offset=packed_tree; - else - offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree); - huff_tree->offset_bits=max_bit(huff_tree->max_offset); - if (huff_tree->max_offset >= IS_OFFSET) - { /* This should be impossible */ - VOID(fprintf(stderr,"Tree offset got too big: %d, aborted\n", - huff_tree->max_offset)); - my_afree((gptr) packed_tree); - return 0; - } - -#ifdef EXTRA_DBUG - printf("pos: %d elements: %d tree-elements: %d char_bits: %d\n", - (uint) (file_buffer.pos-file_buffer.buffer), - huff_tree->elements, (offset-packed_tree),huff_tree->char_bits); -#endif - if (!huff_tree->counts->tree_buff) - { - write_bits(0,1); - write_bits(huff_tree->min_chr,8); - write_bits(huff_tree->elements,9); - write_bits(huff_tree->char_bits,5); - write_bits(huff_tree->offset_bits,5); - int_length=0; - } - else - { - int_length=(uint) (huff_tree->counts->tree_pos - - huff_tree->counts->tree_buff); - write_bits(1,1); - write_bits(huff_tree->elements,15); - write_bits(int_length,16); - write_bits(huff_tree->char_bits,5); - write_bits(huff_tree->offset_bits,5); - intervall_length+=int_length; - } - length=(uint) (offset-packed_tree); - if (length != huff_tree->elements*2-2) - printf("error: Huff-tree-length: %d != calc_length: %d\n", - length,huff_tree->elements*2-2); - - for (i=0 ; i < length ; i++) - { - if (packed_tree[i] & IS_OFFSET) - write_bits(packed_tree[i] - IS_OFFSET+ ((ulong) 1L << huff_tree->offset_bits), - huff_tree->offset_bits+1); - else - write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1); - } - flush_bits(); - if (huff_tree->counts->tree_buff) - { - for (i=0 ; i < int_length ; i++) - write_bits((uint) (uchar) huff_tree->counts->tree_buff[i],8); - } - flush_bits(); - } - my_afree((gptr) packed_tree); - return elements; -} - - -static uint *make_offset_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element, - uint *offset) -{ - uint *prev_offset; - - prev_offset= offset; - if (!element->a.nod.left->a.leaf.null) - { - offset[0] =(uint) element->a.nod.left->a.leaf.element_nr; - offset+=2; - } - else - { - prev_offset[0]= IS_OFFSET+2; - offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2); - } - if (!element->a.nod.right->a.leaf.null) - { - prev_offset[1]=element->a.nod.right->a.leaf.element_nr; - return offset; - } - else - { - uint temp=(uint) (offset-prev_offset-1); - prev_offset[1]= IS_OFFSET+ temp; - if (huff_tree->max_offset < temp) - huff_tree->max_offset = temp; - return make_offset_code_tree(huff_tree,element->a.nod.right,offset); - } -} - - /* Get number of bits neaded to represent value */ - -static uint max_bit(register uint value) -{ - reg2 uint power=1; - - while ((value>>=1)) - power++; - return (power); -} - - -static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts) -{ - int error; - uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length, - intervall,field_length; - my_off_t record_count,max_allowed_length; - ulong length; - byte *record,*pos,*end_pos,*record_pos,*start_pos; - HUFF_COUNTS *count,*end_count; - HUFF_TREE *tree; - N_INFO *isam_file=mrg->file[0]; - DBUG_ENTER("compress_isam_file"); - - if (!(record=(byte*) my_alloca(isam_file->s->base.reclength))) - return -1; - end_count=huff_counts+isam_file->s->base.fields; - min_record_length= (uint) ~0; - max_record_length=0; - - for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++) - { - if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL)) - huff_counts[i].max_zero_fill=0; - if (huff_counts[i].field_type == FIELD_CONSTANT || - huff_counts[i].field_type == FIELD_ZERO) - continue; - if (huff_counts[i].field_type == FIELD_INTERVALL) - max_calc_length+=huff_counts[i].tree->height; - else - max_calc_length+= - (huff_counts[i].field_length - huff_counts[i].max_zero_fill)* - huff_counts[i].tree->height+huff_counts[i].length_bits; - } - max_calc_length/=8; - if (max_calc_length <= 255) - pack_ref_length=1; - else if (max_calc_length <= 65535) - pack_ref_length=2; - else - pack_ref_length=3; - if (force_pack_ref_length) - pack_ref_length=force_pack_ref_length; - max_allowed_length= 1L << (pack_ref_length*8); - record_count=0; - - mrg_reset(mrg); - while ((error=mrg_rrnd(mrg,record)) >= 0) - { - if (! error) - { - if (flush_buffer(max_calc_length+pack_ref_length)) - break; - record_pos=file_buffer.pos; - file_buffer.pos+=pack_ref_length; - for (start_pos=record, count= huff_counts; count < end_count ; count++) - { - end_pos=start_pos+(field_length=count->field_length); - tree=count->tree; - - if (count->pack_type & PACK_TYPE_SPACE_FIELDS) - { - for (pos=start_pos ; *pos == ' ' && pos < end_pos; pos++) ; - if (pos == end_pos) - { - write_bits(1,1); - start_pos=end_pos; - continue; - } - write_bits(0,1); - } - -#ifdef BYTE_ORDER_HIGH_FIRST - start_pos+=count->max_zero_fill; -#else - end_pos-=count->max_zero_fill; -#endif - field_length-=count->max_zero_fill; - - switch(count->field_type) { - case FIELD_SKIP_ZERO: - if (!memcmp((byte*) start_pos,zero_string,field_length)) - { - write_bits(1,1); - start_pos=end_pos; - break; - } - write_bits(0,1); - /* Fall through */ - case FIELD_NORMAL: - for ( ; start_pos < end_pos ; start_pos++) - write_bits(tree->code[(uchar) *start_pos], - (uint) tree->code_len[(uchar) *start_pos]); - break; - case FIELD_SKIP_ENDSPACE: - for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ; - length=(uint) (end_pos-pos); - if (count->pack_type & PACK_TYPE_SELECTED) - { - if (length > count->min_space) - { - write_bits(1,1); - write_bits(length,count->length_bits); - } - else - { - write_bits(0,1); - pos=end_pos; - } - } - else - write_bits(length,count->length_bits); - for ( ; start_pos < pos ; start_pos++) - write_bits(tree->code[(uchar) *start_pos], - (uint) tree->code_len[(uchar) *start_pos]); - start_pos=end_pos; - break; - case FIELD_SKIP_PRESPACE: - for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ; - length=(uint) (pos-start_pos); - if (count->pack_type & PACK_TYPE_SELECTED) - { - if (length > count->min_space) - { - write_bits(1,1); - write_bits(length,count->length_bits); - } - else - { - pos=start_pos; - write_bits(0,1); - } - } - else - write_bits(length,count->length_bits); - for (start_pos=pos ; start_pos < end_pos ; start_pos++) - write_bits(tree->code[(uchar) *start_pos], - (uint) tree->code_len[(uchar) *start_pos]); - break; - case FIELD_CONSTANT: - case FIELD_ZERO: - start_pos=end_pos; - break; - case FIELD_INTERVALL: - global_count=count; - pos=(byte*) tree_search(&count->int_tree, start_pos, - count->int_tree.custom_arg); - intervall=(uint) (pos - count->tree_buff)/field_length; - write_bits(tree->code[intervall],(uint) tree->code_len[intervall]); - start_pos=end_pos; - break; - case FIELD_BLOB: - VOID(fprintf(stderr,"Can't pack files with blobs. Aborting\n")); - DBUG_RETURN(1); - case FIELD_LAST: - case FIELD_VARCHAR: - case FIELD_CHECK: - abort(); /* Impossible */ - } -#ifndef BYTE_ORDER_HIGH_FIRST - start_pos+=count->max_zero_fill; -#endif - } - flush_bits(); - length=(ulong) (file_buffer.pos-record_pos)-pack_ref_length; - save_integer(record_pos,pack_ref_length,length); - if (length < (ulong) min_record_length) - min_record_length=(uint) length; - if (length > (ulong) max_record_length) - { - max_record_length=(uint) length; - if (max_record_length >= max_allowed_length) - { - fprintf(stderr, - "Error: Found record with packed-length: %d, max is: %lu\n", - max_record_length, (ulong) max_allowed_length); - error=1; - break; - } - } - if (write_loop && ++record_count % WRITE_COUNT == 0) - { - printf("%lu\r",(ulong) record_count); VOID(fflush(stdout)); - } - } - else if (my_errno != HA_ERR_RECORD_DELETED) - break; - } - if (error < 0) - { - error=0; - if (my_errno != HA_ERR_END_OF_FILE) - { - fprintf(stderr,"%s: Got error %d reading records\n",my_progname,my_errno); - error= 1; - } - } - - my_afree((gptr) record); - mrg->ref_length=pack_ref_length; - mrg->min_pack_length=max_record_length ? min_record_length : 0; - mrg->max_pack_length=max_record_length; - if (verbose && max_record_length && - max_record_length < max_allowed_length/256) - printf("Record-length is %d bytes, could have been %d bytes\nYou can change this by using -p=%d next time you pack this file\n", - pack_ref_length, - max_record_length/256+1, - max_record_length/256+1); - DBUG_RETURN(error || error_on_write || flush_buffer((uint) ~0)); -} - - -static char *make_new_name(char *new_name, char *old_name) -{ - return fn_format(new_name,old_name,"",DATA_TMP_EXT,2+4); -} - -static char *make_old_name(char *new_name, char *old_name) -{ - return fn_format(new_name,old_name,"",OLD_EXT,2+4); -} - - /* rutines for bit writing buffer */ - -static void init_file_buffer(File file, pbool read_buffer) -{ - file_buffer.file=file; - file_buffer.buffer=my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE),MYF(MY_WME)); - file_buffer.end=file_buffer.buffer+ALIGN_SIZE(RECORD_CACHE_SIZE)-4; - file_buffer.pos_in_file=0; - error_on_write=0; - if (read_buffer) - { - - file_buffer.pos=file_buffer.end; - file_buffer.bits=0; - } - else - { - file_buffer.pos=file_buffer.buffer; - file_buffer.bits=BITS_SAVED; - } - file_buffer.bytes=0; -} - - -static int flush_buffer(uint neaded_length) -{ - uint length; - if ((uint) (file_buffer.end - file_buffer.pos) > neaded_length) - return 0; - length=(uint) (file_buffer.pos-file_buffer.buffer); - file_buffer.pos=file_buffer.buffer; - file_buffer.pos_in_file+=length; - if (test_only) - return 0; - return (error_on_write|=test(my_write(file_buffer.file,file_buffer.buffer, - length, - MYF(MY_WME | MY_NABP | - MY_WAIT_IF_FULL)))); -} - -static void end_file_buffer(void) -{ - my_free((gptr) file_buffer.buffer,MYF(0)); -} - - /* output `bits` low bits of `value' */ - -static void write_bits (register ulong value, register uint bits) -{ - if ((file_buffer.bits-=(int) bits) >= 0) - { - file_buffer.bytes|=value << file_buffer.bits; - } - else - { - reg3 uint byte_buff; - bits= (uint) -file_buffer.bits; - byte_buff=file_buffer.bytes | (uint) (value >> bits); -#if BITS_SAVED == 32 - *file_buffer.pos++= (byte) (byte_buff >> 24) ; - *file_buffer.pos++= (byte) (byte_buff >> 16) ; -#endif - *file_buffer.pos++= (byte) (byte_buff >> 8) ; - *file_buffer.pos++= (byte) byte_buff; - - value&=((ulong) 1L << bits)-1; -#if BITS_SAVED == 16 - if (bits >= sizeof(uint)) - { - bits-=8; - *file_buffer.pos++= (uchar) (value >> bits); - value&= ((ulong) 1L << bits)-1; - if (bits >= sizeof(uint)) - { - bits-=8; - *file_buffer.pos++= (uchar) (value >> bits); - value&= ((ulong) 1L << bits)-1; - } - } -#endif - if (file_buffer.pos >= file_buffer.end) - VOID(flush_buffer((uint) ~0)); - file_buffer.bits=(int) (BITS_SAVED - bits); - file_buffer.bytes=(uint) (value << (BITS_SAVED - bits)); - } - return; -} - - /* Flush bits in bit_buffer to buffer */ - -static void flush_bits (void) -{ - uint bits,byte_buff; - - bits=(file_buffer.bits) & ~7; - byte_buff = file_buffer.bytes >> bits; - bits=BITS_SAVED - bits; - while (bits > 0) - { - bits-=8; - *file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ; - } - file_buffer.bits=BITS_SAVED; - file_buffer.bytes=0; - return; -} - - /* Store long in 1,2,3,4 or 5 bytes */ - -static void save_integer(byte *pos, uint pack_length, my_off_t value) -{ - switch (pack_length) { - case 5: int5store(pos,(ulonglong) value); break; - default: int4store(pos,(ulong) value); break; - case 3: int3store(pos,(ulong) value); break; - case 2: int2store(pos,(uint) value); break; - case 1: pos[0]= (byte) (uchar) value; break; - } - return; -} - - -/**************************************************************************** -** functions to handle the joined files -****************************************************************************/ - -static void save_state(N_INFO *isam_file,MRG_INFO *mrg,my_off_t new_length, - ulong crc) -{ - ISAM_SHARE *share=isam_file->s; - uint options=uint2korr(share->state.header.options); - DBUG_ENTER("save_state"); - - options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA; - int2store(share->state.header.options,options); - - share->state.data_file_length=(ulong) new_length; - share->state.del=share->state.empty=0; - share->state.dellink= (ulong) NI_POS_ERROR; - share->state.splitt=(ulong) mrg->records; - share->state.version=(ulong) time((time_t*) 0); - share->state.keys=0; - share->state.key_file_length=share->base.keystart; - - isam_file->update|=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - isam_file->this_uniq=crc; /* Save crc here */ - share->changed=1; /* Force write of header */ - VOID(my_chsize(share->kfile, share->state.key_file_length, 0, - MYF(0))); - if (share->state.keys != share->base.keys) - isamchk_neaded=1; - DBUG_VOID_RETURN; -} - - -static int save_state_mrg(File file,MRG_INFO *mrg,my_off_t new_length, - ulong crc) -{ - N_STATE_INFO state; - N_INFO *isam_file=mrg->file[0]; - uint options; - DBUG_ENTER("save_state_mrg"); - - memcpy(&state,&isam_file->s->state,sizeof(state)); - options= (uint2korr(state.header.options) | HA_OPTION_COMPRESS_RECORD | - HA_OPTION_READ_ONLY_DATA); - int2store(state.header.options,options); - state.data_file_length=(ulong) new_length; - state.del=state.empty=0; - state.dellink= (ulong) NI_POS_ERROR; - state.records=state.splitt=(ulong) mrg->records; - state.version=(ulong) time((time_t*) 0); - state.keys=0; - state.key_file_length=isam_file->s->base.keystart; - state.uniq=crc; - if (state.keys != isam_file->s->base.keys) - isamchk_neaded=1; - DBUG_RETURN (my_pwrite(file,(char*) &state.header, - isam_file->s->state_length,0L, - MYF(MY_NABP | MY_WME)) != 0); -} - - -/* reset for mrg_rrnd */ - -static void mrg_reset(MRG_INFO *mrg) -{ - if (mrg->current) - { - nisam_extra(*mrg->current,HA_EXTRA_NO_CACHE); - mrg->current=0; - } -} - -static int mrg_rrnd(MRG_INFO *info,byte *buf) -{ - int error; - N_INFO *isam_info; - my_off_t filepos; - - if (!info->current) - { - isam_info= *(info->current=info->file); - info->end=info->current+info->count; - nisam_extra(isam_info,HA_EXTRA_RESET); - nisam_extra(isam_info,HA_EXTRA_CACHE); - filepos=isam_info->s->pack.header_length; - } - else - { - isam_info= *info->current; - filepos= isam_info->nextpos; - } - - for (;;) - { - isam_info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if ((error=(*isam_info->s->read_rnd)(isam_info,(byte*) buf, - (ulong) filepos, 1)) >= 0 || - my_errno != HA_ERR_END_OF_FILE) - return (error); - nisam_extra(isam_info,HA_EXTRA_NO_CACHE); - if (info->current+1 == info->end) - return(-1); - info->current++; - isam_info= *info->current; - filepos=isam_info->s->pack.header_length; - nisam_extra(isam_info,HA_EXTRA_RESET); - nisam_extra(isam_info,HA_EXTRA_CACHE); - } -} - - -static int mrg_close(MRG_INFO *mrg) -{ - uint i; - int error=0; - for (i=0 ; i < mrg->count ; i++) - error|=nisam_close(mrg->file[i]); - return error; -} diff --git a/isam/panic.c b/isam/panic.c deleted file mode 100644 index 7af979a5104..00000000000 --- a/isam/panic.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (C) 2000 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 */ - -#include "isamdef.h" - - /* if flag == HA_PANIC_CLOSE then all misam files are closed */ - /* if flag == HA_PANIC_WRITE then all misam files are unlocked and - all changed data in single user misam is written to file */ - /* if flag == HA_PANIC_READ then all misam files that was locked when - nisam_panic(HA_PANIC_WRITE) was done is locked. A ni_readinfo() is - done for all single user files to get changes in database */ - - -int nisam_panic(enum ha_panic_function flag) -{ - int error=0; - LIST *list_element,*next_open; - N_INFO *info; - DBUG_ENTER("nisam_panic"); - - pthread_mutex_lock(&THR_LOCK_isam); - for (list_element=nisam_open_list ; list_element ; list_element=next_open) - { - next_open=list_element->next; /* Save if close */ - info=(N_INFO*) list_element->data; - switch (flag) { - case HA_PANIC_CLOSE: - pthread_mutex_unlock(&THR_LOCK_isam); /* Not exactly right... */ - if (nisam_close(info)) - error=my_errno; - pthread_mutex_lock(&THR_LOCK_isam); - break; - case HA_PANIC_WRITE: /* Do this to free databases */ -#ifdef CANT_OPEN_FILES_TWICE - if (info->s->base.options & HA_OPTION_READ_ONLY_DATA) - break; -#endif - if (flush_key_blocks(dflt_key_cache,info->s->kfile,FLUSH_RELEASE)) - error=my_errno; - if (info->opt_flag & WRITE_CACHE_USED) - if (flush_io_cache(&info->rec_cache)) - error=my_errno; - if (info->opt_flag & READ_CACHE_USED) - { - if (flush_io_cache(&info->rec_cache)) - error=my_errno; - reinit_io_cache(&info->rec_cache,READ_CACHE,0, - (pbool) (info->lock_type != F_UNLCK),1); - } -#ifndef NO_LOCKING - if (info->lock_type != F_UNLCK && ! info->was_locked) - { - info->was_locked=info->lock_type; - if (nisam_lock_database(info,F_UNLCK)) - error=my_errno; - } -#else - { - int save_status=info->s->w_locks; /* Only w_locks! */ - info->s->w_locks=0; - if (_nisam_writeinfo(info, test(info->update & HA_STATE_CHANGED))) - error=my_errno; - info->s->w_locks=save_status; - info->update&= ~HA_STATE_CHANGED; /* Not changed */ - } -#endif /* NO_LOCKING */ -#ifdef CANT_OPEN_FILES_TWICE - if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0))) - error = my_errno; - if (info->dfile >= 0 && my_close(info->dfile,MYF(0))) - error = my_errno; - info->s->kfile=info->dfile= -1; /* Files aren't open anymore */ - break; -#endif - case HA_PANIC_READ: /* Restore to before WRITE */ -#ifdef CANT_OPEN_FILES_TWICE - { /* Open closed files */ - char name_buff[FN_REFLEN]; - if (info->s->kfile < 0) - if ((info->s->kfile= my_open(fn_format(name_buff,info->filename,"", - N_NAME_IEXT,4),info->mode, - MYF(MY_WME))) < 0) - error = my_errno; - if (info->dfile < 0) - { - if ((info->dfile= my_open(fn_format(name_buff,info->filename,"", - N_NAME_DEXT,4),info->mode, - MYF(MY_WME))) < 0) - error = my_errno; - info->rec_cache.file=info->dfile; - } - } -#endif -#ifndef NO_LOCKING - if (info->was_locked) - { - if (nisam_lock_database(info, info->was_locked)) - error=my_errno; - info->was_locked=0; - } -#else - { - int lock_type,w_locks; - lock_type=info->lock_type ; w_locks=info->s->w_locks; - info->lock_type=0; info->s->w_locks=0; - if (_nisam_readinfo(info,0,1)) /* Read changed data */ - error=my_errno; - info->lock_type=lock_type; info->s->w_locks=w_locks; - } - /* Don't use buffer when doing next */ - info->update|=HA_STATE_WRITTEN; -#endif /* NO_LOCKING */ - break; - } - } - if (flag == HA_PANIC_CLOSE) - VOID(nisam_log(0)); /* Close log if neaded */ - pthread_mutex_unlock(&THR_LOCK_isam); - if (!error) DBUG_RETURN(0); - my_errno=error; - DBUG_RETURN(-1); -} /* nisam_panic */ diff --git a/isam/range.c b/isam/range.c deleted file mode 100644 index 3b79b6d93a9..00000000000 --- a/isam/range.c +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* - Gives a approximated number of how many records there is between two keys. - Used when optimizing querries. - */ - -#include "isamdef.h" - -static ulong _nisam_record_pos(N_INFO *info,const byte *key,uint key_len, - enum ha_rkey_function search_flag); -static double _nisam_search_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *key, - uint key_len,uint nextflag,ulong pos); -static uint _nisam_keynr(N_INFO *info,N_KEYDEF *keyinfo,uchar *page, - uchar *keypos,uint *ret_max_key); - - - /* If start_key = 0 assume read from start */ - /* If end_key = 0 assume read to end */ - /* Returns NI_POS_ERROR on error */ - -ulong nisam_records_in_range(N_INFO *info, int inx, const byte *start_key, - uint start_key_len, - enum ha_rkey_function start_search_flag, - const byte *end_key, uint end_key_len, - enum ha_rkey_function end_search_flag) -{ - ulong start_pos,end_pos; - DBUG_ENTER("nisam_records_in_range"); - - if ((inx = _nisam_check_index(info,inx)) < 0) - DBUG_RETURN(NI_POS_ERROR); - -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_RDLCK,1)) - DBUG_RETURN(NI_POS_ERROR); -#endif - info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - start_pos= (start_key ? - _nisam_record_pos(info,start_key,start_key_len,start_search_flag) : - 0L); - end_pos= (end_key ? - _nisam_record_pos(info,end_key,end_key_len,end_search_flag) : - info->s->state.records+1L); - VOID(_nisam_writeinfo(info,0)); - if (start_pos == NI_POS_ERROR || end_pos == NI_POS_ERROR) - DBUG_RETURN(NI_POS_ERROR); - DBUG_PRINT("info",("records: %ld",end_pos-start_pos)); - DBUG_RETURN(end_pos < start_pos ? 0L : - (end_pos == start_pos ? 1L : end_pos-start_pos)); -} - - - /* Find relative position (in records) for key in index-tree */ - -static ulong _nisam_record_pos(N_INFO *info, const byte *key, uint key_len, - enum ha_rkey_function search_flag) -{ - uint inx=(uint) info->lastinx; - N_KEYDEF *keyinfo=info->s->keyinfo+inx; - uchar *key_buff; - double pos; - - DBUG_ENTER("_nisam_record_pos"); - DBUG_PRINT("enter",("search_flag: %d",search_flag)); - - if (key_len >= (keyinfo->base.keylength-info->s->rec_reflength) - && !(keyinfo->base.flag & HA_SPACE_PACK_USED)) - key_len=USE_HOLE_KEY; - key_buff=info->lastkey+info->s->base.max_key_length; - key_len=_nisam_pack_key(info,inx,key_buff,(uchar*) key,key_len); - DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg, - (uchar*) key_buff);); - pos=_nisam_search_pos(info,keyinfo,key_buff,key_len, - nisam_read_vec[search_flag] | SEARCH_SAVE_BUFF, - info->s->state.key_root[inx]); - if (pos >= 0.0) - { - DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->s->state.records))); - DBUG_RETURN((ulong) (pos*info->s->state.records+0.5)); - } - DBUG_RETURN(NI_POS_ERROR); -} - - - /* This is a modified version of _nisam_search */ - /* Returns offset for key in indextable (decimal 0.0 <= x <= 1.0) */ - -static double _nisam_search_pos(register N_INFO *info, register N_KEYDEF *keyinfo, - uchar *key, uint key_len, uint nextflag, - register ulong pos) -{ - int flag; - uint nod_flag,keynr,max_keynr; - uchar *keypos,*buff; - double offset; - DBUG_ENTER("_nisam_search_pos"); - - if (pos == NI_POS_ERROR) - DBUG_RETURN(0.5); - - if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,1))) - goto err; - flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag, - &keypos,info->lastkey); - nod_flag=test_if_nod(buff); - keynr=_nisam_keynr(info,keyinfo,buff,keypos,&max_keynr); - - if (flag) - { - /* - ** Didn't found match. keypos points at next (bigger) key - * Try to find a smaller, better matching key. - ** Matches keynr + [0-1] - */ - if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,nextflag, - _nisam_kpos(nod_flag,keypos))) < 0) - DBUG_RETURN(offset); - } - else - { - /* - ** Found match. Keypos points at the start of the found key - ** Matches keynr+1 - */ - offset=1.0; /* Matches keynr+1 */ - if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME) - || key_len) && nod_flag) - { - /* - ** There may be identical keys in the tree. Try to match on of those. - ** Matches keynr + [0-1] - */ - if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,SEARCH_FIND, - _nisam_kpos(nod_flag,keypos))) < 0) - DBUG_RETURN(offset); /* Read error */ - } - } - DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d", - keynr,offset,max_keynr,nod_flag,flag)); - DBUG_RETURN((keynr+offset)/(max_keynr+1)); -err: - DBUG_PRINT("exit",("Error: %d",my_errno)); - DBUG_RETURN (-1.0); -} - - - /* Get keynummer of current key and max number of keys in nod */ - -static uint _nisam_keynr(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key) -{ - uint nod_flag,keynr,max_key; - uchar t_buff[N_MAX_KEY_BUFF],*end; - - end= page+getint(page); - nod_flag=test_if_nod(page); - page+=2+nod_flag; - - if (!(keyinfo->base.flag & - (HA_PACK_KEY | HA_SPACE_PACK | HA_SPACE_PACK_USED))) - { - *ret_max_key= (uint) (end-page)/(keyinfo->base.keylength+nod_flag); - return (uint) (keypos-page)/(keyinfo->base.keylength+nod_flag); - } - - max_key=keynr=0; - while (page < end) - { - t_buff[0]=0; /* Don't move packed key */ - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff)); - max_key++; - if (page == keypos) - keynr=max_key; - } - *ret_max_key=max_key; - return(keynr); -} diff --git a/isam/rfirst.c b/isam/rfirst.c deleted file mode 100644 index cc1cbee92bf..00000000000 --- a/isam/rfirst.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* L{ser f|rsta posten som har samma isam-nyckel */ - -#include "isamdef.h" - - /* - L{ser f|rsta posten med samma isamnyckel som f|reg}ende l{sning. - Man kan ha gjort write, update eller delete p} f|reg}ende post. - OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses - posten i avseende p} f|reg}ende isam-nyckel-l{sning !! - */ - -int nisam_rfirst(N_INFO *info, byte *buf, int inx) -{ - DBUG_ENTER("nisam_rfirst"); - info->lastpos= NI_POS_ERROR; - info->update|= HA_STATE_PREV_FOUND; - DBUG_RETURN(nisam_rnext(info,buf,inx)); -} /* nisam_rfirst */ diff --git a/isam/rkey.c b/isam/rkey.c deleted file mode 100644 index bbe4576418b..00000000000 --- a/isam/rkey.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* L{ser p} basen av en isam_nyckel */ - -#include "isamdef.h" - - - /* Read a record using key */ - /* Ordinary search_flag is 0 ; Give error if no record with key */ - -int nisam_rkey(N_INFO *info, byte *buf, int inx, const byte *key, uint key_len, enum ha_rkey_function search_flag) -{ - uchar *key_buff; - ISAM_SHARE *share=info->s; - DBUG_ENTER("nisam_rkey"); - DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d", - info,inx,search_flag)); - - if ((inx = _nisam_check_index(info,inx)) < 0) - DBUG_RETURN(-1); - info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if (key_len >= (share->keyinfo[inx].base.keylength - share->rec_reflength) - && !(info->s->keyinfo[inx].base.flag & HA_SPACE_PACK_USED)) - key_len=USE_HOLE_KEY; - key_buff=info->lastkey+info->s->base.max_key_length; - key_len=_nisam_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len); - DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,share->keyinfo[inx].seg, - (uchar*) key);); - -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_RDLCK,1)) - goto err; -#endif - - VOID(_nisam_search(info,info->s->keyinfo+inx,key_buff,key_len, - nisam_read_vec[search_flag],info->s->state.key_root[inx])); - if ((*info->read_record)(info,info->lastpos,buf) >= 0) - { - info->update|= HA_STATE_AKTIV; /* Record is read */ - DBUG_RETURN(0); - } - - info->lastpos = NI_POS_ERROR; /* Didn't find key */ - VOID(_nisam_move_key(info->s->keyinfo+inx,info->lastkey,key_buff)); - if (search_flag == HA_READ_AFTER_KEY) - info->update|=HA_STATE_NEXT_FOUND; /* Previous gives last row */ -err: - DBUG_RETURN(-1); -} /* nisam_rkey */ diff --git a/isam/rlast.c b/isam/rlast.c deleted file mode 100644 index a91f1f1011b..00000000000 --- a/isam/rlast.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* L{ser sista posten som har samma isam-nyckel */ - -#include "isamdef.h" - - /* - L{ser sista posten med samma isamnyckel som f|reg}ende l{sning. - Man kan ha gjort write, update eller delete p} f|reg}ende post. - OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses - posten i avseende p} f|reg}ende isam-nyckel-l{sning !! - */ - -int nisam_rlast(N_INFO *info, byte *buf, int inx) -{ - DBUG_ENTER("nisam_rlast"); - info->lastpos= NI_POS_ERROR; - info->update|= HA_STATE_NEXT_FOUND; - DBUG_RETURN(nisam_rprev(info,buf,inx)); -} /* nisam_rlast */ diff --git a/isam/rnext.c b/isam/rnext.c deleted file mode 100644 index be26098c901..00000000000 --- a/isam/rnext.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* L{ser n{sta post med samma isam-nyckel */ - -#include "isamdef.h" - - /* - L{ser n{sta post med samma isamnyckel som f|reg}ende l{sning. - Man kan ha gjort write, update eller delete p} f|reg}ende post. - OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses - posten i avseende p} f|reg}ende isam-nyckel-l{sning !! - */ - -int nisam_rnext(N_INFO *info, byte *buf, int inx) -{ - int error,changed; - uint flag; - DBUG_ENTER("nisam_rnext"); - - if ((inx = _nisam_check_index(info,inx)) < 0) - DBUG_RETURN(-1); - flag=SEARCH_BIGGER; /* Read next */ - if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_PREV_FOUND) - flag=0; /* Read first */ - -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1); -#endif - changed=_nisam_test_if_changed(info); - if (!flag) - error=_nisam_search_first(info,info->s->keyinfo+inx, - info->s->state.key_root[inx]); - else if (!changed) - error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag, - info->s->state.key_root[inx]); - else - error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag, - info->s->state.key_root[inx]); - - /* Don't clear if database-changed */ - info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | - HA_STATE_BUFF_SAVED); - info->update|= HA_STATE_NEXT_FOUND; - - if (error && my_errno == HA_ERR_KEY_NOT_FOUND) - my_errno=HA_ERR_END_OF_FILE; - if ((*info->read_record)(info,info->lastpos,buf) >=0) - { - info->update|= HA_STATE_AKTIV; /* Record is read */ - DBUG_RETURN(0); - } - DBUG_RETURN(-1); -} /* nisam_rnext */ diff --git a/isam/rprev.c b/isam/rprev.c deleted file mode 100644 index 0997a04fbbe..00000000000 --- a/isam/rprev.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* L{ser f|reg}ende post med samma isam-nyckel */ - -#include "isamdef.h" - - /* - L{ser f|reg}ende post med samma isamnyckel som f|reg}ende l{sning. - Man kan ha gjort write, update eller delete p} f|reg}ende post. - OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses - posten i avseende p} f|reg}ende isam-nyckel-l{sning !! - */ - -int nisam_rprev(N_INFO *info, byte *buf, int inx) -{ - int error,changed; - register uint flag; - DBUG_ENTER("nisam_rprev"); - - if ((inx = _nisam_check_index(info,inx)) < 0) - DBUG_RETURN(-1); - flag=SEARCH_SMALLER; /* Read previous */ - if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_NEXT_FOUND) - flag=0; /* Read last */ - -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1); -#endif - changed=_nisam_test_if_changed(info); - if (!flag) - error=_nisam_search_last(info,info->s->keyinfo+inx,info->s->state.key_root[inx]); - else if (!changed) - error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag, - info->s->state.key_root[inx]); - else - error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag, - info->s->state.key_root[inx]); - - info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | - HA_STATE_BUFF_SAVED); - info->update|= HA_STATE_PREV_FOUND; - if (error && my_errno == HA_ERR_KEY_NOT_FOUND) - my_errno=HA_ERR_END_OF_FILE; - if ((*info->read_record)(info,info->lastpos,buf) >=0) - { - info->update|= HA_STATE_AKTIV; /* Record is read */ - DBUG_RETURN(0); - } - DBUG_RETURN(-1); -} /* nisam_rprev */ diff --git a/isam/rrnd.c b/isam/rrnd.c deleted file mode 100644 index 16b3ab1b859..00000000000 --- a/isam/rrnd.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Read a record with random-access. The position to the record must - get by N_INFO. The next record can be read with pos= -1 */ - - -#include "isamdef.h" - -/* - If filepos == NI_POS_ERROR, read next - Returns: - 0 = Ok. - 1 = Row was deleted - -1 = EOF (check errno to verify) -*/ - -int nisam_rrnd(N_INFO *info, byte *buf, register ulong filepos) -{ - int skipp_deleted_blocks; - DBUG_ENTER("nisam_rrnd"); - - skipp_deleted_blocks=0; - - if (filepos == NI_POS_ERROR) - { - skipp_deleted_blocks=1; - if (info->lastpos == NI_POS_ERROR) /* First read ? */ - filepos= info->s->pack.header_length; /* Read first record */ - else - filepos= info->nextpos; - } - - info->lastinx= -1; /* Can't forward or backward */ - /* Init all but update-flag */ - info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - - if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache)) - DBUG_RETURN(my_errno); - - DBUG_RETURN ((*info->s->read_rnd)(info,buf,filepos,skipp_deleted_blocks)); -} diff --git a/isam/rsame.c b/isam/rsame.c deleted file mode 100644 index 9a2a03da054..00000000000 --- a/isam/rsame.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* L{ser nuvarande record med direktl{sning */ -/* Klarar b}de poster l{sta med nyckel och rrnd. */ - -#include "isamdef.h" - - /* Funktionen ger som resultat: - 0 = Ok. - 1 = Posten borttagen - -1 = EOF (eller motsvarande: se errno) */ - - -int nisam_rsame(N_INFO *info, byte *record, int inx) - - - /* If inx >= 0 find record using key */ -{ - DBUG_ENTER("nisam_rsame"); - - if (inx >= (int) info->s->state.keys || inx < -1) - { - my_errno=HA_ERR_WRONG_INDEX; - DBUG_RETURN(-1); - } - if (info->lastpos == NI_POS_ERROR || info->update & HA_STATE_DELETED) - { - my_errno=HA_ERR_KEY_NOT_FOUND; /* No current record */ - DBUG_RETURN(-1); - } - info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - - /* L{s record fr}n datafilen */ - -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_RDLCK,1)) - DBUG_RETURN(-1); -#endif - - if (inx >= 0) - { - info->lastinx=inx; - VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos)); - VOID(_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,SEARCH_SAME, - info->s->state.key_root[inx])); - } - - if ((*info->read_record)(info,info->lastpos,record) == 0) - DBUG_RETURN(0); - if (my_errno == HA_ERR_RECORD_DELETED) - { - my_errno=HA_ERR_KEY_NOT_FOUND; - DBUG_RETURN(1); - } - DBUG_RETURN(-1); -} /* nisam_rsame */ diff --git a/isam/rsamepos.c b/isam/rsamepos.c deleted file mode 100644 index c64ac492d1a..00000000000 --- a/isam/rsamepos.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* read record through position and fix key-position */ -/* As nisam_rsame but supply a position */ - -#include "isamdef.h" - - - /* - ** If inx >= 0 update index pointer - ** Returns one of the following values: - ** 0 = Ok. - ** 1 = Record deleted - ** -1 = EOF (or something similar. More information in my_errno) - */ - -int nisam_rsame_with_pos(N_INFO *info, byte *record, int inx, ulong filepos) -{ - DBUG_ENTER("nisam_rsame_with_pos"); - - if (inx >= (int) info->s->state.keys || inx < -1) - { - my_errno=HA_ERR_WRONG_INDEX; - DBUG_RETURN(-1); - } - - info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if ((*info->s->read_rnd)(info,record,filepos,0)) - { - if (my_errno == HA_ERR_RECORD_DELETED) - { - my_errno=HA_ERR_KEY_NOT_FOUND; - DBUG_RETURN(1); - } - DBUG_RETURN(-1); - } - info->lastpos=filepos; - info->lastinx=inx; - if (inx >= 0) - { - VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos)); - info->update|=HA_STATE_KEY_CHANGED; /* Don't use indexposition */ - } - DBUG_RETURN(0); -} /* nisam_rsame_pos */ diff --git a/isam/sort.c b/isam/sort.c deleted file mode 100644 index d22b0e648a0..00000000000 --- a/isam/sort.c +++ /dev/null @@ -1,558 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* - Creates a index for a database by reading keys, sorting them and outputing - them in sorted order through SORT_INFO functions. -*/ - -#include "isamdef.h" -#if defined(MSDOS) || defined(__WIN__) -#include <fcntl.h> -#else -#include <stddef.h> -#endif -#include <queues.h> - - /* static variabels */ - -#define MERGEBUFF 15 -#define MERGEBUFF2 31 -#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD) -#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) - -typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */ - my_off_t file_pos; /* Position var bufferten finns */ - ulong count; /* Antal nycklar i bufferten */ - uchar *base,*key; /* Pekare inom sort_key - indexdel */ - uint mem_count; /* Antal nycklar kvar i minnet */ - uint max_keys; /* Max keys in buffert */ -} BUFFPEK; - -extern void print_error _VARARGS((const char *fmt,...)); - - /* functions defined in this file */ - -static ulong NEAR_F find_all_keys(SORT_PARAM *info,uint keys, - uchar * *sort_keys, - BUFFPEK *buffpek,int *maxbuffer, - FILE **tempfile, my_string tempname); -static int NEAR_F write_keys(SORT_PARAM *info,uchar * *sort_keys, - uint count, BUFFPEK *buffpek,FILE **tempfile, - my_string tempname); -static int NEAR_F write_index(SORT_PARAM *info,uchar * *sort_keys, - uint count); -static int NEAR_F merge_many_buff(SORT_PARAM *info,uint keys, - uchar * *sort_keys, - BUFFPEK *buffpek,int *maxbuffer, - FILE * *t_file, my_string tempname); -static uint NEAR_F read_to_buffer(FILE *fromfile,BUFFPEK *buffpek, - uint sort_length); -static int NEAR_F merge_buffers(SORT_PARAM *info,uint keys,FILE *from_file, - FILE *to_file, uchar * *sort_keys, - BUFFPEK *lastbuff,BUFFPEK *Fb, - BUFFPEK *Tb); -static int NEAR_F merge_index(SORT_PARAM *,uint,uchar **,BUFFPEK *, int, - FILE *); -static char **make_char_array(uint fields,uint length,myf my_flag); -static FILE *opentemp(my_string name); -static void closetemp(char *name,FILE *stream); - - - /* Creates a index of sorted keys */ - /* Returns 0 if everything went ok */ - -int _create_index_by_sort(info,no_messages,sortbuff_size) -SORT_PARAM *info; -pbool no_messages; -uint sortbuff_size; -{ - int error,maxbuffer,skr; - uint memavl,old_memavl,keys,sort_length; - BUFFPEK *buffpek; - char tempname[FN_REFLEN]; - ulong records; - uchar **sort_keys; - FILE *tempfile; - DBUG_ENTER("_create_index_by_sort"); - - tempfile=0; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1; - maxbuffer=1; - - memavl=max(sortbuff_size,MIN_SORT_MEMORY); - records= info->max_records; - sort_length= info->key_length; - LINT_INIT(keys); - - while (memavl >= MIN_SORT_MEMORY) - { - if ((records+1)*(sort_length+sizeof(char*)) < (ulong) memavl) - keys= records+1; - else - do - { - skr=maxbuffer; - if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer || - (keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/ - (sort_length+sizeof(char*))) <= 1) - { - print_error("Sortbuffer to small"); - goto err; - } - } - while ((maxbuffer= (int) (records/(keys-1)+1)) != skr); - - if ((sort_keys= (uchar **) make_char_array(keys,sort_length,MYF(0)))) - { - if ((buffpek = (BUFFPEK*) my_malloc((uint) (sizeof(BUFFPEK)* - (uint) maxbuffer), - MYF(0)))) - break; - else - my_free((gptr) sort_keys,MYF(0)); - } - old_memavl=memavl; - if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY) - memavl=MIN_SORT_MEMORY; - } - if (memavl < MIN_SORT_MEMORY) - { - print_error("Sortbuffer to small"); - goto err; - } - (*info->lock_in_memory)(); /* Everything is allocated */ - - if (!no_messages) - printf(" - Searching for keys, allocating buffer for %d keys\n",keys); - - if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile, - tempname)) - == (ulong) -1) - goto err; - if (maxbuffer == 0) - { - if (!no_messages) - printf(" - Dumping %lu keys\n",records); - if (write_index(info,sort_keys,(uint) records)) - goto err; - } - else - { - keys=(keys*(sort_length+sizeof(char*)))/sort_length; - if (maxbuffer >= MERGEBUFF2) - { - if (!no_messages) - printf(" - Merging %lu keys\n",records); - if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile, - tempname)) - goto err; - } - if (!no_messages) - puts(" - Last merge and dumping keys"); - if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile)) - goto err; - } - error =0; - -err: - if (sort_keys) - my_free((gptr) sort_keys,MYF(0)); - if (buffpek) - my_free((gptr) buffpek,MYF(0)); - if (tempfile) - closetemp(tempname,tempfile); - - DBUG_RETURN(error ? -1 : 0); -} /* _create_index_by_sort */ - - - /* Search after all keys and place them in a temp. file */ - -static ulong NEAR_F find_all_keys(info,keys,sort_keys,buffpek,maxbuffer, - tempfile,tempname) -SORT_PARAM *info; -uint keys; -uchar **sort_keys; -BUFFPEK *buffpek; -int *maxbuffer; -FILE **tempfile; -my_string tempname; -{ - int error; - uint index,indexpos; - DBUG_ENTER("find_all_keys"); - - index=indexpos=error=0; - - while (!(error=(*info->key_read)(sort_keys[index]))) - { - if ((uint) ++index == keys) - { - if (indexpos >= (uint) *maxbuffer || - write_keys(info,sort_keys,index-1,buffpek+indexpos,tempfile, - tempname)) - DBUG_RETURN(NI_POS_ERROR); - memcpy(sort_keys[0],sort_keys[index-1],(size_t) info->key_length); - index=1; indexpos++; - } - } - if (error > 0) - DBUG_RETURN(NI_POS_ERROR); /* Aborted by get_key */ - if (indexpos) - if (indexpos >= (uint) *maxbuffer || - write_keys(info,sort_keys,index,buffpek+indexpos,tempfile,tempname)) - DBUG_RETURN(NI_POS_ERROR); - *maxbuffer=(int) indexpos; - DBUG_RETURN(indexpos*(keys-1)+index); -} /* find_all_keys */ - - - /* Write all keys in memory to file for later merge */ - -static int NEAR_F write_keys(info,sort_keys,count,buffpek,tempfile,tempname) -SORT_PARAM *info; -reg1 uchar **sort_keys; -uint count; -BUFFPEK *buffpek; -reg2 FILE **tempfile; -my_string tempname; -{ - DBUG_ENTER("write_keys"); - - qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, - NullS); - if (! *tempfile && ! (*tempfile=opentemp(tempname))) - DBUG_RETURN(1); - buffpek->file_pos=my_ftell(*tempfile,MYF(0)); - buffpek->count=count; - while (count--) - if (my_fwrite(*tempfile,(byte*)*sort_keys++,info->key_length,MYF_RW)) - DBUG_RETURN(1); - DBUG_RETURN(0); -} /* write_keys */ - - - /* Write index */ - -static int NEAR_F write_index(info,sort_keys,count) -SORT_PARAM *info; -reg1 uchar **sort_keys; -reg2 uint count; -{ - DBUG_ENTER("write_index"); - - qsort2((gptr) sort_keys,(size_t) count,sizeof(byte*), - (qsort2_cmp) info->key_cmp, NullS); - while (count--) - if ((*info->key_write)(*sort_keys++)) - DBUG_RETURN(-1); - DBUG_RETURN(0); -} /* write_index */ - - - /* Merge buffers to make < MERGEBUFF2 buffers */ - -static int NEAR_F merge_many_buff(info,keys,sort_keys,buffpek,maxbuffer,t_file, - t_name) -SORT_PARAM *info; -uint keys; -uchar **sort_keys; -int *maxbuffer; -BUFFPEK *buffpek; -FILE **t_file; -my_string t_name; -{ - register int i; - FILE *from_file,*to_file,*temp; - FILE *t_file2; - char t_name2[FN_REFLEN]; - BUFFPEK *lastbuff; - DBUG_ENTER("merge_many_buff"); - - if (!(t_file2=opentemp(t_name2))) - DBUG_RETURN(1); - - from_file= *t_file ; to_file= t_file2; - while (*maxbuffer >= MERGEBUFF2) - { - lastbuff=buffpek; - for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) - { - if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, - buffpek+i,buffpek+i+MERGEBUFF-1)) - break; - } - if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, - buffpek+i,buffpek+ *maxbuffer)) - break; - *maxbuffer= (int) (lastbuff-buffpek)-1; - temp=from_file; from_file=to_file; to_file=temp; - VOID(my_fseek(to_file,0L,MY_SEEK_SET,MYF(0))); - } - if (to_file == *t_file) - { - closetemp(t_name,to_file); - *t_file=t_file2; - VOID(strmov(t_name,t_name2)); - } - else closetemp(t_name2,to_file); - - DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */ -} /* merge_many_buff */ - - - /* Read data to buffer */ - /* This returns (uint) -1 if something goes wrong */ - -static uint NEAR_F read_to_buffer(fromfile,buffpek,sort_length) -FILE *fromfile; -BUFFPEK *buffpek; -uint sort_length; -{ - register uint count; - uint length; - - if ((count=(uint) min((ulong) buffpek->max_keys,buffpek->count))) - { - VOID(my_fseek(fromfile,buffpek->file_pos,MY_SEEK_SET,MYF(0))); - if (my_fread(fromfile,(byte*) buffpek->base, - (length= sort_length*count),MYF_RW)) - return((uint) -1); - buffpek->key=buffpek->base; - buffpek->file_pos+= length; /* New filepos */ - buffpek->count-= count; - buffpek->mem_count= count; - } - return (count*sort_length); -} /* read_to_buffer */ - - - /* Merge buffers to one buffer */ - /* If to_file == 0 then use info->key_write */ - -static int NEAR_F merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff, - Fb,Tb) -SORT_PARAM *info; -uint keys; -FILE *from_file,*to_file; -uchar **sort_keys; -BUFFPEK *lastbuff,*Fb,*Tb; -{ - int error; - uint sort_length,maxcount; - ulong count; - my_off_t to_start_filepos; - uchar *strpos; - BUFFPEK *buffpek,**refpek; - QUEUE queue; - DBUG_ENTER("merge_buffers"); - - count=error=0; - maxcount=keys/((uint) (Tb-Fb) +1); - sort_length=info->key_length; - - LINT_INIT(to_start_filepos); - if (to_file) - to_start_filepos=my_ftell(to_file,MYF(0)); - strpos=(uchar*) sort_keys; - - if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, - (int (*)(void *, byte *,byte *)) info->key_cmp,0)) - DBUG_RETURN(1); - - for (buffpek= Fb ; buffpek <= Tb && error != -1 ; buffpek++) - { - count+= buffpek->count; - buffpek->base= strpos; - buffpek->max_keys=maxcount; - strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek, - sort_length)); - queue_insert(&queue,(void*) buffpek); - } - if (error == -1) - goto err; - - while (queue.elements > 1) - { - for (;;) - { - buffpek=(BUFFPEK*) queue_top(&queue); - if (to_file) - { - if (my_fwrite(to_file,(byte*) buffpek->key,(uint) sort_length, - MYF_RW | MY_WAIT_IF_FULL)) - { - error=1; goto err; - } - } - else - { - if ((*info->key_write)((void*) buffpek->key)) - { - error=1; goto err; - } - } - buffpek->key+=sort_length; - if (! --buffpek->mem_count) - { - if (!(error=(int) read_to_buffer(from_file,buffpek,sort_length))) - { - uchar *base=buffpek->base; - uint max_keys=buffpek->max_keys; - - VOID(queue_remove(&queue,0)); - - /* Put room used by buffer to use in other buffer */ - for (refpek= (BUFFPEK**) &queue_top(&queue); - refpek <= (BUFFPEK**) &queue_end(&queue); - refpek++) - { - buffpek= *refpek; - if (buffpek->base+buffpek->max_keys*sort_length == base) - { - buffpek->max_keys+=max_keys; - break; - } - else if (base+max_keys*sort_length == buffpek->base) - { - buffpek->base=base; - buffpek->max_keys+=max_keys; - break; - } - } - break; /* One buffer have been removed */ - } - } - queue_replaced(&queue); /* Top element has been replaced */ - } - } - buffpek=(BUFFPEK*) queue_top(&queue); - buffpek->base=(uchar *) sort_keys; - buffpek->max_keys=keys; - do - { - if (to_file) - { - if (my_fwrite(to_file,(byte*) buffpek->key, - (uint) (sort_length*buffpek->mem_count), - MYF_RW | MY_WAIT_IF_FULL)) - { - error=1; goto err; - } - } - else - { - register uchar *end; - strpos= buffpek->key; - for (end=strpos+buffpek->mem_count*sort_length; - strpos != end ; - strpos+=sort_length) - { - if ((*info->key_write)((void*) strpos)) - { - error=1; goto err; - } - } - } - } - while ((error=(int) read_to_buffer(from_file,buffpek,sort_length)) != -1 && - error != 0); - - lastbuff->count=count; - if (to_file) - lastbuff->file_pos=to_start_filepos; /* New block starts here */ -err: - delete_queue(&queue); - DBUG_RETURN(error); -} /* merge_buffers */ - - - /* Do a merge to output-file (save only positions) */ - -static int NEAR_F merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile) -SORT_PARAM *info; -uint keys; -uchar **sort_keys; -BUFFPEK *buffpek; -int maxbuffer; -FILE *tempfile; -{ - DBUG_ENTER("merge_index"); - if (merge_buffers(info,keys,tempfile,(FILE*) 0,sort_keys,buffpek,buffpek, - buffpek+maxbuffer)) - DBUG_RETURN(1); - DBUG_RETURN(0); -} /* merge_index */ - - - /* Make a pointer of arrays to keys */ - -static char **make_char_array(fields,length,my_flag) -register uint fields; -uint length; -myf my_flag; -{ - register char **pos; - char **old_pos,*char_pos; - DBUG_ENTER("make_char_array"); - - if ((old_pos= (char**) my_malloc( fields*(length+sizeof(char*)), my_flag))) - { - pos=old_pos; char_pos=((char*) (pos+fields)) -length; - while (fields--) - *(pos++) = (char_pos+= length); - } - - DBUG_RETURN(old_pos); -} /* make_char_array */ - - - /* |ppnar en tempor{rfil som kommer att raderas efter anv{nding */ - -static FILE *opentemp(name) -my_string name; -{ - FILE *stream; - reg1 my_string str_pos; - DBUG_ENTER("opentemp"); - - if (!(str_pos=my_tempnam(NullS,"ST",MYF(MY_WME)))) - DBUG_RETURN(0); - VOID(strmov(name,str_pos)); - (*free)(str_pos); /* Inte via vanliga malloc */ - - stream=my_fopen(name,(int) (O_RDWR | FILE_BINARY | O_CREAT | O_TEMPORARY), - MYF(MY_WME)); -#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES) - VOID(my_delete(name,MYF(MY_WME | ME_NOINPUT))); -#endif - DBUG_PRINT("exit",("stream: %lx",stream)); - DBUG_RETURN (stream); -} /* opentemp */ - - -static void closetemp(char *name __attribute__((unused)) ,FILE *stream) -{ - DBUG_ENTER("closetemp"); - - if (stream) - VOID(my_fclose(stream,MYF(MY_WME))); -#ifdef CANT_DELETE_OPEN_FILES - if (name) - VOID(my_delete(name,MYF(MY_WME))); -#endif - DBUG_VOID_RETURN; -} /* closetemp */ diff --git a/isam/static.c b/isam/static.c deleted file mode 100644 index 0a8dc809ad7..00000000000 --- a/isam/static.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* - Static variables for ISAM library. All definied here for easy making of - a shared library -*/ - -#ifndef _global_h -#include "isamdef.h" -#endif - -LIST *nisam_open_list=0; -uchar NEAR nisam_file_magic[]= -{ (uchar) 254, (uchar) 254,'\005', '\002', }; -uchar NEAR nisam_pack_file_magic[]= -{ (uchar) 254, (uchar) 254,'\006', '\001', }; -my_string nisam_log_filename= (char*) "isam.log"; -File nisam_log_file= -1; -uint nisam_quick_table_bits=9; -uint nisam_block_size=1024; /* Best by test */ -my_bool nisam_flush=0; - -/* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ */ -/* Position is , == , >= , <= , > , < */ - -uint NEAR nisam_read_vec[]= -{ - SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER, - SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER, - SEARCH_FIND, SEARCH_LAST,SEARCH_LAST | SEARCH_SMALLER -}; diff --git a/isam/test1.c b/isam/test1.c deleted file mode 100644 index b9f4d8242c3..00000000000 --- a/isam/test1.c +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2000 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 */ - -#include "isamdef.h" - -static void get_options(int argc, char *argv[]); - -static int rec_pointer_size=0,verbose=0,remove_ant=0,pack_keys=1,flags[50], - packed_field=FIELD_SKIP_PRESPACE; - -int main(int argc, char *argv[]) -{ - N_INFO *file; - int i,j,error,deleted,found; - char record[128],key[32],*filename,read_record[128]; - N_KEYDEF keyinfo[10]; - N_RECINFO recinfo[10]; - MY_INIT(argv[0]); - - filename= (char*) "test1"; - my_init(); - get_options(argc,argv); - keyinfo[0].seg[0].base.type=HA_KEYTYPE_NUM; - keyinfo[0].seg[0].base.flag=(uint8) (pack_keys ? - HA_PACK_KEY | HA_SPACE_PACK : 0); - keyinfo[0].seg[0].base.start=0; - keyinfo[0].seg[0].base.length=6; - keyinfo[0].seg[1].base.type=HA_KEYTYPE_END; - keyinfo[0].base.flag = (uint8) (pack_keys ? - HA_NOSAME | HA_PACK_KEY : HA_NOSAME); - - recinfo[0].base.type=packed_field; recinfo[0].base.length=6; - recinfo[1].base.type=FIELD_NORMAL; recinfo[1].base.length=24; - recinfo[2].base.type=FIELD_LAST; - - deleted=0; - bzero((byte*) flags,sizeof(flags)); - - printf("- Creating isam-file\n"); - if (nisam_create(filename,1,keyinfo,recinfo, - (ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/40 : - 0),10l,0,0,0L)) - goto err; - if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) - goto err; - printf("- Writing key:s\n"); - strmov(record," ..... key"); strappend(record,30,' '); - - my_errno=0; - for (i=49 ; i>=1 ; i-=2 ) - { - j=i%25 +1; - sprintf(key,"%6d",j); - bmove(record,key,6); - error=nisam_write(file,record); - flags[j]=1; - if (verbose || error) - printf("J= %2d nisam_write: %d errno: %d\n", j,error,my_errno); - } - if (nisam_close(file)) goto err; - printf("- Reopening file\n"); - if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err; - printf("- Removing keys\n"); - for (i=1 ; i<=10 ; i++) - { - if (i == remove_ant) { VOID(nisam_close(file)) ; exit(0) ; } - sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25))); - my_errno=0; - if ((error = nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))) - { - if (verbose || (flags[j] == 1 || - (error && my_errno != HA_ERR_KEY_NOT_FOUND))) - printf("key: %s nisam_rkey: %3d errno: %3d\n",key,error,my_errno); - } - else - { - error=nisam_delete(file,read_record); - if (verbose || error) - printf("key: %s nisam_delete: %3d errno: %3d\n",key,error,my_errno); - flags[j]=0; - if (! error) - deleted++; - } - } - printf("- Reading records with key\n"); - for (i=1 ; i<=25 ; i++) - { - sprintf(key,"%6d",i); - bmove(record,key,6); - my_errno=0; - error=nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT); - if (verbose || - (error == 0 && flags[i] != 1) || - (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND))) - { - printf("key: %s nisam_rkey: %3d errno: %3d record: %s\n", - key,error,my_errno,record+1); - } - } - - printf("- Reading records with position\n"); - for (i=1,found=0 ; i <= 30 ; i++) - { - my_errno=0; - if ((error=nisam_rrnd(file,read_record,i == 1 ? 0L : NI_POS_ERROR)) == -1) - { - if (found != 25-deleted) - printf("Found only %d of %d records\n",found,25-deleted); - break; - } - if (!error) - found++; - if (verbose || (error != 0 && error != 1)) - { - printf("pos: %2d nisam_rrnd: %3d errno: %3d record: %s\n", - i-1,error,my_errno,read_record+1); - } - } - if (nisam_close(file)) goto err; - my_end(MY_CHECK_ERROR); - - exit(0); -err: - printf("got error: %3d when using nisam-database\n",my_errno); - exit(1); - return 0; /* skip warning */ -} /* main */ - - - /* l{ser optioner */ - /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */ - -static void get_options(int argc, char *argv[]) -{ - char *pos; - - while (--argc >0 && *(pos = *(++argv)) == '-' ) { - switch(*++pos) { - case 'R': /* Length of record pointer */ - rec_pointer_size=atoi(++pos); - if (rec_pointer_size > 3) - rec_pointer_size=0; - break; - case 'P': - pack_keys=0; /* Don't use packed key */ - break; - case 'S': - packed_field=FIELD_NORMAL; /* static-size record*/ - break; - case 'v': /* verbose */ - verbose=1; - break; - case 'm': - remove_ant=atoi(++pos); - break; - case 'V': - printf("isamtest1 Ver 1.0 \n"); - exit(0); - case '#': - DEBUGGER_ON; - DBUG_PUSH (++pos); - break; - } - } - return; -} /* get options */ diff --git a/isam/test2.c b/isam/test2.c deleted file mode 100644 index 4b22f2d679c..00000000000 --- a/isam/test2.c +++ /dev/null @@ -1,841 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Test av isam-databas: stor test */ - -#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */ -#define USE_MY_FUNC -#endif -#ifdef DBUG_OFF -#undef DBUG_OFF -#endif -#ifndef SAFEMALLOC -#define SAFEMALLOC -#endif - -#include "isamdef.h" - -#define STANDAR_LENGTH 37 -#define NISAM_KEYS 6 -#if !defined(MSDOS) && !defined(labs) -#define labs(a) abs(a) -#endif - -static void get_options(int argc, char *argv[]); -static uint rnd(uint max_value); -static void fix_length(byte *record,uint length); -static void put_blob_in_record(char *blob_pos,char **blob_buffer); -static void copy_key(struct st_isam_info *info,uint inx, - uchar *record,uchar *key); - -static int verbose=0,testflag=0,pack_type=HA_SPACE_PACK, - first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0, - rec_pointer_size=0,pack_fields=1,use_log=0; -static uint keys=NISAM_KEYS,recant=1000; -static uint use_blob=0; -static uint16 key1[1000],key3[5000]; -static char record[300],record2[300],key[100],key2[100], - read_record[300],read_record2[300],read_record3[300]; - - - /* Test program */ - -int main(int argc, char *argv[]) -{ - uint i; - int j,n1,n2,n3,error,k; - uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos, - reclength,ant; - ulong lastpos,range_records,records; - N_INFO *file; - N_KEYDEF keyinfo[10]; - N_RECINFO recinfo[10]; - N_ISAMINFO info; - char *filename,*blob_buffer; - MY_INIT(argv[0]); - - filename= (char*) "test2.ISM"; - get_options(argc,argv); - if (! async_io) - my_disable_async_io=1; - - reclength=STANDAR_LENGTH+60+(use_blob ? 8 : 0); - blob_pos=STANDAR_LENGTH+60; - keyinfo[0].seg[0].base.start=0; - keyinfo[0].seg[0].base.length=6; - keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT; - keyinfo[0].seg[0].base.flag=(uint8) pack_type; - keyinfo[0].seg[1].base.type=0; - keyinfo[0].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0); - keyinfo[1].seg[0].base.start=7; - keyinfo[1].seg[0].base.length=6; - keyinfo[1].seg[0].base.type=HA_KEYTYPE_BINARY; - keyinfo[1].seg[0].base.flag=0; - keyinfo[1].seg[1].base.start=0; /* Tv}delad nyckel */ - keyinfo[1].seg[1].base.length=6; - keyinfo[1].seg[1].base.type=HA_KEYTYPE_NUM; - keyinfo[1].seg[1].base.flag=HA_REVERSE_SORT; - keyinfo[1].seg[2].base.type=0; - keyinfo[1].base.flag =0; - keyinfo[2].seg[0].base.start=12; - keyinfo[2].seg[0].base.length=8; - keyinfo[2].seg[0].base.type=HA_KEYTYPE_BINARY; - keyinfo[2].seg[0].base.flag=HA_REVERSE_SORT; - keyinfo[2].seg[1].base.type=0; - keyinfo[2].base.flag =HA_NOSAME; - keyinfo[3].seg[0].base.start=0; - keyinfo[3].seg[0].base.length=reclength-(use_blob ? 8 : 0); - keyinfo[3].seg[0].base.type=HA_KEYTYPE_TEXT; - keyinfo[3].seg[0].base.flag=(uint8) pack_type; - keyinfo[3].seg[1].base.type=0; - keyinfo[3].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0); - keyinfo[4].seg[0].base.start=0; - keyinfo[4].seg[0].base.length=5; - keyinfo[4].seg[0].base.type=HA_KEYTYPE_TEXT; - keyinfo[4].seg[0].base.flag=0; - keyinfo[4].seg[1].base.type=0; - keyinfo[4].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0); - keyinfo[5].seg[0].base.start=0; - keyinfo[5].seg[0].base.length=4; - keyinfo[5].seg[0].base.type=HA_KEYTYPE_TEXT; - keyinfo[5].seg[0].base.flag=(uint8) pack_type; - keyinfo[5].seg[1].base.type=0; - keyinfo[5].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0); - - recinfo[0].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0; - recinfo[0].base.length=7; - recinfo[1].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0; - recinfo[1].base.length=5; - recinfo[2].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0; - recinfo[2].base.length=9; - recinfo[3].base.type=FIELD_NORMAL; - recinfo[3].base.length=STANDAR_LENGTH-7-5-9-4; - recinfo[4].base.type=pack_fields ? FIELD_SKIP_ZERO : 0; - recinfo[4].base.length=4; - recinfo[5].base.type=pack_fields ? FIELD_SKIP_ENDSPACE : 0; - recinfo[5].base.length=60; - if (use_blob) - { - recinfo[6].base.type=FIELD_BLOB; - recinfo[6].base.length=4+sizeof(char*); /* 4 byte ptr, 4 byte length */ - recinfo[7].base.type= FIELD_LAST; - } - else - recinfo[6].base.type= FIELD_LAST; - - write_count=update=dupp_keys=opt_delete=0; - blob_buffer=0; - - for (i=999 ; i>0 ; i--) key1[i]=0; - for (i=4999 ; i>0 ; i--) key3[i]=0; - - printf("- Creating isam-file\n"); - /* DBUG_PUSH(""); */ - my_delete(filename,MYF(0)); /* Remove old locks under gdb */ - file= 0; - if (nisam_create(filename,keys,&keyinfo[first_key],&recinfo[0], - (ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/ - reclength : 0),100l,0,0,0L)) - goto err; - if (use_log) - nisam_log(1); - if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) - goto err; - printf("- Writing key:s\n"); - if (key_cacheing) - init_key_cache(dflt_key_cache,512,IO_SIZE*16,0,0); /* Use a small cache */ - if (locking) - nisam_lock_database(file,F_WRLCK); - if (write_cacheing) - nisam_extra(file,HA_EXTRA_WRITE_CACHE); - - for (i=0 ; i < recant ; i++) - { - n1=rnd(1000); n2=rnd(100); n3=rnd(5000); - sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count); - longstore(record+STANDAR_LENGTH-4,(long) i); - fix_length(record,(uint) STANDAR_LENGTH+rnd(60)); - put_blob_in_record(record+blob_pos,&blob_buffer); - DBUG_PRINT("test",("record: %d",i)); - - if (nisam_write(file,record)) - { - if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0) - { - printf("Error: %d in write at record: %d\n",my_errno,i); - goto err; - } - if (verbose) printf(" Double key: %d\n",n3); - } - else - { - if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3) - { - printf("Error: Didn't get error when writing second key: '%8d'\n",n3); - goto err; - } - write_count++; key1[n1]++; key3[n3]=1; - } - - /* Check if we can find key without flushing database */ - if (i == recant/2) - { - for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ; - if (!j) - for (j=999 ; j>0 && key1[j] == 0 ; j--) ; - sprintf(key,"%6d",j); - if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) - { - printf("Test in loop: Can't find key: \"%s\"\n",key); - goto err; - } - } - } - if (testflag==1) goto end; - - if (write_cacheing) - if (nisam_extra(file,HA_EXTRA_NO_CACHE)) - { - puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)"); - goto end; - } - - printf("- Delete\n"); - for (i=0 ; i<recant/10 ; i++) - { - for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ; - if (j != 0) - { - sprintf(key,"%6d",j); - if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) - { - printf("can't find key1: \"%s\"\n",key); - goto err; - } - if (nisam_delete(file,read_record)) - { - printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record); - goto err; - } - opt_delete++; - key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--; - key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0; - } - } - if (testflag==2) goto end; - - printf("- Update\n"); - for (i=0 ; i<recant/10 ; i++) - { - n1=rnd(1000); n2=rnd(100); n3=rnd(5000); - sprintf(record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update); - longstore(record2+STANDAR_LENGTH-4,(long) i); - fix_length(record2,(uint) STANDAR_LENGTH+rnd(60)); - - for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ; - if (j != 0) - { - sprintf(key,"%6d",j); - if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) - { - printf("can't find key1: \"%s\"\n",key); - goto err; - } - if (use_blob) - { - if (i & 1) - put_blob_in_record(record+blob_pos,&blob_buffer); - else - bmove(record+blob_pos,read_record+blob_pos,8); - } - if (nisam_update(file,read_record,record2)) - { - if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0) - { - printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n", - my_errno,read_record,record2); - goto err; - } - if (verbose) - printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2); - } - else - { - key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--; - key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0; - key1[n1]++; key3[n3]=1; - update++; - } - } - } - if (testflag==3) goto end; - - printf("- Same key: first - next -> last - prev -> first\n"); - DBUG_PRINT("progpos",("first - next -> last - prev -> first")); - for (i=999, dupp_keys=j=0 ; i>0 ; i--) - { - if (key1[i] >dupp_keys) { dupp_keys=key1[i]; j=i; } - } - sprintf(key,"%6d",j); - if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys); - if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err; - if (nisam_rsame(file,read_record2,-1)) goto err; - if (memcmp(read_record,read_record2,reclength) != 0) - { - printf("nisam_rsame didn't find same record\n"); - goto end; - } - nisam_info(file,&info,0); - if (nisam_rfirst(file,read_record2,0) || - nisam_rsame_with_pos(file,read_record2,0,info.recpos) || - memcmp(read_record,read_record2,reclength) != 0) - { - printf("nisam_rsame_with_pos didn't find same record\n"); - goto end; - } - { - int skr=nisam_rnext(file,read_record2,0); - if ((skr && my_errno != HA_ERR_END_OF_FILE) || - nisam_rprev(file,read_record2,-1) || - memcmp(read_record,read_record2,reclength) != 0) - { - printf("nisam_rsame_with_pos lost position\n"); - goto end; - } - } - ant=1; - start=keyinfo[0].seg[0].base.start; length=keyinfo[0].seg[0].base.length; - while (nisam_rnext(file,read_record2,0) == 0 && - memcmp(read_record2+start,key,length) == 0) ant++; - if (ant != dupp_keys) - { - printf("next: I can only find: %d keys of %d\n",ant,dupp_keys); - goto end; - } - ant=0; - while (nisam_rprev(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; - if (ant != dupp_keys) - { - printf("prev: I can only find: %d records of %d\n",ant,dupp_keys); - goto end; - } - - printf("- All keys: first - next -> last - prev -> first\n"); - DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first")); - ant=1; - if (nisam_rfirst(file,read_record,0)) - { - printf("Can't find first record\n"); - goto end; - } - while (nisam_rnext(file,read_record3,0) == 0 && ant < write_count+10) - ant++; - if (ant != write_count - opt_delete) - { - printf("next: I found: %d records of %d\n",ant,write_count - opt_delete); - goto end; - } - if (nisam_rlast(file,read_record2,0) || - bcmp(read_record2,read_record3,reclength)) - { - printf("Can't find last record\n"); - DBUG_DUMP("record2",(byte*) read_record2,reclength); - DBUG_DUMP("record3",(byte*) read_record3,reclength); - goto end; - } - ant=1; - while (nisam_rprev(file,read_record3,0) == 0 && ant < write_count+10) - ant++; - if (ant != write_count - opt_delete) - { - printf("prev: I found: %d records of %d\n",ant,write_count); - goto end; - } - if (bcmp(read_record,read_record3,reclength)) - { - printf("Can't find first record\n"); - goto end; - } - - printf("- Test if: Read first - next - prev - prev - next == first\n"); - DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first")); - if (nisam_rfirst(file,read_record,0) || - nisam_rnext(file,read_record3,0) || - nisam_rprev(file,read_record3,0) || - nisam_rprev(file,read_record3,0) == 0 || - nisam_rnext(file,read_record3,0)) - goto err; - if (bcmp(read_record,read_record3,reclength) != 0) - printf("Can't find first record\n"); - - printf("- Test if: Read last - prev - next - next - prev == last\n"); - DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last")); - if (nisam_rlast(file,read_record2,0) || - nisam_rprev(file,read_record3,0) || - nisam_rnext(file,read_record3,0) || - nisam_rnext(file,read_record3,0) == 0 || - nisam_rprev(file,read_record3,0)) - goto err; - if (bcmp(read_record2,read_record3,reclength)) - printf("Can't find last record\n"); - - puts("- Test read key-part"); - strmov(key2,key); - for(i=strlen(key2) ; i-- > 1 ;) - { - key2[i]=0; - if (nisam_rkey(file,read_record,0,key2,(uint) i,HA_READ_KEY_EXACT)) goto err; - if (bcmp(read_record+start,key,(uint) i)) - { - puts("Didn't find right record"); - goto end; - } - } - if (dupp_keys > 2) - { - printf("- Read key (first) - next - delete - next -> last\n"); - DBUG_PRINT("progpos",("first - next - delete - next -> last")); - if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err; - if (nisam_rnext(file,read_record3,0)) goto err; - if (nisam_delete(file,read_record3)) goto err; - opt_delete++; - ant=1; - while (nisam_rnext(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; - if (ant != dupp_keys-1) - { - printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1); - goto end; - } - } - if (dupp_keys>4) - { - printf("- Read last of key - prev - delete - prev -> first\n"); - DBUG_PRINT("progpos",("last - prev - delete - prev -> first")); - if (nisam_rprev(file,read_record3,0)) goto err; - if (nisam_rprev(file,read_record3,0)) goto err; - if (nisam_delete(file,read_record3)) goto err; - opt_delete++; - ant=1; - while (nisam_rprev(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; - if (ant != dupp_keys-2) - { - printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2); - goto end; - } - } - if (dupp_keys > 6) - { - printf("- Read first - delete - next -> last\n"); - DBUG_PRINT("progpos",("first - delete - next -> last")); - if (nisam_rkey(file,read_record3,0,key,0,HA_READ_KEY_EXACT)) goto err; - if (nisam_delete(file,read_record3)) goto err; - opt_delete++; - ant=1; - if (nisam_rnext(file,read_record,0)) - goto err; /* Skall finnas poster */ - while (nisam_rnext(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; - if (ant != dupp_keys-3) - { - printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3); - goto end; - } - - printf("- Read last - delete - prev -> first\n"); - DBUG_PRINT("progpos",("last - delete - prev -> first")); - if (nisam_rprev(file,read_record3,0)) goto err; - if (nisam_delete(file,read_record3)) goto err; - opt_delete++; - ant=0; - while (nisam_rprev(file,read_record3,0) == 0 && - bcmp(read_record3+start,key,length) == 0) ant++; - if (ant != dupp_keys-4) - { - printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4); - goto end; - } - } - - puts("- Test if: Read rrnd - same"); - DBUG_PRINT("progpos",("Read rrnd - same")); - for (i=0 ; i < write_count ; i++) - { - if (nisam_rrnd(file,read_record,i == 0 ? 0L : NI_POS_ERROR) == 0) - break; - } - if (i == write_count) - goto err; - - bmove(read_record2,read_record,reclength); - for (i=2 ; i-- > 0 ;) - { - if (nisam_rsame(file,read_record2,(int) i)) goto err; - if (bcmp(read_record,read_record2,reclength) != 0) - { - printf("is_rsame didn't find same record\n"); - goto end; - } - } - puts("- Test nisam_records_in_range"); - nisam_info(file,&info,HA_STATUS_VARIABLE); - for (i=0 ; i < info.keys ; i++) - { - if (nisam_rfirst(file,read_record,(int) i) || - nisam_rlast(file,read_record2,(int) i)) - goto err; - copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key); - copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2); - range_records=nisam_records_in_range(file,(int) i,key,0,HA_READ_KEY_EXACT, - key2,0,HA_READ_AFTER_KEY); - if (range_records < info.records*8/10 || - range_records > info.records*12/10) - { - printf("ni_records_range returned %lu; Should be about %lu\n", - range_records,info.records); - goto end; - } - if (verbose) - { - printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n", - range_records,info.records, - labs((long) range_records - (long) info.records)*100.0/ - info.records); - - } - } - for (i=0 ; i < 5 ; i++) - { - for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ; - for (k=rnd(1000) ; k>0 && key1[k] == 0 ; k--) ; - if (j != 0 && k != 0) - { - if (j > k) - swap_variables(int, j, k); - sprintf(key,"%6d",j); - sprintf(key2,"%6d",k); - range_records=nisam_records_in_range(file,0,key,0,HA_READ_AFTER_KEY, - key2,0,HA_READ_BEFORE_KEY); - records=0; - for (j++ ; j < k ; j++) - records+=key1[j]; - if ((long) range_records < (long) records*7/10-2 || - (long) range_records > (long) records*13/10+2) - { - printf("ni_records_range returned %ld; Should be about %ld\n", - range_records,records); - goto end; - } - if (verbose && records) - { - printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n", - range_records,records, - labs((long) range_records-(long) records)*100.0/records); - - } - } - } - - printf("- nisam_info\n"); - nisam_info(file,&info,0); - if (info.records != write_count-opt_delete || info.deleted > opt_delete + update - || info.keys != keys) - { - puts("Wrong info from nisam_info"); - printf("Got: records: %ld opt_delete: %ld i_keys: %d\n", - info.records,info.deleted,info.keys); - } - if (verbose) - { - char buff[80]; - get_date(buff,3,info.create_time); - printf("info: Created %s\n",buff); - get_date(buff,3,info.isamchk_time); - printf("info: checked %s\n",buff); - get_date(buff,3,info.update_time); - printf("info: Modified %s\n",buff); - } - - nisam_panic(HA_PANIC_WRITE); - nisam_panic(HA_PANIC_READ); - if (nisam_is_changed(file)) - puts("Warning: nisam_is_changed reported that datafile was changed"); - - printf("- nisam_extra(CACHE) + nisam_rrnd.... + nisam_extra(NO_CACHE)\n"); - if (nisam_extra(file,HA_EXTRA_RESET) || nisam_extra(file,HA_EXTRA_CACHE)) - { - if (locking || (!use_blob && !pack_fields)) - { - puts("got error from nisam_extra(HA_EXTRA_CACHE)"); - goto end; - } - } - ant=0; - while ((error=nisam_rrnd(file,record,NI_POS_ERROR)) >= 0 && - ant < write_count + 10) - ant+= error ? 0 : 1; - if (ant != write_count-opt_delete) - { - printf("rrnd with cache: I can only find: %d records of %d\n", - ant,write_count-opt_delete); - goto end; - } - if (nisam_extra(file,HA_EXTRA_NO_CACHE)) - { - puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)"); - goto end; - } - - if (testflag == 4) goto end; - - printf("- Removing keys\n"); - lastpos = NI_POS_ERROR; - /* DBUG_POP(); */ - nisam_extra(file,HA_EXTRA_RESET); - while ((error=nisam_rrnd(file,read_record,NI_POS_ERROR)) >=0) - { - nisam_info(file,&info,1); - if (lastpos >= info.recpos && lastpos != NI_POS_ERROR) - { - printf("nisam_rrnd didn't advance filepointer; old: %ld, new: %ld\n", - lastpos,info.recpos); - goto err; - } - lastpos=info.recpos; - if (error == 0) - { - if (nisam_rsame(file,read_record,-1)) - { - printf("can't find record %lx\n",info.recpos); - goto err; - } - if (use_blob) - { - ulong blob_length,pos; - uchar *ptr; - longget(blob_length,read_record+blob_pos+4); - ptr=(uchar*) blob_length; - longget(blob_length,read_record+blob_pos); - for (pos=0 ; pos < blob_length ; pos++) - { - if (ptr[pos] != (uchar) (blob_length+pos)) - { - printf("found blob with wrong info at %ld\n",lastpos); - use_blob=0; - break; - } - } - } - if (nisam_delete(file,read_record)) - { - printf("can't delete record: %s\n",read_record); - goto err; - } - opt_delete++; - } - } - if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED) - printf("error: %d from nisam_rrnd\n",my_errno); - if (write_count != opt_delete) - { - printf("Deleted only %d of %d records\n",write_count,opt_delete); - goto err; - } -end: - if (nisam_close(file)) - goto err; - nisam_panic(HA_PANIC_CLOSE); /* Should close log */ - printf("\nFollowing test have been made:\n"); - printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete); - if (rec_pointer_size) - printf("Record pointer size: %d\n",rec_pointer_size); - if (key_cacheing) - puts("Key cacheing used"); - if (write_cacheing) - puts("Write cacheing used"); - if (async_io && locking) - puts("Asyncron io with locking used"); - else if (locking) - puts("Locking used"); - if (use_blob) - puts("blobs used"); - end_key_cache(dflt_key_cache,1); - if (blob_buffer) - my_free(blob_buffer,MYF(0)); - my_end(MY_CHECK_ERROR | MY_GIVE_INFO); - return(0); -err: - printf("got error: %d when using NISAM-database\n",my_errno); - if (file) - VOID(nisam_close(file)); - return(1); -} /* main */ - - - /* l{ser optioner */ - /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */ - -static void get_options( int argc, char *argv[]) -{ - char *pos,*progname; - DEBUGGER_OFF; - - progname= argv[0]; - - while (--argc >0 && *(pos = *(++argv)) == '-' ) { - switch(*++pos) { - case 'b': - if (*++pos) - nisam_block_size= MY_ALIGN(atoi(pos),512); - set_if_bigger(nisam_block_size,8192); /* Max block size */ - set_if_smaller(nisam_block_size,1024); - break; - case 'B': - use_blob=1; - break; - case 'K': /* Use key cacheing */ - key_cacheing=1; - break; - case 'W': /* Use write cacheing */ - write_cacheing=1; - if (*++pos) - my_default_record_cache_size=atoi(pos); - break; - case 'i': - if (*++pos) - srand(atoi(pos)); - break; - case 'l': - use_log=1; - break; - case 'L': - locking=1; - break; - case 'A': /* use asyncron io */ - async_io=1; - if (*++pos) - my_default_record_cache_size=atoi(pos); - break; - case 'v': /* verbose */ - verbose=1; - break; - case 'm': /* records */ - recant=atoi(++pos); - break; - case 'f': - if ((first_key=atoi(++pos)) <0 || first_key >= NISAM_KEYS) - first_key=0; - break; - case 'k': - if ((keys=(uint) atoi(++pos)) < 1 || - keys > (uint) (NISAM_KEYS-first_key)) - keys=NISAM_KEYS-first_key; - break; - case 'P': - pack_type=0; /* Don't use DIFF_LENGTH */ - break; - case 'R': /* Length of record pointer */ - rec_pointer_size=atoi(++pos); - if (rec_pointer_size > 3) - rec_pointer_size=0; - break; - case 'S': - pack_fields=0; /* Static-length-records */ - break; - case 't': - testflag=atoi(++pos); /* testmod */ - break; - case '?': - case 'I': - case 'V': - printf("%s Ver 1.4 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); - puts("TCX Datakonsult AB, by Monty, for your professional use\n"); - printf("Usage: %s [-?ABIKLPRSVWltv] [-b#] [-k#] [-f#] [-m#] [-t#]\n",progname); - exit(0); - case '#': - DEBUGGER_ON; - DBUG_PUSH (++pos); - break; - default: - printf("Illegal option: '%c'\n",*pos); - break; - } - } - return; -} /* get options */ - - /* Ge ett randomv{rde inom ett intervall 0 <=x <= n */ - -static uint rnd( uint max_value) -{ - return (uint) ((rand() & 32767)/32767.0*max_value); -} /* rnd */ - - - /* G|r en record av skiftande length */ - -static void fix_length( byte *rec, uint length) -{ - bmove(rec+STANDAR_LENGTH, - "0123456789012345678901234567890123456789012345678901234567890", - length-STANDAR_LENGTH); - strfill(rec+length,STANDAR_LENGTH+60-length,' '); -} /* fix_length */ - - - /* Put maybe a blob in record */ - -static void put_blob_in_record(char *blob_pos, char **blob_buffer) -{ - ulong i,length; - if (use_blob) - { - if (rnd(10) == 0) - { - if (! *blob_buffer && - !(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME)))) - { - use_blob=0; - return; - } - length=rnd(use_blob); - for (i=0 ; i < length ; i++) - (*blob_buffer)[i]=(char) (length+i); - longstore(blob_pos,length); - bmove(blob_pos+4,(char*) blob_buffer,sizeof(char*)); - } - else - { - longstore(blob_pos,0); - } - } - return; -} - - -static void copy_key( N_INFO *info, uint inx, uchar *rec, uchar *key_buff) -{ - N_KEYSEG *keyseg; - - for (keyseg=info->s->keyinfo[inx].seg ; keyseg->base.type ; keyseg++) - { - memcpy(key_buff,rec+keyseg->base.start,(size_t) keyseg->base.length); - key_buff+=keyseg->base.length; - } - return; -} diff --git a/isam/test3.c b/isam/test3.c deleted file mode 100644 index 9195fcbf1b6..00000000000 --- a/isam/test3.c +++ /dev/null @@ -1,494 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Test av locking */ - -#ifndef __NETWARE__ - -#include "nisam.h" -#include <sys/types.h> -#include <keycache.h> -#ifdef HAVE_SYS_WAIT_H -# include <sys/wait.h> -#endif -#ifndef WEXITSTATUS -# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) -#endif -#ifndef WIFEXITED -# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) -#endif - - -#if defined(HAVE_LRAND48) -#define rnd(X) (lrand48() % X) -#define rnd_init(X) srand48(X) -#else -#define rnd(X) (random() % X) -#define rnd_init(X) srandom(X) -#endif - - -const char *filename= "test3.ISM"; -uint tests=10,forks=10,key_cacheing=0,use_log=0; - -static void get_options(int argc, char *argv[]); -void start_test(int id); -int test_read(N_INFO *,int),test_write(N_INFO *,int,int), - test_update(N_INFO *,int,int),test_rrnd(N_INFO *,int); - -struct record { - char id[8]; - uint32 nr; - char text[10]; -} record; - - -int main(int argc,char **argv) -{ - int status,wait_ret; - uint i; - N_KEYDEF keyinfo[10]; - N_RECINFO recinfo[10]; - MY_INIT(argv[0]); - - get_options(argc,argv); - - keyinfo[0].seg[0].base.start=0; - keyinfo[0].seg[0].base.length=8; - keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT; - keyinfo[0].seg[0].base.flag=HA_SPACE_PACK; - keyinfo[0].seg[1].base.type=0; - keyinfo[0].base.flag = (uint8) HA_PACK_KEY; - keyinfo[1].seg[0].base.start=8; - keyinfo[1].seg[0].base.length=sizeof(uint32); - keyinfo[1].seg[0].base.type=HA_KEYTYPE_LONG_INT; - keyinfo[1].seg[0].base.flag=0; - keyinfo[1].seg[1].base.type=0; - keyinfo[1].base.flag =HA_NOSAME; - - recinfo[0].base.type=0; - recinfo[0].base.length=sizeof(record.id); - recinfo[1].base.type=0; - recinfo[1].base.length=sizeof(record.nr); - recinfo[2].base.type=0; - recinfo[2].base.length=sizeof(record.text); - recinfo[3].base.type=FIELD_LAST; - - puts("- Creating isam-file"); - my_delete(filename,MYF(0)); /* Remove old locks under gdb */ - if (nisam_create(filename,2,&keyinfo[0],&recinfo[0],10000,0,0,0,0L)) - exit(1); - - rnd_init(0); - printf("- Starting %d processes\n",forks); fflush(stdout); - for (i=0 ; i < forks; i++) - { - if (!fork()) - { - start_test(i+1); - sleep(1); - return 0; - } - VOID(rnd(1)); - } - - for (i=0 ; i < forks ; i++) - while ((wait_ret=wait(&status)) && wait_ret == -1); - return 0; -} - - -static void get_options(argc,argv) -int argc; -char *argv[]; -{ - char *pos,*progname; - DEBUGGER_OFF; - - progname= argv[0]; - - while (--argc >0 && *(pos = *(++argv)) == '-' ) { - switch(*++pos) { - case 'l': - use_log=1; - break; - case 'f': - forks=atoi(++pos); - break; - case 't': - tests=atoi(++pos); - break; - case 'K': /* Use key cacheing */ - key_cacheing=1; - break; - case 'A': /* All flags */ - use_log=key_cacheing=1; - break; - case '?': - case 'I': - case 'V': - printf("%s Ver 1.0 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); - puts("TCX Datakonsult AB, by Monty, for your professional use\n"); - puts("Test av locking with threads\n"); - printf("Usage: %s [-?lKA] [-f#] [-t#]\n",progname); - exit(0); - case '#': - DEBUGGER_ON; - DBUG_PUSH (++pos); - break; - default: - printf("Illegal option: '%c'\n",*pos); - break; - } - } - return; -} - - -void start_test(int id) -{ - uint i; - int error,lock_type; - N_ISAMINFO isam_info; - N_INFO *file,*file1,*file2,*lock; - - if (use_log) - nisam_log(1); - if (!(file1=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)) || - !(file2=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED))) - { - fprintf(stderr,"Can't open isam-file: %s\n",filename); - exit(1); - } - if (key_cacheing && rnd(2) == 0) - init_key_cache(dflt_key_cache,512,65536L,0,0); - printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout); - - for (error=i=0 ; i < tests && !error; i++) - { - file= (rnd(2) == 1) ? file1 : file2; - lock=0 ; lock_type=0; - if (rnd(10) == 0) - { - if (nisam_lock_database(lock=(rnd(2) ? file1 : file2), - lock_type=(rnd(2) == 0 ? F_RDLCK : F_WRLCK))) - { - fprintf(stderr,"%2d: start: Can't lock table %d\n",id,my_errno); - error=1; - break; - } - } - switch (rnd(4)) { - case 0: error=test_read(file,id); break; - case 1: error=test_rrnd(file,id); break; - case 2: error=test_write(file,id,lock_type); break; - case 3: error=test_update(file,id,lock_type); break; - } - if (lock) - nisam_lock_database(lock,F_UNLCK); - } - if (!error) - { - nisam_info(file1,&isam_info,0); - printf("%2d: End of test. Records: %ld Deleted: %ld\n", - id,isam_info.records,isam_info.deleted); - fflush(stdout); - } - - nisam_close(file1); - nisam_close(file2); - if (use_log) - nisam_log(0); - if (error) - { - printf("%2d: Aborted\n",id); fflush(stdout); - exit(1); - } -} - - -int test_read(N_INFO *file,int id) -{ - uint i,lock,found,next,prev; - ulong find; - - lock=0; - if (rnd(2) == 0) - { - lock=1; - if (nisam_lock_database(file,F_RDLCK)) - { - fprintf(stderr,"%2d: Can't lock table %d\n",id,my_errno); - return 1; - } - } - - found=next=prev=0; - for (i=0 ; i < 100 ; i++) - { - find=rnd(100000); - if (!nisam_rkey(file,record.id,1,(byte*) &find, - sizeof(find),HA_READ_KEY_EXACT)) - found++; - else - { - if (my_errno != HA_ERR_KEY_NOT_FOUND) - { - fprintf(stderr,"%2d: Got error %d from read in read\n",id,my_errno); - return 1; - } - else if (!nisam_rnext(file,record.id,1)) - next++; - else - { - if (my_errno != HA_ERR_END_OF_FILE) - { - fprintf(stderr,"%2d: Got error %d from rnext in read\n",id,my_errno); - return 1; - } - else if (!nisam_rprev(file,record.id,1)) - prev++; - else - { - if (my_errno != HA_ERR_END_OF_FILE) - { - fprintf(stderr,"%2d: Got error %d from rnext in read\n", - id,my_errno); - return 1; - } - } - } - } - } - if (lock) - { - if (nisam_lock_database(file,F_UNLCK)) - { - fprintf(stderr,"%2d: Can't unlock table\n",id); - return 1; - } - } - printf("%2d: read: found: %5d next: %5d prev: %5d\n", - id,found,next,prev); - fflush(stdout); - return 0; -} - - -int test_rrnd(N_INFO *file,int id) -{ - uint count,lock; - - lock=0; - if (rnd(2) == 0) - { - lock=1; - if (nisam_lock_database(file,F_RDLCK)) - { - fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno); - nisam_close(file); - return 1; - } - if (rnd(2) == 0) - nisam_extra(file,HA_EXTRA_CACHE); - } - - count=0; - if (nisam_rrnd(file,record.id,0L)) - { - if (my_errno == HA_ERR_END_OF_FILE) - goto end; - fprintf(stderr,"%2d: Can't read first record (%d)\n",id,my_errno); - return 1; - } - for (count=1 ; !nisam_rrnd(file,record.id,NI_POS_ERROR) ;count++) ; - if (my_errno != HA_ERR_END_OF_FILE) - { - fprintf(stderr,"%2d: Got error %d from rrnd\n",id,my_errno); - return 1; - } - -end: - if (lock) - { - nisam_extra(file,HA_EXTRA_NO_CACHE); - if (nisam_lock_database(file,F_UNLCK)) - { - fprintf(stderr,"%2d: Can't unlock table\n",id); - exit(0); - } - } - printf("%2d: rrnd: %5d\n",id,count); fflush(stdout); - return 0; -} - - -int test_write(N_INFO *file,int id,int lock_type) -{ - uint i,tries,count,lock; - - lock=0; - if (rnd(2) == 0 || lock_type == F_RDLCK) - { - lock=1; - if (nisam_lock_database(file,F_WRLCK)) - { - if (lock_type == F_RDLCK && my_errno == EDEADLK) - { - printf("%2d: write: deadlock\n",id); fflush(stdout); - return 0; - } - fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno); - nisam_close(file); - return 1; - } - if (rnd(2) == 0) - nisam_extra(file,HA_EXTRA_WRITE_CACHE); - } - - sprintf(record.id,"%7d",(int) getpid()); - strmov(record.text,"Testing..."); - - tries=(uint) rnd(100)+10; - for (i=count=0 ; i < tries ; i++) - { - record.nr=rnd(80000)+20000; - if (!nisam_write(file,record.id)) - count++; - else - { - if (my_errno != HA_ERR_FOUND_DUPP_KEY) - { - fprintf(stderr,"%2d: Got error %d (errno %d) from write\n",id,my_errno, - errno); - return 1; - } - } - } - if (lock) - { - nisam_extra(file,HA_EXTRA_NO_CACHE); - if (nisam_lock_database(file,F_UNLCK)) - { - fprintf(stderr,"%2d: Can't unlock table\n",id); - exit(0); - } - } - printf("%2d: write: %5d\n",id,count); fflush(stdout); - return 0; -} - - -int test_update(N_INFO *file,int id,int lock_type) -{ - uint i,lock,found,next,prev,update; - ulong find; - struct record new_record; - - lock=0; - if (rnd(2) == 0 || lock_type == F_RDLCK) - { - lock=1; - if (nisam_lock_database(file,F_WRLCK)) - { - if (lock_type == F_RDLCK && my_errno == EDEADLK) - { - printf("%2d: write: deadlock\n",id); fflush(stdout); - return 0; - } - fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno); - return 1; - } - } - bzero((char*) &new_record,sizeof(new_record)); - strmov(new_record.text,"Updated"); - - found=next=prev=update=0; - for (i=0 ; i < 100 ; i++) - { - find=rnd(100000); - if (!nisam_rkey(file,record.id,1,(byte*) &find, - sizeof(find),HA_READ_KEY_EXACT)) - found++; - else - { - if (my_errno != HA_ERR_KEY_NOT_FOUND) - { - fprintf(stderr,"%2d: Got error %d from read in update\n",id,my_errno); - return 1; - } - else if (!nisam_rnext(file,record.id,1)) - next++; - else - { - if (my_errno != HA_ERR_END_OF_FILE) - { - fprintf(stderr,"%2d: Got error %d from rnext in update\n", - id,my_errno); - return 1; - } - else if (!nisam_rprev(file,record.id,1)) - prev++; - else - { - if (my_errno != HA_ERR_END_OF_FILE) - { - fprintf(stderr,"%2d: Got error %d from rnext in update\n", - id,my_errno); - return 1; - } - continue; - } - } - } - memcpy_fixed(new_record.id,record.id,sizeof(record.id)); - new_record.nr=rnd(20000)+40000; - if (!nisam_update(file,record.id,new_record.id)) - update++; - else - { - if (my_errno != HA_ERR_RECORD_CHANGED && - my_errno != HA_ERR_RECORD_DELETED && - my_errno != HA_ERR_FOUND_DUPP_KEY) - { - fprintf(stderr,"%2d: Got error %d from update\n",id,my_errno); - return 1; - } - } - } - if (lock) - { - if (nisam_lock_database(file,F_UNLCK)) - { - fprintf(stderr,"Can't unlock table,id, error%d\n",my_errno); - return 1; - } - } - printf("%2d: update: %5d\n",id,update); fflush(stdout); - return 0; -} - -#else /* __NETWARE__ */ - -#include <stdio.h> - -main() -{ - fprintf(stderr,"this test has not been ported to NetWare\n"); - return 0; -} - -#endif /* __NETWARE__ */ diff --git a/isam/test_all b/isam/test_all deleted file mode 100755 index 5de37e44585..00000000000 --- a/isam/test_all +++ /dev/null @@ -1,30 +0,0 @@ -echo "test2 -L -K -W -P" -test2 -L -K -W -P -echo "test2 -L -K -W -P -A" -test2 -L -K -W -P -A -echo "test2 -L -K -W -P -S -R1 -m500" -test2 -L -K -W -P -S -R1 -m500 -echo "test2 -L -K -R1 -m2000 ; Should give error 135" -test2 -L -K -R1 -m2000 -echo "test2 -L -K -P -S -R3 -m50 -b1000000" -test2 -L -K -P -S -R3 -m50 -b1000000 -echo "test2 -L -B" -test2 -L -B -echo "test2 -L -K -W -P -m50 -l" -test2 -L -K -W -P -m50 -l -isamlog -echo "test2 -L -K -W -P -m50 -l -b100" -test2 -L -K -W -P -m50 -l -b100 -isamlog -echo "time test2" -time test2 -echo "time test2 -K" -time test2 -K -echo "time test2 -L" -time test2 -L -echo "time test2 -L -K" -time test2 -L -K -echo "time test2 -L -K -W" -time test2 -L -K -W -echo "time test2 -L -K -W -S" -time test2 -L -K -W -S diff --git a/isam/test_all.res b/isam/test_all.res deleted file mode 100644 index 5de37e44585..00000000000 --- a/isam/test_all.res +++ /dev/null @@ -1,30 +0,0 @@ -echo "test2 -L -K -W -P" -test2 -L -K -W -P -echo "test2 -L -K -W -P -A" -test2 -L -K -W -P -A -echo "test2 -L -K -W -P -S -R1 -m500" -test2 -L -K -W -P -S -R1 -m500 -echo "test2 -L -K -R1 -m2000 ; Should give error 135" -test2 -L -K -R1 -m2000 -echo "test2 -L -K -P -S -R3 -m50 -b1000000" -test2 -L -K -P -S -R3 -m50 -b1000000 -echo "test2 -L -B" -test2 -L -B -echo "test2 -L -K -W -P -m50 -l" -test2 -L -K -W -P -m50 -l -isamlog -echo "test2 -L -K -W -P -m50 -l -b100" -test2 -L -K -W -P -m50 -l -b100 -isamlog -echo "time test2" -time test2 -echo "time test2 -K" -time test2 -K -echo "time test2 -L" -time test2 -L -echo "time test2 -L -K" -time test2 -L -K -echo "time test2 -L -K -W" -time test2 -L -K -W -echo "time test2 -L -K -W -S" -time test2 -L -K -W -S diff --git a/isam/update.c b/isam/update.c deleted file mode 100644 index b3b676f967d..00000000000 --- a/isam/update.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Uppdaterare nuvarande record i en pisam-databas */ - -#include "isamdef.h" -#ifdef __WIN__ -#include <errno.h> -#endif - - /* Updaterar senaste l{sta record i databasen */ - -int nisam_update(register N_INFO *info, const byte *oldrec, const byte *newrec) -{ - int flag,key_changed,save_errno; - reg3 ulong pos; - uint i,length; - uchar old_key[N_MAX_KEY_BUFF],*new_key; - DBUG_ENTER("nisam_update"); - - LINT_INIT(save_errno); - if (!(info->update & HA_STATE_AKTIV)) - { - my_errno=HA_ERR_KEY_NOT_FOUND; - DBUG_RETURN(-1); - } - if (info->s->base.options & HA_OPTION_READ_ONLY_DATA) - { - my_errno=EACCES; - DBUG_RETURN(-1); - } - pos=info->lastpos; -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1); -#endif - if ((*info->s->compare_record)(info,oldrec)) - { - save_errno=my_errno; - goto err_end; /* Record has changed */ - } - if (info->s->state.key_file_length >= - info->s->base.max_key_file_length - - info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys) - { - save_errno=HA_ERR_INDEX_FILE_FULL; - goto err_end; - } - - /* Flyttar de element i isamfilen som m}ste flyttas */ - - new_key=info->lastkey+info->s->base.max_key_length; - key_changed=HA_STATE_KEY_CHANGED; /* We changed current database */ - /* Remove key that didn't change */ - for (i=0 ; i < info->s->state.keys ; i++) - { - length=_nisam_make_key(info,i,new_key,newrec,pos); - if (length != _nisam_make_key(info,i,old_key,oldrec,pos) || - memcmp((byte*) old_key,(byte*) new_key,length)) - { - if ((int) i == info->lastinx) - key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */ - if (_nisam_ck_delete(info,i,old_key)) goto err; - if (_nisam_ck_write(info,i,new_key)) goto err; - } - } - - if ((*info->s->update_record)(info,pos,newrec)) - goto err; - - info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | - key_changed); - nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,0); - VOID(_nisam_writeinfo(info,test(key_changed))); - allow_break(); /* Allow SIGHUP & SIGINT */ - DBUG_RETURN(0); - -err: - DBUG_PRINT("error",("key: %d errno: %d",i,my_errno)); - save_errno=my_errno; - if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) - { - info->errkey= (int) i; - flag=0; - do - { - length=_nisam_make_key(info,i,new_key,newrec,pos); - if (length != _nisam_make_key(info,i,old_key,oldrec,pos) || - memcmp((byte*) old_key,(byte*) new_key,length)) - { - if ((flag++ && _nisam_ck_delete(info,i,new_key)) || - _nisam_ck_write(info,i,old_key)) - break; - } - } while (i-- != 0); - } - info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | - key_changed); - err_end: - nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,save_errno); - VOID(_nisam_writeinfo(info,1)); - allow_break(); /* Allow SIGHUP & SIGINT */ - my_errno=(save_errno == HA_ERR_KEY_NOT_FOUND) ? HA_ERR_CRASHED : save_errno; - DBUG_RETURN(-1); -} /* nisam_update */ diff --git a/isam/write.c b/isam/write.c deleted file mode 100644 index f2c0d8dbc45..00000000000 --- a/isam/write.c +++ /dev/null @@ -1,840 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* Skriver ett record till en isam-databas */ - -#include "isamdef.h" -#ifdef __WIN__ -#include <errno.h> -#endif - - /* Functions declared in this file */ - -static int w_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key, - ulong pos, uchar *father_buff, uchar *father_keypos, - ulong father_page); -static int _nisam_balance_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key, - uchar *curr_buff,uchar *father_buff, - uchar *father_keypos,ulong father_page); - - - /* Write new record to database */ - -int nisam_write(N_INFO *info, const byte *record) -{ - uint i; - ulong filepos; - uchar *buff; - DBUG_ENTER("nisam_write"); - DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile)); - - if (info->s->base.options & HA_OPTION_READ_ONLY_DATA) - { - my_errno=EACCES; - DBUG_RETURN(-1); - } -#ifndef NO_LOCKING - if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1); -#endif - dont_break(); /* Dont allow SIGHUP or SIGINT */ -#if !defined(NO_LOCKING) && defined(USE_RECORD_LOCK) - if (!info->locked && my_lock(info->dfile,F_WRLCK,0L,F_TO_EOF, - MYF(MY_SEEK_NOT_DONE) | info->lock_wait)) - goto err; -#endif - filepos= ((info->s->state.dellink != NI_POS_ERROR) ? - info->s->state.dellink : - info->s->state.data_file_length); - - if (info->s->base.reloc == 1L && info->s->base.records == 1L && - info->s->state.records == 1L) - { /* System file */ - my_errno=HA_ERR_RECORD_FILE_FULL; - goto err2; - } - if (info->s->state.key_file_length >= - info->s->base.max_key_file_length - - info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys) - { - my_errno=HA_ERR_INDEX_FILE_FULL; - goto err2; - } - - /* Write all keys to indextree */ - buff=info->lastkey+info->s->base.max_key_length; - for (i=0 ; i < info->s->state.keys ; i++) - { - VOID(_nisam_make_key(info,i,buff,record,filepos)); - if (_nisam_ck_write(info,i,buff)) goto err; - } - - if ((*info->s->write_record)(info,record)) - goto err; - - info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |HA_STATE_AKTIV | - HA_STATE_WRITTEN); - info->s->state.records++; - info->lastpos=filepos; - nisam_log_record(LOG_WRITE,info,record,filepos,0); - VOID(_nisam_writeinfo(info,1)); - allow_break(); /* Allow SIGHUP & SIGINT */ - DBUG_RETURN(0); - -err: - if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) - { - info->errkey= (int) i; - while ( i-- > 0) - { - VOID(_nisam_make_key(info,i,buff,record,filepos)); - if (_nisam_ck_delete(info,i,buff)) - break; - } - } - info->update=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_WRITTEN); -err2: - nisam_log_record(LOG_WRITE,info,record,filepos,my_errno); - VOID(_nisam_writeinfo(info,1)); - allow_break(); /* Allow SIGHUP & SIGINT */ - DBUG_RETURN(-1); -} /* nisam_write */ - - - /* Write one key to btree */ - -int _nisam_ck_write(register N_INFO *info, uint keynr, uchar *key) -{ - int error; - DBUG_ENTER("_nisam_ck_write"); - - if ((error=w_search(info,info->s->keyinfo+keynr,key, - info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0, - 0L)) > 0) - error=_nisam_enlarge_root(info,keynr,key); - DBUG_RETURN(error); -} /* _nisam_ck_write */ - - - /* Make a new root with key as only pointer */ - -int _nisam_enlarge_root(register N_INFO *info, uint keynr, uchar *key) -{ - uint t_length,nod_flag; - reg2 N_KEYDEF *keyinfo; - S_PARAM s_temp; - ISAM_SHARE *share=info->s; - DBUG_ENTER("_nisam_enlarge_root"); - - info->page_changed=1; - nod_flag= (share->state.key_root[keynr] != NI_POS_ERROR) ? - share->base.key_reflength : 0; - _nisam_kpointer(info,info->buff+2,share->state.key_root[keynr]); /* if nod */ - keyinfo=share->keyinfo+keynr; - t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,(uchar*) 0, - key,&s_temp); - putint(info->buff,t_length+2+nod_flag,nod_flag); - _nisam_store_key(keyinfo,info->buff+2+nod_flag,&s_temp); - if ((share->state.key_root[keynr]= _nisam_new(info,keyinfo)) == - NI_POS_ERROR || - _nisam_write_keypage(info,keyinfo,share->state.key_root[keynr],info->buff)) - DBUG_RETURN(-1); - DBUG_RETURN(0); -} /* _nisam_enlarge_root */ - - - /* S|ker reda p} vart nyckeln skall s{ttas och placerar den dit */ - /* Returnerar -1 om fel ; 0 om ok. 1 om nyckel propagerar upp}t */ - -static int w_search(register N_INFO *info, register N_KEYDEF *keyinfo, - uchar *key, ulong page, uchar *father_buff, - uchar *father_keypos, ulong father_page) -{ - int error,flag; - uint comp_flag,nod_flag; - uchar *temp_buff,*keypos; - uchar keybuff[N_MAX_KEY_BUFF]; - DBUG_ENTER("w_search"); - DBUG_PRINT("enter",("page: %ld",page)); - - if (page == NI_POS_ERROR) - DBUG_RETURN(1); /* No key, make new */ - - if (keyinfo->base.flag & HA_SORT_ALLOWS_SAME) - comp_flag=SEARCH_BIGGER; /* Put after same key */ - else if (keyinfo->base.flag & HA_NOSAME) - comp_flag=SEARCH_FIND; /* No dupplicates */ - else - comp_flag=SEARCH_SAME; /* Keys in rec-pos order */ - - if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+ - N_MAX_KEY_BUFF))) - DBUG_RETURN(-1); - if (!_nisam_fetch_keypage(info,keyinfo,page,temp_buff,0)) - goto err; - - flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,0,comp_flag,&keypos, - keybuff); - nod_flag=test_if_nod(temp_buff); - if (flag == 0) - { - my_errno=HA_ERR_FOUND_DUPP_KEY; - /* get position to record with dupplicated key */ - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff)); - info->dupp_key_pos=_nisam_dpos(info,test_if_nod(temp_buff),keypos); - my_afree((byte*) temp_buff); - DBUG_RETURN(-1); - } - if ((error=w_search(info,keyinfo,key,_nisam_kpos(nod_flag,keypos), - temp_buff,keypos,page)) >0) - { - error=_nisam_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff, - father_keypos,father_page); - if (_nisam_write_keypage(info,keyinfo,page,temp_buff)) - goto err; - } - my_afree((byte*) temp_buff); - DBUG_RETURN(error); -err: - my_afree((byte*) temp_buff); - DBUG_PRINT("exit",("Error: %d",my_errno)); - DBUG_RETURN (-1); -} /* w_search */ - - - /* Insert new key at right of key_pos */ - /* Returns 2 if key contains key to upper level */ - -int _nisam_insert(register N_INFO *info, register N_KEYDEF *keyinfo, - uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff, - uchar *father_buff, uchar *father_key_pos, ulong father_page) -{ - uint a_length,t_length,nod_flag; - uchar *endpos; - int key_offset; - S_PARAM s_temp; - DBUG_ENTER("_nisam_insert"); - DBUG_PRINT("enter",("key_pos: %lx",key_pos)); - DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key);); - - nod_flag=test_if_nod(anc_buff); - a_length=getint(anc_buff); - endpos= anc_buff+ a_length; - t_length=_nisam_get_pack_key_length(keyinfo,nod_flag, - (key_pos == endpos ? (uchar*) 0 : key_pos), - (key_pos == anc_buff+2+nod_flag ? - (uchar*) 0 : key_buff),key,&s_temp); -#ifndef DBUG_OFF - if (key_pos != anc_buff+2+nod_flag) - DBUG_DUMP("prev_key",(byte*) key_buff,_nisam_keylength(keyinfo,key_buff)); - if (keyinfo->base.flag & HA_PACK_KEY) - { - DBUG_PRINT("test",("t_length: %d ref_len: %d", - t_length,s_temp.ref_length)); - DBUG_PRINT("test",("n_ref_len: %d n_length: %d key: %lx", - s_temp.n_ref_length,s_temp.n_length,s_temp.key)); - } -#endif - key_offset = (uint)(endpos-key_pos); - if((int) t_length < 0) - key_offset += (int) t_length; - if (key_offset < 0) - { - DBUG_PRINT("error",("Found a bug: negative key_offset %d\n", key_offset)); - DBUG_RETURN(-1); - } - if ((int) t_length >= 0) /* t_length is almost always > 0 */ - bmove_upp((byte*) endpos+t_length,(byte*) endpos,(uint)key_offset ); - else - { - /* This may happen if a key was deleted and the next key could be - compressed better than before */ - DBUG_DUMP("anc_buff",(byte*) anc_buff,a_length); - - bmove(key_pos,key_pos - (int) t_length,(uint)key_offset); - } - _nisam_store_key(keyinfo,key_pos,&s_temp); - a_length+=t_length; - putint(anc_buff,a_length,nod_flag); - if (a_length <= keyinfo->base.block_length) - DBUG_RETURN(0); /* There is room on page */ - - /* Page is full */ - - if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)) && - father_buff) - DBUG_RETURN(_nisam_balance_page(info,keyinfo,key,anc_buff,father_buff, - father_key_pos,father_page)); - DBUG_RETURN(_nisam_splitt_page(info,keyinfo,key,anc_buff,key_buff)); -} /* _nisam_insert */ - - - /* splitt a full page in two and assign emerging item to key */ - -int _nisam_splitt_page(register N_INFO *info, register N_KEYDEF *keyinfo, - uchar *key, uchar *buff, uchar *key_buff) -{ - uint length,a_length,key_ref_length,t_length,nod_flag; - uchar *key_pos,*pos; - ulong new_pos; - S_PARAM s_temp; - DBUG_ENTER("ni_splitt_page"); - DBUG_DUMP("buff",(byte*) buff,getint(buff)); - - nod_flag=test_if_nod(buff); - key_ref_length=2+nod_flag; - key_pos=_nisam_find_half_pos(info,keyinfo,buff,key_buff); - length=(uint) (key_pos-buff); - a_length=getint(buff); - putint(buff,length,nod_flag); - info->page_changed=1; - - /* Correct new page pointer */ - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff)); - if (nod_flag) - { - DBUG_PRINT("test",("Splitting nod")); - pos=key_pos-nod_flag; - memcpy((byte*) info->buff+2,(byte*) pos,(size_t) nod_flag); - } - - /* Move midle item to key and pointer to new page */ - if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR) - DBUG_RETURN(-1); - _nisam_kpointer(info,_nisam_move_key(keyinfo,key,key_buff),new_pos); - - /* Store new page */ - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff)); - t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar *) 0, (uchar*) 0, - key_buff, &s_temp); - s_temp.n_length= *key_pos; /* Needed by ni_store_key */ - length=(uint) ((buff+a_length)-key_pos); - memcpy((byte*) info->buff+key_ref_length+t_length,(byte*) key_pos, - (size_t) length); - _nisam_store_key(keyinfo,info->buff+key_ref_length,&s_temp); - putint(info->buff,length+t_length+key_ref_length,nod_flag); - - if (_nisam_write_keypage(info,keyinfo,new_pos,info->buff)) - DBUG_RETURN(-1); - DBUG_DUMP("key",(byte*) key,_nisam_keylength(keyinfo,key)); - DBUG_RETURN(2); /* Middle key up */ -} /* _nisam_splitt_page */ - - - /* find out how much more room a key will take */ - -#ifdef QQ -uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo, uint nod_flag, uchar *key_pos, uchar *key_buff, uchar *key, S_PARAM *s_temp) - - /* If nod: Length of nod-pointer */ - /* Position to pos after key in buff */ - /* Last key before current key */ - /* Current key */ - /* How next key will be packed */ -{ - reg1 N_KEYSEG *keyseg; - int length; - uint key_length,ref_length,n_length,diff_flag,same_length; - uchar *start,*end,*key_end; - - s_temp->key=key; - if (!(keyinfo->base.flag & HA_PACK_KEY)) - return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag); - s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0; - s_temp->prev_length=0; - - same_length=0; keyseg=keyinfo->seg; - key_length=_nisam_keylength(keyinfo,key)+nod_flag; - - if (keyseg->base.flag & HA_SPACE_PACK) - { - diff_flag=1; - end=key_end= key+ *key+1; - if (key_buff) - { - if (*key == *key_buff && *key) - same_length=1; /* Don't use key-pack if length == 0 */ - else if (*key > *key_buff) - end=key+ *key_buff+1; - key_buff++; - } - key++; - } - else - { - diff_flag=0; - key_end=end= key+keyseg->base.length; - } - - start=key; - if (key_buff) - while (key < end && *key == *key_buff) - { - key++; key_buff++; - } - - s_temp->key=key; s_temp->key_length= (uint) (key_end-key); - - if (same_length && key == key_end) - { - s_temp->ref_length=128; - length=(int) key_length-(int)(key_end-start); /* Same as prev key */ - if (key_pos) - { - s_temp->n_length= *key_pos; - key_pos=0; /* Can't combine with next */ - } - } - else - { - if (start != key) - { /* Starts as prev key */ - s_temp->ref_length= (uint) (key-start)+128; - length=(int) (1+key_length-(uint) (key-start)); - } - else - length=(int) (key_length+ (1-diff_flag)); /* Not packed key */ - } - s_temp->totlength=(uint) length; - - DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d", - key_length,length,s_temp->key_length)); - - /* If something after that is not 0 length test if we can combine */ - - if (key_pos && (n_length= *key_pos)) - { - key_pos++; - ref_length=0; - if (n_length & 128) - { - if ((ref_length=n_length & 127)) - if (diff_flag) - n_length= *key_pos++; /* Length of key-part */ - else - n_length=keyseg->base.length - ref_length; - } - else - if (*start == *key_pos && diff_flag && start != key_end) - length++; /* One new pos for ref.len */ - - DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos)); - if (n_length != 128) - { /* Not same key after */ - key=start+ref_length; - while (n_length > 0 && key < key_end && *key == *key_pos) - { - key++; key_pos++; - ref_length++; - n_length--; - length--; /* We gained one char */ - } - - if (n_length == 0 && diff_flag) - { - n_length=128; /* Same as prev key */ - length--; /* We don't need key-length */ - } - else if (ref_length) - s_temp->n_ref_length=ref_length | 128; - } - s_temp->n_length=n_length; - } - return (uint) length; -} /* _nisam_get_pack_key_length */ - -#else - -uint -_nisam_get_pack_key_length(N_KEYDEF *keyinfo, - uint nod_flag, /* If nod: Length of nod-pointer */ - uchar *key_pos, /* Position to pos after key in buff */ - uchar *key_buff,/* Last key before current key */ - uchar *key, /* Current key */ - S_PARAM *s_temp/* How next key will be packed */ - ) -{ - reg1 N_KEYSEG *keyseg; - int length; - uint key_length,ref_length,n_length,diff_flag,same_length,org_key_length=0; - uchar *start,*end,*key_end; - - s_temp->key=key; - if (!(keyinfo->base.flag & HA_PACK_KEY)) - return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag); - s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0; - - same_length=0; keyseg=keyinfo->seg; - key_length=_nisam_keylength(keyinfo,key)+nod_flag; - s_temp->prev_key=key_buff; - - if (keyseg->base.flag & HA_SPACE_PACK) - { - diff_flag=1; - end=key_end= key+ *key+1; - if (key_buff) - { - org_key_length= (uint) *key_buff; - if (*key == *key_buff && *key) - same_length=1; /* Don't use key-pack if length == 0 */ - else if (*key > *key_buff) - end=key+ org_key_length+1; - key_buff++; - } - key++; - } - else - { - diff_flag=0; - key_end=end= key+(org_key_length=keyseg->base.length); - } - - start=key; - if (key_buff) - while (key < end && *key == *key_buff) - { - key++; key_buff++; - } - - s_temp->key=key; s_temp->key_length= (uint) (key_end-key); - - if (same_length && key == key_end) - { - s_temp->ref_length=128; - length=(int) key_length-(int)(key_end-start); /* Same as prev key */ - if (key_pos) - { /* Can't combine with next */ - s_temp->n_length= *key_pos; /* Needed by _nisam_store_key */ - key_pos=0; - } - } - else - { - if (start != key) - { /* Starts as prev key */ - s_temp->ref_length= (uint) (key-start)+128; - length=(int) (1+key_length-(uint) (key-start)); - } - else - length=(int) (key_length+ (1-diff_flag)); /* Not packed key */ - } - s_temp->totlength=(uint) length; - s_temp->prev_length=0; - DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d", - key_length,length,s_temp->key_length)); - - /* If something after that is not 0 length test if we can combine */ - - if (key_pos && (n_length= *key_pos++)) - { - if (n_length == 128) - { - /* - We put a different key between two identical keys - Extend next key to have same prefix as this key - */ - if (s_temp->ref_length) - { /* make next key longer */ - s_temp->part_of_prev_key= s_temp->ref_length; - s_temp->prev_length= org_key_length - (s_temp->ref_length-128); - s_temp->n_length= s_temp->prev_length; - s_temp->prev_key+= diff_flag + (s_temp->ref_length - 128); - length+= s_temp->prev_length+diff_flag; - } - else - { /* Can't use prev key */ - s_temp->part_of_prev_key=0; - s_temp->prev_length= org_key_length; - s_temp->n_length= org_key_length; - s_temp->prev_key+= diff_flag; /* To start of key */ - length+= org_key_length; - } - return (uint) length; - } - - if (n_length & 128) - { - ref_length=n_length & 127; - if (diff_flag) /* If SPACE_PACK */ - n_length= *key_pos++; /* Length of key-part */ - else - n_length=keyseg->base.length - ref_length; - - /* Test if new keys has fewer characters that match the previous key */ - if (!s_temp->ref_length) - { /* Can't use prev key */ - s_temp->part_of_prev_key= 0; - s_temp->prev_length= ref_length; - s_temp->n_length= n_length+ref_length; - s_temp->prev_key+= diff_flag; /* To start of key */ - return (uint) length+ref_length-diff_flag; - } - if (ref_length+128 > s_temp->ref_length) - { - /* We must copy characters from the original key to the next key */ - s_temp->part_of_prev_key= s_temp->ref_length; - s_temp->prev_length= ref_length+128 - s_temp->ref_length; - s_temp->n_length= n_length + s_temp->prev_length; - s_temp->prev_key+= diff_flag + s_temp->ref_length -128; - return (uint) length + s_temp->prev_length; - } - } - else - { - ref_length=0; - if (*start == *key_pos && diff_flag && start != key_end) - length++; /* One new pos for ref.len */ - } - DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos)); - - key=start+ref_length; - while (n_length > 0 && key < key_end && *key == *key_pos) - { - key++; key_pos++; - ref_length++; - n_length--; - length--; /* We gained one char */ - } - - if (n_length == 0 && diff_flag) - { - n_length=128; /* Same as prev key */ - length--; /* We don't need key-length */ - } - else if (ref_length) - s_temp->n_ref_length=ref_length | 128; - s_temp->n_length=n_length; - } - return (uint) length; -} /* _nisam_get_pack_key_length */ -#endif - - - /* store a key in page-buffert */ - -void _nisam_store_key(N_KEYDEF *keyinfo, register uchar *key_pos, - register S_PARAM *s_temp) -{ - uint length; - uchar *start; - - if (! (keyinfo->base.flag & HA_PACK_KEY)) - { - memcpy((byte*) key_pos,(byte*) s_temp->key,(size_t) s_temp->totlength); - return; - } - start=key_pos; - if ((*key_pos=(uchar) s_temp->ref_length)) - key_pos++; - if (s_temp->ref_length == 0 || - (s_temp->ref_length > 128 && - (keyinfo->seg[0].base.flag & HA_SPACE_PACK))) - *key_pos++= (uchar) s_temp->key_length; - bmove((byte*) key_pos,(byte*) s_temp->key, - (length=s_temp->totlength-(uint) (key_pos-start))); - key_pos+=length; - - if (s_temp->prev_length) - { - /* Extend next key because new key didn't have same prefix as prev key */ - if (s_temp->part_of_prev_key) - *key_pos++ = s_temp->part_of_prev_key; - if (keyinfo->seg[0].base.flag & HA_SPACE_PACK) - *key_pos++= s_temp->n_length; - memcpy(key_pos, s_temp->prev_key, s_temp->prev_length); - return; - } - - if ((*key_pos = (uchar) s_temp->n_ref_length)) - { - if (! (keyinfo->seg[0].base.flag & HA_SPACE_PACK)) - return; /* Don't save keylength */ - key_pos++; /* Store ref for next key */ - } - *key_pos = (uchar) s_temp->n_length; - return; -} /* _nisam_store_key */ - - - /* Calculate how to much to move to split a page in two */ - /* Returns pointer and key for get_key() to get mid key */ - /* There is at last 2 keys after pointer in buff */ - -uchar *_nisam_find_half_pos(N_INFO *info, N_KEYDEF *keyinfo, uchar *page, uchar *key) -{ - uint keys,length,key_ref_length,nod_flag; - uchar *end,*lastpos; - DBUG_ENTER("_nisam_find_half_pos"); - - nod_flag=test_if_nod(page); - key_ref_length=2+nod_flag; - length=getint(page)-key_ref_length; - page+=key_ref_length; - if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED))) - { - keys=(length/(keyinfo->base.keylength+nod_flag))/2; - DBUG_RETURN(page+keys*(keyinfo->base.keylength+nod_flag)); - } - - end=page+length/2-key_ref_length; /* This is aprox. half */ - *key='\0'; - do - { - lastpos=page; - VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,key)); - } while (page < end); - - DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end)); - DBUG_RETURN(lastpos); -} /* _nisam_find_half_pos */ - - - /* Balance page with not packed keys with page on right/left */ - /* returns 0 if balance was done */ - -static int _nisam_balance_page(register N_INFO *info, N_KEYDEF *keyinfo, - uchar *key, uchar *curr_buff, uchar *father_buff, - uchar *father_key_pos, ulong father_page) -{ - my_bool right; - uint k_length,father_length,father_keylength,nod_flag,curr_keylength, - right_length,left_length,new_right_length,new_left_length,extra_length, - length,keys; - uchar *pos,*buff,*extra_buff; - ulong next_page,new_pos; - byte tmp_part_key[N_MAX_KEY_BUFF]; - DBUG_ENTER("_nisam_balance_page"); - - k_length=keyinfo->base.keylength; - father_length=getint(father_buff); - father_keylength=k_length+info->s->base.key_reflength; - nod_flag=test_if_nod(curr_buff); - curr_keylength=k_length+nod_flag; - info->page_changed=1; - - if ((father_key_pos != father_buff+father_length && (info->s->rnd++ & 1)) || - father_key_pos == father_buff+2+info->s->base.key_reflength) - { - right=1; - next_page= _nisam_kpos(info->s->base.key_reflength, - father_key_pos+father_keylength); - buff=info->buff; - DBUG_PRINT("test",("use right page: %lu",next_page)); - } - else - { - right=0; - father_key_pos-=father_keylength; - next_page= _nisam_kpos(info->s->base.key_reflength,father_key_pos); - /* Fix that curr_buff is to left */ - buff=curr_buff; curr_buff=info->buff; - DBUG_PRINT("test",("use left page: %lu",next_page)); - } /* father_key_pos ptr to parting key */ - - if (!_nisam_fetch_keypage(info,keyinfo,next_page,info->buff,0)) - goto err; - DBUG_DUMP("next",(byte*) info->buff,getint(info->buff)); - - /* Test if there is room to share keys */ - - left_length=getint(curr_buff); - right_length=getint(buff); - keys=(left_length+right_length-4-nod_flag*2)/curr_keylength; - - if ((right ? right_length : left_length) + curr_keylength <= - keyinfo->base.block_length) - { /* Merge buffs */ - new_left_length=2+nod_flag+(keys/2)*curr_keylength; - new_right_length=2+nod_flag+((keys+1)/2)*curr_keylength; - putint(curr_buff,new_left_length,nod_flag); - putint(buff,new_right_length,nod_flag); - - if (left_length < new_left_length) - { /* Move keys buff -> leaf */ - pos=curr_buff+left_length; - memcpy((byte*) pos,(byte*) father_key_pos, (size_t) k_length); - memcpy((byte*) pos+k_length, (byte*) buff+2, - (size_t) (length=new_left_length - left_length - k_length)); - pos=buff+2+length; - memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length); - bmove((byte*) buff+2,(byte*) pos+k_length,new_right_length); - } - else - { /* Move keys -> buff */ - - bmove_upp((byte*) buff+new_right_length,(byte*) buff+right_length, - right_length-2); - length=new_right_length-right_length-k_length; - memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length); - pos=curr_buff+new_left_length; - memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length); - memcpy((byte*) buff+2,(byte*) pos+k_length,(size_t) length); - } - - if (_nisam_write_keypage(info,keyinfo,next_page,info->buff) || - _nisam_write_keypage(info,keyinfo,father_page,father_buff)) - goto err; - DBUG_RETURN(0); - } - - /* curr_buff[] and buff[] are full, lets splitt and make new nod */ - - extra_buff=info->buff+info->s->base.max_block; - new_left_length=new_right_length=2+nod_flag+(keys+1)/3*curr_keylength; - if (keys == 5) /* Too few keys to balance */ - new_left_length-=curr_keylength; - extra_length=nod_flag+left_length+right_length-new_left_length-new_right_length-curr_keylength; - DBUG_PRINT("info",("left_length: %d right_length: %d new_left_length: %d new_right_length: %d extra_length: %d", - left_length, right_length, - new_left_length, new_right_length, - extra_length)); - putint(curr_buff,new_left_length,nod_flag); - putint(buff,new_right_length,nod_flag); - putint(extra_buff,extra_length+2,nod_flag); - - /* move first largest keys to new page */ - pos=buff+right_length-extra_length; - memcpy((byte*) extra_buff+2,pos,(size_t) extra_length); - - /* Save new parting key */ - memcpy(tmp_part_key, pos-k_length,k_length); - - /* Make place for new keys */ - bmove_upp((byte*) buff+new_right_length,(byte*) pos-k_length, - right_length-extra_length-k_length-2); - /* Copy keys from left page */ - pos= curr_buff+new_left_length; - memcpy((byte*) buff+2,(byte*) pos+k_length, - (size_t) (length=left_length-new_left_length-k_length)); - /* Copy old parting key */ - memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length); - - /* Move new parting keys up */ - memcpy((byte*) (right ? key : father_key_pos),pos, (size_t) k_length); - memcpy((byte*) (right ? father_key_pos : key), tmp_part_key, k_length); - - if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR) - goto err; - _nisam_kpointer(info,key+k_length,new_pos); - if (_nisam_write_keypage(info,keyinfo,(right ? new_pos : next_page), - info->buff) || - _nisam_write_keypage(info,keyinfo,(right ? next_page : new_pos),extra_buff)) - goto err; - - DBUG_RETURN(1); /* Middle key up */ - -err: - DBUG_RETURN(-1); -} /* _nisam_balance_page */ |