summaryrefslogtreecommitdiff
path: root/heap
diff options
context:
space:
mode:
authorbk@work.mysql.com <>2000-07-31 21:29:14 +0200
committerbk@work.mysql.com <>2000-07-31 21:29:14 +0200
commitf4c589ff6c653d1d2a09c26e46ead3c8a15655d8 (patch)
treed253a359142dfc1ed247d5d4365d86972ea31109 /heap
parent7eec25e393727b16bb916b50d82b0aa3084e065c (diff)
downloadmariadb-git-f4c589ff6c653d1d2a09c26e46ead3c8a15655d8.tar.gz
Import changeset
Diffstat (limited to 'heap')
-rw-r--r--heap/.cvsignore6
-rw-r--r--heap/ChangeLog8
-rw-r--r--heap/Makefile.am37
-rw-r--r--heap/_check.c81
-rw-r--r--heap/_rectest.c31
-rw-r--r--heap/heapdef.h81
-rw-r--r--heap/hp_block.c111
-rw-r--r--heap/hp_clear.c52
-rw-r--r--heap/hp_close.c51
-rw-r--r--heap/hp_create.c62
-rw-r--r--heap/hp_delete.c151
-rw-r--r--heap/hp_extra.c47
-rw-r--r--heap/hp_hash.c266
-rw-r--r--heap/hp_info.c58
-rw-r--r--heap/hp_open.c173
-rw-r--r--heap/hp_panic.c57
-rw-r--r--heap/hp_rename.c42
-rw-r--r--heap/hp_rfirst.c28
-rw-r--r--heap/hp_rkey.c51
-rw-r--r--heap/hp_rlast.c29
-rw-r--r--heap/hp_rnext.c56
-rw-r--r--heap/hp_rprev.c53
-rw-r--r--heap/hp_rrnd.c106
-rw-r--r--heap/hp_rsame.c57
-rw-r--r--heap/hp_scan.c72
-rw-r--r--heap/hp_static.c26
-rw-r--r--heap/hp_test1.c187
-rw-r--r--heap/hp_test2.c659
-rw-r--r--heap/hp_update.c67
-rw-r--r--heap/hp_write.c275
-rwxr-xr-xheap/make-ccc4
31 files changed, 2984 insertions, 0 deletions
diff --git a/heap/.cvsignore b/heap/.cvsignore
new file mode 100644
index 00000000000..675df8a3eb6
--- /dev/null
+++ b/heap/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+hp_test1
+hp_test2
diff --git a/heap/ChangeLog b/heap/ChangeLog
new file mode 100644
index 00000000000..9d3ced84cc9
--- /dev/null
+++ b/heap/ChangeLog
@@ -0,0 +1,8 @@
+Sun Sep 6 10:56:59 1992 Michael Widenius (monty@bitch)
+
+ * Added functions for first,next,last,prev and clear of database-heap
+ * Added optional index to rsame for compability.
+
+Fri Aug 14 14:34:35 1992 Michael Widenius (monty@bitch)
+
+ * changed file parameter to HP_INFO *
diff --git a/heap/Makefile.am b/heap/Makefile.am
new file mode 100644
index 00000000000..3977eb5bb64
--- /dev/null
+++ b/heap/Makefile.am
@@ -0,0 +1,37 @@
+# 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$(srcdir)/../include -I../include
+LDADD = libheap.a ../mysys/libmysys.a ../dbug/libdbug.a \
+ ../strings/libmystrings.a
+pkglib_LIBRARIES = libheap.a
+noinst_PROGRAMS = hp_test1 hp_test2
+noinst_HEADERS = heapdef.h
+libheap_a_SOURCES = hp_open.c hp_extra.c hp_close.c hp_panic.c hp_info.c \
+ hp_rrnd.c hp_scan.c hp_update.c hp_write.c hp_delete.c \
+ hp_rsame.c hp_create.c hp_rename.c hp_rfirst.c \
+ hp_rnext.c hp_rlast.c hp_rprev.c hp_clear.c \
+ hp_rkey.c hp_block.c \
+ hp_hash.c _check.c _rectest.c hp_static.c
+
+OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
+ __math.h time.h __time.h unistd.h __unistd.h types.h \
+ xtypes.h ac-types.h posix.h string.h __string.h \
+ errno.h socket.h inet.h dirent.h netdb.h \
+ cleanup.h cond.h debug_out.h fd.h kernel.h mutex.h \
+ prio_queue.h pthread_attr.h pthread_once.h queue.h\
+ sleep.h specific.h version.h pwd.h timers.h uio.h \
+ cdefs.h machdep.h signal.h __signal.h util.h
diff --git a/heap/_check.c b/heap/_check.c
new file mode 100644
index 00000000000..77fa0262732
--- /dev/null
+++ b/heap/_check.c
@@ -0,0 +1,81 @@
+/* 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 that heap-structure is ok */
+
+#include "heapdef.h"
+
+static int check_one_key(HP_KEYDEF *keydef,ulong records,ulong blength);
+
+/* Returns 0 if the HEAP is ok */
+
+int heap_check_heap(HP_INFO *info)
+{
+ int error;
+ uint key;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_check_keys");
+
+ for (error=key=0 ; key < share->keys ; key++)
+ error|=check_one_key(share->keydef+key,share->records,share->blength);
+
+ DBUG_RETURN(error);
+}
+
+
+static int check_one_key(HP_KEYDEF *keydef, ulong records, ulong blength)
+{
+ int error;
+ uint i,found,max_links,seek,links;
+ uint rec_link; /* Only used with debugging */
+ HASH_INFO *hash_info;
+
+ error=0;
+ for (i=found=max_links=seek=0 ; i < records ; i++)
+ {
+ hash_info=hp_find_hash(&keydef->block,i);
+ if (_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
+ blength,records) == i)
+ {
+ found++;
+ seek++;
+ links=1;
+ while ((hash_info=hash_info->next_key) && found < records + 1)
+ {
+ seek+= ++links;
+ if ((rec_link=_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
+ blength,records))
+ != i)
+ {
+ DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
+ error=1;
+ }
+ else
+ found++;
+ }
+ if (links > max_links) max_links=links;
+ }
+ }
+ if (found != records)
+ {
+ DBUG_PRINT("error",("Found %ld of %ld records"));
+ error=1;
+ }
+ DBUG_PRINT("info",
+ ("records: %ld seeks: %d max links: %d hitrate: %.2f",
+ records,seek,max_links,(float) seek / (float) records));
+ return error;
+}
diff --git a/heap/_rectest.c b/heap/_rectest.c
new file mode 100644
index 00000000000..3368fbeeffa
--- /dev/null
+++ b/heap/_rectest.c
@@ -0,0 +1,31 @@
+/* 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 if a record has changed since last read */
+/* In heap this is only used when debugging */
+
+#include "heapdef.h"
+
+int _hp_rectest(register HP_INFO *info, register const byte *old)
+{
+ DBUG_ENTER("_hp_rectest");
+
+ if (memcmp(info->current_ptr,old,(size_t) info->s->reclength))
+ {
+ DBUG_RETURN((my_errno=HA_ERR_RECORD_CHANGED)); /* Record have changed */
+ }
+ DBUG_RETURN(0);
+} /* _heap_rectest */
diff --git a/heap/heapdef.h b/heap/heapdef.h
new file mode 100644
index 00000000000..19c3b7d7792
--- /dev/null
+++ b/heap/heapdef.h
@@ -0,0 +1,81 @@
+/* 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 */
+
+/* This file is included in all heap-files */
+
+#include <my_base.h> /* This includes global */
+#ifdef THREAD
+#include <my_pthread.h>
+#endif
+#include "heap.h" /* Structs & some defines */
+
+ /* Some extern variables */
+
+extern LIST *heap_open_list,*heap_share_list;
+
+#define test_active(info) \
+if (!(info->update & HA_STATE_AKTIV))\
+{ my_errno=HA_ERR_NO_ACTIVE_RECORD; DBUG_RETURN(-1); }
+#define hp_find_hash(A,B) ((HASH_INFO*) _hp_find_block((A),(B)))
+
+ /* Find pos for record and update it in info->current_ptr */
+#define _hp_find_record(info,pos) (info)->current_ptr= _hp_find_block(&(info)->s->block,pos)
+
+typedef struct st_hash_info
+{
+ struct st_hash_info *next_key;
+ byte *ptr_to_rec;
+} HASH_INFO;
+
+ /* Prototypes for intern functions */
+
+extern HP_SHARE *_hp_find_named_heap(const char *name);
+extern int _hp_rectest(HP_INFO *info,const byte *old);
+extern void _hp_delete_file_from_open_list(HP_INFO *info);
+extern byte *_hp_find_block(HP_BLOCK *info,ulong pos);
+extern int _hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
+extern void _hp_free(HP_SHARE *info);
+extern byte *_hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
+ byte *last_pos);
+extern int _hp_write_key(HP_SHARE *info,HP_KEYDEF *keyinfo,
+ const byte *record,byte *recpos);
+extern int _hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
+ const byte *record,byte *recpos,int flag);
+extern HASH_INFO *_heap_find_hash(HP_BLOCK *block,ulong pos);
+extern byte *_hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
+ uint nextflag);
+extern byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
+ const byte *key,
+ HASH_INFO *pos);
+extern ulong _hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
+extern ulong _hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
+extern ulong _hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
+extern void _hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
+ HASH_INFO *newlink);
+extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
+ const byte *rec2);
+extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
+ const byte *key);
+extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
+extern int _hp_close(register HP_INFO *info);
+extern void _hp_clear(HP_SHARE *info);
+
+#ifdef THREAD
+extern pthread_mutex_t THR_LOCK_heap;
+#else
+#define pthread_mutex_lock(A)
+#define pthread_mutex_unlock(A)
+#endif
diff --git a/heap/hp_block.c b/heap/hp_block.c
new file mode 100644
index 00000000000..510d89d6d1e
--- /dev/null
+++ b/heap/hp_block.c
@@ -0,0 +1,111 @@
+/* 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 on blocks; Keys and records are saved in blocks */
+
+#include "heapdef.h"
+
+ /* Find record according to record-position */
+
+byte *_hp_find_block(HP_BLOCK *block, ulong pos)
+{
+ reg1 int i;
+ reg3 HP_PTRS *ptr;
+
+ for (i=block->levels-1, ptr=block->root ; i > 0 ; i--)
+ {
+ ptr=(HP_PTRS*)ptr->blocks[pos/block->level_info[i].records_under_level];
+ pos%=block->level_info[i].records_under_level;
+ }
+ return (byte*) ptr+ pos*block->recbuffer;
+}
+
+
+ /* get one new block-of-records. Alloc ptr to block if neaded */
+ /* Interrupts are stopped to allow ha_panic in interrupts */
+
+int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
+{
+ reg1 uint i,j;
+ HP_PTRS *root;
+
+ for (i=0 ; i < block->levels ; i++)
+ if (block->level_info[i].free_ptrs_in_block)
+ break;
+
+ *alloc_length=sizeof(HP_PTRS)*i+block->records_in_block* block->recbuffer;
+ if (!(root=(HP_PTRS*) my_malloc(*alloc_length,MYF(0))))
+ return 1;
+
+ if (i == 0)
+ {
+ block->levels=1;
+ block->root=block->level_info[0].last_blocks=root;
+ }
+ else
+ {
+ dont_break(); /* Dont allow SIGHUP or SIGINT */
+ if ((uint) i == block->levels)
+ {
+ block->levels=i+1;
+ block->level_info[i].free_ptrs_in_block=HP_PTRS_IN_NOD-1;
+ ((HP_PTRS**) root)[0]= block->root;
+ block->root=block->level_info[i].last_blocks= root++;
+ }
+ block->level_info[i].last_blocks->
+ blocks[HP_PTRS_IN_NOD - block->level_info[i].free_ptrs_in_block--]=
+ (byte*) root;
+
+ for (j=i-1 ; j >0 ; j--)
+ {
+ block->level_info[j].last_blocks= root++;
+ block->level_info[j].last_blocks->blocks[0]=(byte*) root;
+ block->level_info[j].free_ptrs_in_block=HP_PTRS_IN_NOD-1;
+ }
+ block->level_info[0].last_blocks= root;
+ allow_break(); /* Allow SIGHUP & SIGINT */
+ }
+ return 0;
+}
+
+
+ /* free all blocks under level */
+
+byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
+{
+ int i,max_pos;
+ byte *next_ptr;
+
+ if (level == 1)
+ next_ptr=(byte*) pos+block->recbuffer;
+ else
+ {
+ max_pos= (block->level_info[level-1].last_blocks == pos) ?
+ HP_PTRS_IN_NOD - block->level_info[level-1].free_ptrs_in_block :
+ HP_PTRS_IN_NOD;
+
+ next_ptr=(byte*) (pos+1);
+ for (i=0 ; i < max_pos ; i++)
+ next_ptr=_hp_free_level(block,level-1,
+ (HP_PTRS*) pos->blocks[i],next_ptr);
+ }
+ if ((byte*) pos != last_pos)
+ {
+ my_free((gptr) pos,MYF(0));
+ return last_pos;
+ }
+ return next_ptr; /* next memory position */
+}
diff --git a/heap/hp_clear.c b/heap/hp_clear.c
new file mode 100644
index 00000000000..702c2e09d29
--- /dev/null
+++ b/heap/hp_clear.c
@@ -0,0 +1,52 @@
+/* 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 */
+
+/*
+ remove all records from database
+ Identical as hp_create() and hp_open() but used HP_SHARE* instead of name and
+ database remains open.
+*/
+
+#include "heapdef.h"
+
+void heap_clear(HP_INFO *info)
+{
+ _hp_clear(info->s);
+}
+
+void _hp_clear(HP_SHARE *info)
+{
+ uint key;
+ DBUG_ENTER("_hp_clear");
+
+ if (info->block.levels)
+ VOID(_hp_free_level(&info->block,info->block.levels,info->block.root,
+ (byte*) 0));
+ info->block.levels=0;
+ for (key=0 ; key < info->keys ; key++)
+ {
+ HP_BLOCK *block= &info->keydef[key].block;
+ if (block->levels)
+ VOID(_hp_free_level(block,block->levels,block->root,(byte*) 0));
+ block->levels=0;
+ block->last_allocated=0;
+ }
+ info->records=info->deleted=info->data_length=info->index_length=0;;
+ info->blength=1;
+ info->changed=0;
+ info->del_link=0;
+ DBUG_VOID_RETURN;
+}
diff --git a/heap/hp_close.c b/heap/hp_close.c
new file mode 100644
index 00000000000..b1797d2e92f
--- /dev/null
+++ b/heap/hp_close.c
@@ -0,0 +1,51 @@
+/* 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 heap-database */
+
+#include "heapdef.h"
+
+ /* Close a database open by hp_open() */
+ /* Data is not deallocated */
+
+int heap_close(HP_INFO *info)
+{
+ int tmp;
+ DBUG_ENTER("heap_close");
+ pthread_mutex_lock(&THR_LOCK_heap);
+ tmp= _hp_close(info);
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(tmp);
+}
+
+
+int _hp_close(register HP_INFO *info)
+{
+ int error=0;
+ DBUG_ENTER("_hp_close");
+#ifndef DBUG_OFF
+ if (info->s->changed && heap_check_heap(info))
+ {
+ error=my_errno=HA_ERR_CRASHED;
+ }
+#endif
+ info->s->changed=0;
+ info->s->open_count--;
+ heap_open_list=list_delete(heap_open_list,&info->open_list);
+ my_free((gptr) info,MYF(0));
+ DBUG_RETURN(error);
+}
+
diff --git a/heap/hp_create.c b/heap/hp_create.c
new file mode 100644
index 00000000000..01c5f43adfd
--- /dev/null
+++ b/heap/hp_create.c
@@ -0,0 +1,62 @@
+/* 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 */
+
+/*
+ Create is done by simply remove the database from memory if it exists.
+ Open creates the database when neaded
+*/
+
+#include "heapdef.h"
+
+int heap_create(const char *name)
+{
+ DBUG_ENTER("heap_create");
+ (void) heap_delete_all(name);
+ DBUG_RETURN(0);
+}
+
+int heap_delete_all(const char *name)
+{
+ reg1 HP_SHARE *info;
+ int found;
+ DBUG_ENTER("heap_delete_all");
+ pthread_mutex_lock(&THR_LOCK_heap);
+ if ((info=_hp_find_named_heap(name)))
+ {
+ if (info->open_count == 0)
+ _hp_free(info);
+ found=0;
+ }
+ else
+ {
+ found=my_errno=ENOENT;
+ }
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(found);
+}
+
+void _hp_free(HP_SHARE *share)
+{
+ heap_share_list=list_delete(heap_share_list,&share->open_list);
+ _hp_clear(share); /* Remove blocks from memory */
+#ifdef THREAD
+ thr_lock_delete(&share->lock);
+ VOID(pthread_mutex_destroy(&share->intern_lock));
+#endif
+ my_free((gptr) share->name,MYF(0));
+ my_free((gptr) share,MYF(0));
+ return;
+}
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
new file mode 100644
index 00000000000..a6e77fe5f27
--- /dev/null
+++ b/heap/hp_delete.c
@@ -0,0 +1,151 @@
+/* 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 */
+
+/* remove current record in heap-database */
+
+#include "heapdef.h"
+
+int heap_delete(HP_INFO *info, const byte *record)
+{
+ uint key;
+ byte *pos;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_delete");
+ DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
+
+ test_active(info);
+
+ if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,record))
+ DBUG_RETURN(my_errno); /* Record changed */
+ share->changed=1;
+
+ if ( --(share->records) < share->blength >> 1) share->blength>>=1;
+ pos=info->current_ptr;
+
+ for (key=0 ; key < share->keys ; key++)
+ {
+ if (_hp_delete_key(info,share->keydef+key,record,pos,
+ key == (uint) info->lastinx))
+ goto err;
+ }
+
+ info->update=HA_STATE_DELETED;
+ *((byte**) pos)=share->del_link;
+ share->del_link=pos;
+ pos[share->reclength]=0; /* Record deleted */
+ share->deleted++;
+ info->current_hash_ptr=0;
+ DBUG_RETURN(0);
+ err:
+ if( ++(share->records) == share->blength) share->blength+= share->blength;
+ DBUG_RETURN(my_errno);
+}
+
+ /* Remove one key from hash-table */
+ /* Flag is set if we want's to correct info->current_ptr */
+
+int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
+ const byte *record, byte *recpos, int flag)
+{
+ ulong blength,pos2,pos_hashnr,lastpos_hashnr;
+ HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("_hp_delete_key");
+
+ blength=share->blength;
+ if (share->records+1 == blength) blength+= blength;
+ lastpos=hp_find_hash(&keyinfo->block,share->records);
+ last_ptr=0;
+
+ /* Search after record with key */
+ pos= hp_find_hash(&keyinfo->block,
+ _hp_mask(_hp_rec_hashnr(keyinfo,record),blength,
+ share->records+1));
+ gpos = pos3 = 0;
+
+ while (pos->ptr_to_rec != recpos)
+ {
+ if (flag && !_hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
+ last_ptr=pos; /* Previous same key */
+ gpos=pos;
+ if (!(pos=pos->next_key))
+ {
+ DBUG_RETURN(my_errno=HA_ERR_CRASHED); /* This shouldn't happend */
+ }
+ }
+
+ /* Remove link to record */
+
+ if (flag)
+ {
+ /* Save for heap_rnext/heap_rprev */
+ info->current_hash_ptr=last_ptr;
+ info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
+ DBUG_PRINT("info",("Corrected current_ptr to point at: %lx",
+ info->current_ptr));
+ }
+ empty=pos;
+ if (gpos)
+ gpos->next_key=pos->next_key; /* unlink current ptr */
+ else if (pos->next_key)
+ {
+ empty=pos->next_key;
+ pos->ptr_to_rec=empty->ptr_to_rec;
+ pos->next_key=empty->next_key;
+ }
+
+ if (empty == lastpos) /* deleted last hash key */
+ DBUG_RETURN (0);
+
+ /* Move the last key (lastpos) */
+ lastpos_hashnr=_hp_rec_hashnr(keyinfo,lastpos->ptr_to_rec);
+ /* pos is where lastpos should be */
+ pos=hp_find_hash(&keyinfo->block,_hp_mask(lastpos_hashnr,share->blength,
+ share->records));
+ if (pos == empty) /* Move to empty position. */
+ {
+ empty[0]=lastpos[0];
+ DBUG_RETURN(0);
+ }
+ pos_hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
+ /* pos3 is where the pos should be */
+ pos3= hp_find_hash(&keyinfo->block,
+ _hp_mask(pos_hashnr,share->blength,share->records));
+ if (pos != pos3)
+ { /* pos is on wrong posit */
+ empty[0]=pos[0]; /* Save it here */
+ pos[0]=lastpos[0]; /* This shold be here */
+ _hp_movelink(pos,pos3,empty); /* Fix link to pos */
+ DBUG_RETURN(0);
+ }
+ pos2= _hp_mask(lastpos_hashnr,blength,share->records+1);
+ if (pos2 == _hp_mask(pos_hashnr,blength,share->records+1))
+ { /* Identical key-positions */
+ if (pos2 != share->records)
+ {
+ empty[0]=lastpos[0];
+ _hp_movelink(lastpos,pos,empty);
+ DBUG_RETURN(0);
+ }
+ pos3= pos; /* Link pos->next after lastpos */
+ }
+ else pos3= 0; /* Different positions merge */
+
+ empty[0]=lastpos[0];
+ _hp_movelink(pos3,empty,pos->next_key);
+ pos->next_key=empty;
+ DBUG_RETURN(0);
+}
diff --git a/heap/hp_extra.c b/heap/hp_extra.c
new file mode 100644
index 00000000000..581ca1e8e56
--- /dev/null
+++ b/heap/hp_extra.c
@@ -0,0 +1,47 @@
+/* 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 "heapdef.h"
+
+ /* set extra flags for database */
+
+int heap_extra(register HP_INFO *info, enum ha_extra_function function)
+{
+ DBUG_ENTER("heap_extra");
+
+ switch (function) {
+ case HA_EXTRA_RESET:
+ info->lastinx= -1;
+ info->current_record= (ulong) ~0L;
+ info->current_hash_ptr=0;
+ info->update=0;
+ 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;
+ default:
+ break;
+ }
+ DBUG_RETURN(0);
+} /* heap_extra */
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
new file mode 100644
index 00000000000..28647ab7c94
--- /dev/null
+++ b/heap/hp_hash.c
@@ -0,0 +1,266 @@
+/* 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 */
+
+/* The hash functions used for saveing keys */
+
+#include "heapdef.h"
+#include <m_ctype.h>
+
+ /* Search after a record based on a key */
+ /* Sets info->current_ptr to found record */
+ /* next_flag: Search=0, next=1, prev =2, same =3 */
+
+byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
+ uint nextflag)
+{
+ reg1 HASH_INFO *pos,*prev_ptr;
+ int flag;
+ uint old_nextflag;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("_hp_search");
+
+ old_nextflag=nextflag;
+ flag=1;
+ prev_ptr=0;
+
+ if (share->records)
+ {
+ pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_hashnr(keyinfo,key),
+ share->blength,share->records));
+ do
+ {
+ if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
+ {
+ switch (nextflag) {
+ case 0: /* Search after key */
+ DBUG_PRINT("exit",("found key at %d",pos->ptr_to_rec));
+ info->current_hash_ptr=pos;
+ DBUG_RETURN(info->current_ptr= pos->ptr_to_rec);
+ case 1: /* Search next */
+ if (pos->ptr_to_rec == info->current_ptr)
+ nextflag=0;
+ break;
+ case 2: /* Search previous */
+ if (pos->ptr_to_rec == info->current_ptr)
+ {
+ my_errno=HA_ERR_KEY_NOT_FOUND; /* If gpos == 0 */
+ info->current_hash_ptr=prev_ptr;
+ DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
+ }
+ prev_ptr=pos; /* Prev. record found */
+ break;
+ case 3: /* Search same */
+ if (pos->ptr_to_rec == info->current_ptr)
+ {
+ info->current_hash_ptr=pos;
+ DBUG_RETURN(info->current_ptr);
+ }
+ }
+ }
+ if (flag)
+ {
+ flag=0; /* Reset flag */
+ if (hp_find_hash(&keyinfo->block,
+ _hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
+ share->blength,share->records)) != pos)
+ break; /* Wrong link */
+ }
+ }
+ while ((pos=pos->next_key));
+ }
+ my_errno=HA_ERR_KEY_NOT_FOUND;
+ if (nextflag == 2 && ! info->current_ptr)
+ {
+ /* Do a previous from end */
+ info->current_hash_ptr=prev_ptr;
+ DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
+ }
+
+ if (old_nextflag && nextflag)
+ my_errno=HA_ERR_RECORD_CHANGED; /* Didn't find old record */
+ DBUG_PRINT("exit",("Error: %d",my_errno));
+ info->current_hash_ptr=0;
+ DBUG_RETURN((info->current_ptr= 0));
+}
+
+
+/*
+ Search next after last read; Assumes that the table hasn't changed
+ since last read !
+*/
+
+byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
+ HASH_INFO *pos)
+{
+ DBUG_ENTER("_hp_search_next");
+
+ while ((pos= pos->next_key))
+ {
+ if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
+ {
+ info->current_hash_ptr=pos;
+ DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
+ }
+ }
+ my_errno=HA_ERR_KEY_NOT_FOUND;
+ DBUG_PRINT("exit",("Error: %d",my_errno));
+ info->current_hash_ptr=0;
+ DBUG_RETURN ((info->current_ptr= 0));
+}
+
+
+ /* Calculate pos according to keys */
+
+ulong _hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
+{
+ if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
+ return (hashnr & ((buffmax >> 1) -1));
+}
+
+
+ /* Change link from pos to new_link */
+
+void _hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
+{
+ HASH_INFO *old_link;
+ do
+ {
+ old_link=next_link;
+ }
+ while ((next_link=next_link->next_key) != pos);
+ old_link->next_key=newlink;
+ return;
+}
+
+
+ /* Calc hashvalue for a key */
+
+ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
+{
+ register ulong nr=1, nr2=4;
+ HP_KEYSEG *seg,*endseg;
+ uchar *pos;
+
+ for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
+ {
+ if (seg->type == HA_KEYTYPE_TEXT)
+ {
+ for (pos=(uchar*) key,key+=seg->length ; pos < (uchar*) key ; pos++)
+ {
+ nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
+ nr2+=3;
+ }
+ }
+ else
+ {
+ for (pos=(uchar*) key,key+=seg->length ; pos < (uchar*) key ; pos++)
+ {
+ nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8);
+ nr2+=3;
+ }
+ }
+ }
+ return((ulong) nr);
+}
+
+ /* Calc hashvalue for a key in a record */
+
+ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
+{
+ register ulong nr=1, nr2=4;
+ HP_KEYSEG *seg,*endseg;
+ uchar *pos,*end;
+
+ for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
+ {
+ if (seg->type == HA_KEYTYPE_TEXT)
+ {
+ for (pos=(uchar*) rec+seg->start,end=pos+seg->length ; pos < end ; pos++)
+ {
+ nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
+ nr2+=3;
+ }
+ }
+ else
+ {
+ for (pos=(uchar*) rec+seg->start,end=pos+seg->length ; pos < end ; pos++)
+ {
+ nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8);
+ nr2+=3;
+ }
+ }
+ }
+ return((ulong) nr);
+}
+
+ /* Compare keys for two records. Returns 0 if they are identical */
+
+int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
+{
+ HP_KEYSEG *seg,*endseg;
+
+ for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
+ {
+ if (seg->type == HA_KEYTYPE_TEXT)
+ {
+ if (my_sortcmp(rec1+seg->start,rec2+seg->start,seg->length))
+ return 1;
+ }
+ else
+ {
+ if (bcmp(rec1+seg->start,rec2+seg->start,seg->length))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+ /* Compare a key in a record to a hole key */
+
+int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
+{
+ HP_KEYSEG *seg,*endseg;
+
+ for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
+ {
+ if (seg->type == HA_KEYTYPE_TEXT)
+ {
+ if (my_sortcmp(rec+seg->start,key,seg->length))
+ return 1;
+ }
+ else
+ {
+ if (bcmp(rec+seg->start,key,seg->length))
+ return 1;
+ }
+ key+=seg->length;
+ }
+ return 0;
+}
+
+
+ /* Copy a key from a record to a keybuffer */
+
+void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
+{
+ HP_KEYSEG *seg,*endseg;
+
+ for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
+ {
+ memcpy(key,rec+seg->start,(size_t) seg->length);
+ key+=seg->length;
+ }
+}
diff --git a/heap/hp_info.c b/heap/hp_info.c
new file mode 100644
index 00000000000..260ac31ab8e
--- /dev/null
+++ b/heap/hp_info.c
@@ -0,0 +1,58 @@
+/* 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 */
+
+/* Returns info about database status */
+
+#include "heapdef.h"
+
+
+byte *heap_position(HP_INFO *info)
+{
+ return ((info->update & HA_STATE_AKTIV) ? info->current_ptr :
+ (HEAP_PTR) 0);
+}
+
+
+#ifdef WANT_OLD_HEAP_VERSION
+
+/*
+ The following should NOT be used anymore as this can't be used together with
+ heap_rkey()
+*/
+
+ulong heap_position_old(HP_INFO *info)
+{
+ return ((info->update & HA_STATE_AKTIV) ? info->current_record :
+ (ulong) ~0L);
+}
+
+#endif /* WANT_OLD_HEAP_CODE */
+
+/* Note that heap_info does NOT return information about the
+ current position anymore; Use heap_position instead */
+
+int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x,int flag)
+{
+ DBUG_ENTER("heap_info");
+ x->records = info->s->records;
+ x->deleted = info->s->deleted;
+ x->reclength = info->s->reclength;
+ x->data_length = info->s->data_length;
+ x->index_length= info->s->index_length;
+ x->max_records = info->s->max_records;
+ x->errkey = info->errkey;
+ DBUG_RETURN(0);
+} /* heap_info */
diff --git a/heap/hp_open.c b/heap/hp_open.c
new file mode 100644
index 00000000000..77de5ca824a
--- /dev/null
+++ b/heap/hp_open.c
@@ -0,0 +1,173 @@
+/* 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 heap-database */
+
+#include "heapdef.h"
+#ifdef VMS
+#include "hp_static.c" /* Stupid vms-linker */
+#endif
+
+static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
+ ulong max_records);
+
+ /* open a heap database. */
+
+HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
+ uint reclength, ulong max_records, ulong min_records)
+{
+ uint i,j,key_segs,max_length,length;
+ HP_INFO *info;
+ HP_SHARE *share;
+ HP_KEYSEG *keyseg;
+ DBUG_ENTER("heap_open");
+
+ pthread_mutex_lock(&THR_LOCK_heap);
+ if (!(share=_hp_find_named_heap(name)))
+ {
+ for (i=key_segs=max_length=0 ; i < keys ; i++)
+ {
+ key_segs+= keydef[i].keysegs;
+ bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
+ for (j=length=0 ; j < keydef[i].keysegs; j++)
+ length+=keydef[i].seg[j].length;
+ keydef[i].length=length;
+ if (length > max_length)
+ max_length=length;
+ }
+ if (!(share = (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
+ keys*sizeof(HP_KEYDEF)+
+ key_segs*sizeof(HP_KEYSEG),
+ MYF(MY_ZEROFILL))))
+ {
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(0);
+ }
+ share->keydef=(HP_KEYDEF*) (share+1);
+ keyseg=(HP_KEYSEG*) (share->keydef+keys);
+ init_block(&share->block,reclength+1,min_records,max_records);
+ /* Fix keys */
+ memcpy(share->keydef,keydef,(size_t) (sizeof(keydef[0])*keys));
+ for (i=0 ; i < keys ; i++)
+ {
+ share->keydef[i].seg=keyseg;
+ memcpy(keyseg,keydef[i].seg,
+ (size_t) (sizeof(keyseg[0])*keydef[i].keysegs));
+ keyseg+=keydef[i].keysegs;
+ init_block(&share->keydef[i].block,sizeof(HASH_INFO),min_records,
+ max_records);
+ }
+
+ share->min_records=min_records;
+ share->max_records=max_records;
+ share->data_length=share->index_length=0;
+ share->reclength=reclength;
+ share->blength=1;
+ share->keys=keys;
+ share->max_key_length=max_length;
+ share->changed=0;
+ if (!(share->name=my_strdup(name,MYF(0))))
+ {
+ my_free((gptr) share,MYF(0));
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(0);
+ }
+#ifdef THREAD
+ thr_lock_init(&share->lock);
+ VOID(pthread_mutex_init(&share->intern_lock,NULL));
+#endif
+ share->open_list.data=(void*) share;
+ heap_share_list=list_add(heap_share_list,&share->open_list);
+ }
+ if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO)+
+ share->max_key_length,
+ MYF(MY_ZEROFILL))))
+ {
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(0);
+ }
+ share->open_count++;
+#ifdef THREAD
+ thr_lock_data_init(&share->lock,&info->lock,NULL);
+#endif
+ info->open_list.data=(void*) info;
+ heap_open_list=list_add(heap_open_list,&info->open_list);
+ pthread_mutex_unlock(&THR_LOCK_heap);
+
+ info->s=share;
+ info->lastkey=(byte*) (info+1);
+ info->mode=mode;
+ info->current_record= (ulong) ~0L; /* No current record */
+ info->current_ptr=0;
+ info->current_hash_ptr=0;
+ info->lastinx= info->errkey= -1;
+ info->update=0;
+#ifndef DBUG_OFF
+ info->opt_flag=READ_CHECK_USED; /* Check when changing */
+#endif
+ DBUG_PRINT("exit",("heap: %lx reclength: %d records_in_block: %d",
+ info,share->reclength,share->block.records_in_block));
+ DBUG_RETURN(info);
+} /* heap_open */
+
+
+ /* map name to a heap-nr. If name isn't found return 0 */
+
+HP_SHARE *_hp_find_named_heap(const char *name)
+{
+ LIST *pos;
+ HP_SHARE *info;
+ DBUG_ENTER("heap_find");
+ DBUG_PRINT("enter",("name: %s",name));
+
+ for (pos=heap_share_list ; pos ; pos=pos->next)
+ {
+ info=(HP_SHARE*) pos->data;
+ if (!strcmp(name,info->name))
+ {
+ DBUG_PRINT("exit",("Old heap_database: %lx",info));
+ DBUG_RETURN(info);
+ }
+ }
+ DBUG_RETURN((HP_SHARE *)0);
+}
+
+
+static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
+ ulong max_records)
+{
+ uint i,recbuffer,records_in_block;
+
+ max_records=max(min_records,max_records);
+ if (!max_records)
+ max_records=1000; /* As good as quess as anything */
+ recbuffer=(uint) (reclength+sizeof(byte**)-1) & ~(sizeof(byte**)-1);
+ records_in_block=max_records/10;
+ if (records_in_block < 10 && max_records)
+ records_in_block=10;
+ if (!records_in_block || records_in_block*recbuffer >
+ (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
+ records_in_block=(my_default_record_cache_size-sizeof(HP_PTRS)*
+ HP_MAX_LEVELS)/recbuffer+1;
+ block->records_in_block=records_in_block;
+ block->recbuffer=recbuffer;
+ block->last_allocated= 0L;
+
+ for (i=0 ; i <= HP_MAX_LEVELS ; i++)
+ block->level_info[i].records_under_level=
+ (!i ? 1 : i == 1 ? records_in_block :
+ HP_PTRS_IN_NOD * block->level_info[i-1].records_under_level);
+}
diff --git a/heap/hp_panic.c b/heap/hp_panic.c
new file mode 100644
index 00000000000..cfd370a56d0
--- /dev/null
+++ b/heap/hp_panic.c
@@ -0,0 +1,57 @@
+/* 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 "heapdef.h"
+
+ /* if flag == HA_PANIC_CLOSE then all files are removed for more
+ memory */
+
+int heap_panic(enum ha_panic_function flag)
+{
+ LIST *element,*next_open;
+ DBUG_ENTER("heap_panic");
+
+ pthread_mutex_lock(&THR_LOCK_heap);
+ for (element=heap_open_list ; element ; element=next_open)
+ {
+ HP_INFO *info=(HP_INFO*) element->data;
+ next_open=element->next; /* Save if close */
+ switch (flag) {
+ case HA_PANIC_CLOSE:
+ _hp_close(info);
+ break;
+ default:
+ break;
+ }
+ }
+ for (element=heap_share_list ; element ; element=next_open)
+ {
+ HP_SHARE *share=(HP_SHARE*) element->data;
+ next_open=element->next; /* Save if close */
+ switch (flag) {
+ case HA_PANIC_CLOSE:
+ {
+ if (!share->open_count)
+ _hp_free(share);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(0);
+} /* heap_panic */
diff --git a/heap/hp_rename.c b/heap/hp_rename.c
new file mode 100644
index 00000000000..267c16b589d
--- /dev/null
+++ b/heap/hp_rename.c
@@ -0,0 +1,42 @@
+/* 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 */
+
+/*
+ Rename a table
+*/
+
+#include "heapdef.h"
+
+int heap_rename(const char *old_name, const char *new_name)
+{
+ reg1 HP_SHARE *info;
+ char *name_buff;
+ DBUG_ENTER("heap_rename");
+
+ pthread_mutex_lock(&THR_LOCK_heap);
+ if ((info=_hp_find_named_heap(old_name)))
+ {
+ if (!(name_buff=(char*) my_strdup(new_name,MYF(MY_WME))))
+ {
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(my_errno);
+ }
+ my_free(info->name,MYF(0));
+ info->name=name_buff;
+ }
+ pthread_mutex_unlock(&THR_LOCK_heap);
+ DBUG_RETURN(0);
+}
diff --git a/heap/hp_rfirst.c b/heap/hp_rfirst.c
new file mode 100644
index 00000000000..e3b9654061d
--- /dev/null
+++ b/heap/hp_rfirst.c
@@ -0,0 +1,28 @@
+/* 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 "heapdef.h"
+
+/* Read first record with the current key */
+
+int heap_rfirst(HP_INFO *info, byte *record)
+{
+ DBUG_ENTER("heap_rfirst");
+ info->current_record=0;
+ info->current_hash_ptr=0;
+ info->update=HA_STATE_PREV_FOUND;
+ DBUG_RETURN(heap_rnext(info,record));
+}
diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c
new file mode 100644
index 00000000000..872560b1a91
--- /dev/null
+++ b/heap/hp_rkey.c
@@ -0,0 +1,51 @@
+/* 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 "heapdef.h"
+
+int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
+{
+ byte *pos;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("hp_rkey");
+ DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
+
+ if ((uint) inx >= share->keys)
+ {
+ DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
+ }
+ info->lastinx=inx;
+ info->current_record = (ulong) ~0L; /* For heap_rrnd() */
+
+ if (!(pos=_hp_search(info,share->keydef+inx,key,0)))
+ {
+ info->update=0;
+ DBUG_RETURN(my_errno);
+ }
+ memcpy(record,pos,(size_t) share->reclength);
+ info->update=HA_STATE_AKTIV;
+ if (!(share->keydef->flag & HA_NOSAME))
+ memcpy(info->lastkey,key,(size_t) share->keydef[inx].length);
+ DBUG_RETURN(0);
+}
+
+
+ /* Quick find of record */
+
+gptr heap_find(HP_INFO *info, int inx, const byte *key)
+{
+ return _hp_search(info,info->s->keydef+inx,key,0);
+}
diff --git a/heap/hp_rlast.c b/heap/hp_rlast.c
new file mode 100644
index 00000000000..38e07fde2bb
--- /dev/null
+++ b/heap/hp_rlast.c
@@ -0,0 +1,29 @@
+/* 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 "heapdef.h"
+
+ /* Read first record with the current key */
+
+
+int heap_rlast(HP_INFO *info, byte *record)
+{
+ DBUG_ENTER("heap_rlast");
+ info->current_ptr=0;
+ info->current_hash_ptr=0;
+ info->update=HA_STATE_NEXT_FOUND;
+ DBUG_RETURN(heap_rprev(info,record));
+}
diff --git a/heap/hp_rnext.c b/heap/hp_rnext.c
new file mode 100644
index 00000000000..1b775136655
--- /dev/null
+++ b/heap/hp_rnext.c
@@ -0,0 +1,56 @@
+/* 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 "heapdef.h"
+
+/* Read next record with the same key */
+
+int heap_rnext(HP_INFO *info, byte *record)
+{
+ byte *pos;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_rnext");
+
+ if (info->lastinx < 0)
+ DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
+
+ if (info->current_hash_ptr)
+ pos= _hp_search_next(info,share->keydef+info->lastinx, info->lastkey,
+ info->current_hash_ptr);
+ else
+ {
+ if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
+ {
+ pos=0; /* Read next after last */
+ my_errno=HA_ERR_KEY_NOT_FOUND;
+ }
+ else if (!info->current_ptr && (info->update & HA_STATE_PREV_FOUND))
+ pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 0);
+ else
+ pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 1);
+ }
+
+ if (!pos)
+ {
+ info->update=HA_STATE_NEXT_FOUND; /* For heap_rprev */
+ if (my_errno == HA_ERR_KEY_NOT_FOUND)
+ my_errno=HA_ERR_END_OF_FILE;
+ DBUG_RETURN(my_errno);
+ }
+ memcpy(record,pos,(size_t) share->reclength);
+ info->update=HA_STATE_AKTIV | HA_STATE_NEXT_FOUND;
+ DBUG_RETURN(0);
+}
diff --git a/heap/hp_rprev.c b/heap/hp_rprev.c
new file mode 100644
index 00000000000..28a821c143e
--- /dev/null
+++ b/heap/hp_rprev.c
@@ -0,0 +1,53 @@
+/* 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 "heapdef.h"
+
+ /* Read prev record for key */
+
+
+int heap_rprev(HP_INFO *info, byte *record)
+{
+ byte *pos;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_rprev");
+
+ if (info->lastinx < 0)
+ DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
+
+ if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
+ {
+ if ((info->update & HA_STATE_DELETED))
+ pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 3);
+ else
+ pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 2);
+ }
+ else
+ {
+ pos=0; /* Read next after last */
+ my_errno=HA_ERR_KEY_NOT_FOUND;
+ }
+ if (!pos)
+ {
+ info->update=HA_STATE_PREV_FOUND; /* For heap_rprev */
+ if (my_errno == HA_ERR_KEY_NOT_FOUND)
+ my_errno=HA_ERR_END_OF_FILE;
+ DBUG_RETURN(my_errno);
+ }
+ memcpy(record,pos,(size_t) share->reclength);
+ info->update=HA_STATE_AKTIV | HA_STATE_PREV_FOUND;
+ DBUG_RETURN(0);
+}
diff --git a/heap/hp_rrnd.c b/heap/hp_rrnd.c
new file mode 100644
index 00000000000..63181967a29
--- /dev/null
+++ b/heap/hp_rrnd.c
@@ -0,0 +1,106 @@
+/* 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 from a random position */
+
+#include "heapdef.h"
+
+/*
+ Returns one of following values:
+ 0 = Ok.
+ HA_ERR_RECORD_DELETED = Record is deleted.
+ HA_ERR_END_OF_FILE = EOF.
+*/
+
+int heap_rrnd(register HP_INFO *info, byte *record, byte *pos)
+{
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_rrnd");
+ DBUG_PRINT("enter",("info: %lx pos: %lx",info,pos));
+
+ info->lastinx= -1;
+ if (!(info->current_ptr= pos))
+ {
+ info->update= 0;
+ DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
+ }
+ if (!info->current_ptr[share->reclength])
+ {
+ info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
+ DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
+ }
+ info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
+ memcpy(record,info->current_ptr,(size_t) share->reclength);
+ DBUG_PRINT("exit",("found record at %lx",info->current_ptr));
+ info->current_hash_ptr=0; /* Can't use rnext */
+ DBUG_RETURN(0);
+} /* heap_rrnd */
+
+
+#ifdef WANT_OLD_HEAP_VERSION
+
+/*
+ If pos == -1 then read next record
+ Returns one of following values:
+ 0 = Ok.
+ HA_ERR_RECORD_DELETED = Record is deleted.
+ HA_ERR_END_OF_FILE = EOF.
+*/
+
+int heap_rrnd_old(register HP_INFO *info, byte *record, ulong pos)
+{
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_rrnd");
+ DBUG_PRINT("enter",("info: %lx pos: %ld",info,pos));
+
+ info->lastinx= -1;
+ if (pos == (ulong) -1)
+ {
+ pos= ++info->current_record;
+ if (pos % share->block.records_in_block && /* Quick next record */
+ pos < share->records+share->deleted &&
+ (info->update & HA_STATE_PREV_FOUND))
+ {
+ info->current_ptr+=share->block.recbuffer;
+ goto end;
+ }
+ }
+ else
+ info->current_record=pos;
+
+ if (pos >= share->records+share->deleted)
+ {
+ info->update= 0;
+ DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
+ }
+
+ /* Find record number pos */
+ _hp_find_record(info,pos);
+
+end:
+ if (!info->current_ptr[share->reclength])
+ {
+ info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
+ DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
+ }
+ info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
+ memcpy(record,info->current_ptr,(size_t) share->reclength);
+ DBUG_PRINT("exit",("found record at %lx",info->current_ptr));
+ info->current_hash_ptr=0; /* Can't use rnext */
+ DBUG_RETURN(0);
+} /* heap_rrnd */
+
+#endif /* WANT_OLD_HEAP_VERSION */
diff --git a/heap/hp_rsame.c b/heap/hp_rsame.c
new file mode 100644
index 00000000000..888fb349f5a
--- /dev/null
+++ b/heap/hp_rsame.c
@@ -0,0 +1,57 @@
+/* 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 */
+
+/* re-read current record */
+
+#include "heapdef.h"
+
+ /* If inx != -1 the new record is read according to index
+ (for next/prev). Record must in this case point to last record
+ Returncodes:
+ 0 = Ok.
+ HA_ERR_RECORD_DELETED = Record was removed
+ HA_ERR_KEY_NOT_FOUND = Record not found with key
+ */
+
+int heap_rsame(register HP_INFO *info, byte *record, int inx)
+{
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_rsame");
+
+ test_active(info);
+ if (info->current_ptr[share->reclength])
+ {
+ if (inx < -1 || inx >= (int) share->keys)
+ {
+ DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
+ }
+ else if (inx != -1)
+ {
+ info->lastinx=inx;
+ _hp_make_key(share->keydef+inx,info->lastkey,record);
+ if (!_hp_search(info,share->keydef+inx,info->lastkey,3))
+ {
+ info->update=0;
+ DBUG_RETURN(my_errno);
+ }
+ }
+ memcpy(record,info->current_ptr,(size_t) share->reclength);
+ DBUG_RETURN(0);
+ }
+ info->update=0;
+
+ DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
+}
diff --git a/heap/hp_scan.c b/heap/hp_scan.c
new file mode 100644
index 00000000000..b7684cd2673
--- /dev/null
+++ b/heap/hp_scan.c
@@ -0,0 +1,72 @@
+/* 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 */
+
+/* Scan through all rows */
+
+#include "heapdef.h"
+
+/*
+ Returns one of following values:
+ 0 = Ok.
+ HA_ERR_RECORD_DELETED = Record is deleted.
+ HA_ERR_END_OF_FILE = EOF.
+*/
+
+int heap_scan_init(register HP_INFO *info)
+{
+ DBUG_ENTER("heap_scan_init");
+ info->lastinx= -1;
+ info->current_record= (ulong) ~0L; /* No current record */
+ info->update=0;
+ info->next_block=0;
+ DBUG_RETURN(0);
+}
+
+int heap_scan(register HP_INFO *info, byte *record)
+{
+ HP_SHARE *share=info->s;
+ ulong pos;
+ DBUG_ENTER("heap_scan");
+
+ pos= ++info->current_record;
+ if (pos < info->next_block)
+ {
+ info->current_ptr+=share->block.recbuffer;
+ }
+ else
+ {
+ info->next_block+=share->block.records_in_block;
+ if (info->next_block >= share->records+share->deleted)
+ {
+ info->next_block= share->records+share->deleted;
+ if (pos >= info->next_block)
+ {
+ info->update= 0;
+ DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
+ }
+ }
+ _hp_find_record(info,pos);
+ }
+ if (!info->current_ptr[share->reclength])
+ {
+ info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
+ DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
+ }
+ info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
+ memcpy(record,info->current_ptr,(size_t) share->reclength);
+ info->current_hash_ptr=0; /* Can't use read_next */
+ DBUG_RETURN(0);
+} /* heap_scan */
diff --git a/heap/hp_static.c b/heap/hp_static.c
new file mode 100644
index 00000000000..5e5326ca76b
--- /dev/null
+++ b/heap/hp_static.c
@@ -0,0 +1,26 @@
+/* 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 heap library. All definied here for easy making of
+ a shared library
+*/
+
+#ifndef _global_h
+#include "heapdef.h"
+#endif
+
+LIST *heap_open_list=0,*heap_share_list=0;
diff --git a/heap/hp_test1.c b/heap/hp_test1.c
new file mode 100644
index 00000000000..848157e831b
--- /dev/null
+++ b/heap/hp_test1.c
@@ -0,0 +1,187 @@
+/* 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 heap-database */
+/* Programmet skapar en heap-databas. Till denna skrivs ett antal poster.
+ Databasen st{ngs. D{refter |ppnas den p} nytt och en del av posterna
+ raderas.
+*/
+
+#include <global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include "heap.h"
+
+static int get_options(int argc, char *argv[]);
+
+static int flag=0,verbose=0,remove_ant=0,flags[50];
+
+int main(int argc, char **argv)
+{
+ int i,j,error,deleted;
+ HP_INFO *file;
+ char record[128],key[32];
+ const char *filename;
+ HP_KEYDEF keyinfo[10];
+ HP_KEYSEG keyseg[4];
+ MY_INIT(argv[0]);
+
+ filename= "test1";
+ get_options(argc,argv);
+
+ keyinfo[0].keysegs=1;
+ keyinfo[0].seg=keyseg;
+ keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
+ keyinfo[0].seg[0].start=1;
+ keyinfo[0].seg[0].length=6;
+ keyinfo[0].flag = HA_NOSAME;
+
+ deleted=0;
+ bzero((gptr) flags,sizeof(flags));
+
+ printf("- Creating heap-file\n");
+ heap_create(filename);
+ if (!(file=heap_open(filename,2,1,keyinfo,30,(ulong) flag*100000l,10l)))
+ goto err;
+ printf("- Writing records:s\n");
+ strmov(record," ..... key ");
+
+ for (i=49 ; i>=1 ; i-=2 )
+ {
+ j=i%25 +1;
+ sprintf(key,"%6d",j);
+ bmove(record+1,key,6);
+ error=heap_write(file,record);
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+ flags[j]=1;
+ if (verbose || error) printf("J= %2d heap_write: %d my_errno: %d\n",
+ j,error,my_errno);
+ }
+ if (heap_close(file))
+ goto err;
+ printf("- Reopening file\n");
+ if (!(file=heap_open(filename,2,1,keyinfo,30,(ulong) flag*100000l,10l)))
+ goto err;
+
+ printf("- Removing records\n");
+ for (i=1 ; i<=10 ; i++)
+ {
+ if (i == remove_ant) { VOID(heap_close(file)) ; return (0) ; }
+ sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
+ if ((error = heap_rkey(file,record,0,key)))
+ {
+ if (verbose || (flags[j] == 1 ||
+ (error && my_errno != HA_ERR_KEY_NOT_FOUND)))
+ printf("key: %s rkey: %3d my_errno: %3d\n",key,error,my_errno);
+ }
+ else
+ {
+ error=heap_delete(file,record);
+ if (error || verbose)
+ printf("key: %s delete: %d my_errno: %d\n",key,error,my_errno);
+ flags[j]=0;
+ if (! error)
+ deleted++;
+ }
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+ }
+
+ printf("- Reading records with key\n");
+ for (i=1 ; i<=25 ; i++)
+ {
+ sprintf(key,"%6d",i);
+ bmove(record+1,key,6);
+ my_errno=0;
+ error=heap_rkey(file,record,0,key);
+ if (verbose ||
+ (error == 0 && flags[i] != 1) ||
+ (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
+ {
+ printf("key: %s rkey: %3d my_errno: %3d record: %s\n",
+ key,error,my_errno,record+1);
+ }
+ }
+
+#ifdef OLD_HEAP_VERSION
+ {
+ int found;
+ printf("- Reading records with position\n");
+ for (i=1,found=0 ; i <= 30 ; i++)
+ {
+ my_errno=0;
+ if ((error=heap_rrnd(file,record,i == 1 ? 0L : (ulong) -1)) ==
+ HA_ERR_END_OF_FILE)
+ {
+ if (found != 25-deleted)
+ printf("Found only %d of %d records\n",found,25-deleted);
+ break;
+ }
+ if (!error)
+ found++;
+ if (verbose || (error != 0 && error != HA_ERR_RECORD_DELETED))
+ {
+ printf("pos: %2d ni_rrnd: %3d my_errno: %3d record: %s\n",
+ i-1,error,my_errno,record+1);
+ }
+ }
+ }
+#endif
+
+ if (heap_close(file) || heap_panic(HA_PANIC_CLOSE))
+ goto err;
+ my_end(MY_GIVE_INFO);
+ return(0);
+err:
+ printf("got error: %d when using heap-database\n",my_errno);
+ return(1);
+} /* main */
+
+
+/* Read options */
+
+static int get_options(int argc, char **argv)
+{
+ char *pos;
+
+ while (--argc >0 && *(pos = *(++argv)) == '-' ) {
+ switch(*++pos) {
+ case 'B': /* Big file */
+ flag=1;
+ break;
+ case 'v': /* verbose */
+ verbose=1;
+ break;
+ case 'm':
+ remove_ant=atoi(++pos);
+ break;
+ case 'V':
+ printf("hp_test1 Ver 3.0 \n");
+ exit(0);
+ case '#':
+ DBUG_PUSH (++pos);
+ break;
+ }
+ }
+ return 0;
+} /* get options */
diff --git a/heap/hp_test2.c b/heap/hp_test2.c
new file mode 100644
index 00000000000..179e2c7c399
--- /dev/null
+++ b/heap/hp_test2.c
@@ -0,0 +1,659 @@
+/* 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 "heapdef.h" /* Because of _hp_find_block */
+#include <signal.h>
+
+#define MAX_RECORDS 100000
+#define MAX_KEYS 3
+
+static int get_options(int argc, char *argv[]);
+static int rnd(int max_value);
+static sig_handler endprog(int sig_number);
+
+static uint flag=0,verbose=0,testflag=0,recant=10000,silent=0;
+static uint keys=MAX_KEYS;
+static uint16 key1[1001];
+static my_bool key3[MAX_RECORDS];
+
+static int calc_check(byte *buf,uint length);
+
+ /* Huvudprogrammet */
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ register uint i,j;
+ uint ant,n1,n2,n3;
+ uint reclength,write_count,update,delete,check2,dupp_keys,found_key;
+ int error;
+ ulong pos;
+ unsigned long key_check;
+ char record[128],record2[128],record3[128],key[10];
+ const char *filename,*filename2;
+ HP_INFO *file,*file2;
+ HP_KEYDEF keyinfo[MAX_KEYS];
+ HP_KEYSEG keyseg[MAX_KEYS*5];
+ HEAP_PTR position;
+ MY_INIT(argv[0]); /* init my_sys library & pthreads */
+
+ filename= "test2";
+ filename2= "test2_2";
+ file=file2=0;
+ get_options(argc,argv);
+ reclength=37;
+
+ write_count=update=delete=0;
+ key_check=0;
+
+ keyinfo[0].seg=keyseg;
+ keyinfo[0].keysegs=1;
+ keyinfo[0].flag= 0;
+ keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
+ keyinfo[0].seg[0].start=0;
+ keyinfo[0].seg[0].length=6;
+ keyinfo[1].seg=keyseg+1;
+ keyinfo[1].keysegs=2;
+ keyinfo[1].flag=0;
+ keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
+ keyinfo[1].seg[0].start=7;
+ keyinfo[1].seg[0].length=6;
+ keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT;
+ keyinfo[1].seg[1].start=0; /* Tv}delad nyckel */
+ keyinfo[1].seg[1].length=6;
+ keyinfo[2].seg=keyseg+3;
+ keyinfo[2].keysegs=1;
+ keyinfo[2].flag=HA_NOSAME;
+ keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
+ keyinfo[2].seg[0].start=12;
+ keyinfo[2].seg[0].length=8;
+
+ bzero((char*) key1,sizeof(key1));
+ bzero((char*) key3,sizeof(key3));
+
+ printf("- Creating heap-file\n");
+ if (heap_create(filename))
+ goto err;
+ if (!(file=heap_open(filename,2,keys,keyinfo,reclength,(ulong) flag*100000L,
+ (ulong) recant/2)))
+ goto err;
+ signal(SIGINT,endprog);
+
+ printf("- Writing records:s\n");
+ strmov(record," ..... key");
+
+ for (i=0 ; i < recant ; i++)
+ {
+ n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*5,MAX_RECORDS));
+ sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
+
+ if (heap_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)
+ {
+ printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
+ goto err;
+ }
+ write_count++; key1[n1]++; key3[n3]=1;
+ key_check+=n1;
+ }
+ if (testflag == 1 && heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+ }
+ if (testflag == 1)
+ goto end;
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+
+ printf("- Delete\n");
+ for (i=0 ; i < write_count/10 ; i++)
+ {
+ for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
+ if (j != 0)
+ {
+ sprintf(key,"%6d",j);
+ if (heap_rkey(file,record,0,key))
+ {
+ printf("can't find key1: \"%s\"\n",key);
+ goto err;
+ }
+#ifdef NOT_USED
+ if (file->current_ptr == _hp_find_block(&file->s->block,0) ||
+ file->current_ptr == _hp_find_block(&file->s->block,1))
+ continue; /* Don't remove 2 first records */
+#endif
+ if (heap_delete(file,record))
+ {
+ printf("error: %d; can't delete record: \"%s\"\n", my_errno,record);
+ goto err;
+ }
+ delete++;
+ key1[atoi(record+keyinfo[0].seg[0].start)]--;
+ key3[atoi(record+keyinfo[2].seg[0].start)]=0;
+ key_check-=atoi(record);
+ if (testflag == 2 && heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+ }
+ else
+ puts("Warning: Skipping delete test because no dupplicate keys");
+ }
+ if (testflag==2) goto end;
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+
+ printf("- Update\n");
+ for (i=0 ; i < write_count/10 ; i++)
+ {
+ n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*2,MAX_RECORDS));
+ sprintf(record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
+ if (rnd(2) == 1)
+ {
+ if (heap_scan_init(file))
+ goto err;
+ j=rnd(write_count-delete);
+ while ((error=heap_scan(file,record) == HA_ERR_RECORD_DELETED) ||
+ (!error && j))
+ {
+ if (!error)
+ j--;
+ }
+ if (error)
+ goto err;
+ }
+ else
+ {
+ for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
+ if (!key1[j])
+ continue;
+ sprintf(key,"%6d",j);
+ if (heap_rkey(file,record,0,key))
+ {
+ printf("can't find key1: \"%s\"\n",key);
+ goto err;
+ }
+ }
+ if (heap_update(file,record,record2))
+ {
+ if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
+ {
+ printf("error: %d; can't uppdate:\nFrom: \"%s\"\nTo: \"%s\"\n",
+ my_errno,record,record2);
+ goto err;
+ }
+ if (verbose)
+ printf("Double key when tryed to uppdate:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2);
+ }
+ else
+ {
+ key1[atoi(record+keyinfo[0].seg[0].start)]--;
+ key3[atoi(record+keyinfo[2].seg[0].start)]=0;
+ key1[n1]++; key3[n3]=1;
+ update++;
+ key_check=key_check-atoi(record)+n1;
+ }
+ if (testflag == 3 && heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+ }
+ if (testflag == 3) goto end;
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+
+ for (i=999, dupp_keys=found_key=0 ; i>0 ; i--)
+ {
+ if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; }
+ sprintf(key,"%6d",found_key);
+ }
+
+ if (dupp_keys > 3)
+ {
+ if (!silent)
+ printf("- Read first key - next - delete - next -> last\n");
+ DBUG_PRINT("progpos",("first - next - delete - next -> last"));
+
+ if (heap_rkey(file,record,0,key))
+ goto err;
+ if (heap_rnext(file,record3)) goto err;
+ if (heap_delete(file,record3)) goto err;
+ key_check-=atoi(record3);
+ key1[atoi(record+keyinfo[0].seg[0].start)]--;
+ key3[atoi(record+keyinfo[2].seg[0].start)]=0;
+ delete++;
+ ant=2;
+ while ((error=heap_rnext(file,record3)) == 0 ||
+ error == HA_ERR_RECORD_DELETED)
+ if (! error)
+ ant++;
+ if (ant != dupp_keys)
+ {
+ printf("next: I can only find: %d records of %d\n",
+ ant,dupp_keys);
+ goto end;
+ }
+ dupp_keys--;
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+
+ if (!silent)
+ printf("- Read last key - delete - prev - prev - delete - prev -> first\n");
+
+ if (heap_rlast(file,record3)) goto err;
+ if (heap_delete(file,record3)) goto err;
+ key_check-=atoi(record3);
+ key1[atoi(record+keyinfo[0].seg[0].start)]--;
+ key3[atoi(record+keyinfo[2].seg[0].start)]=0;
+ delete++;
+ if (heap_rprev(file,record3) || heap_rprev(file,record3))
+ goto err;
+ if (heap_delete(file,record3)) goto err;
+ key_check-=atoi(record3);
+ key1[atoi(record+keyinfo[0].seg[0].start)]--;
+ key3[atoi(record+keyinfo[2].seg[0].start)]=0;
+ delete++;
+ ant=3;
+ while ((error=heap_rprev(file,record3)) == 0 ||
+ error == HA_ERR_RECORD_DELETED)
+ {
+ if (! error)
+ ant++;
+ }
+ if (ant != dupp_keys)
+ {
+ printf("next: I can only find: %d records of %d\n",
+ ant,dupp_keys);
+ goto end;
+ }
+ dupp_keys-=2;
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+ }
+ else
+ puts("Warning: Not enough duplicated keys: Skipping delete key check");
+
+ if (!silent)
+ printf("- Read (first) - next - delete - next -> last\n");
+ DBUG_PRINT("progpos",("first - next - delete - next -> last"));
+
+ if (heap_scan_init(file))
+ goto err;
+ while ((error=heap_scan(file,record3) == HA_ERR_RECORD_DELETED)) ;
+ if (error)
+ goto err;
+ if (heap_delete(file,record3)) goto err;
+ key_check-=atoi(record3);
+ delete++;
+ key1[atoi(record+keyinfo[0].seg[0].start)]--;
+ key3[atoi(record+keyinfo[2].seg[0].start)]=0;
+ ant=0;
+ while ((error=heap_scan(file,record3)) == 0 ||
+ error == HA_ERR_RECORD_DELETED)
+ if (! error)
+ ant++;
+ if (ant != write_count-delete)
+ {
+ printf("next: Found: %d records of %d\n",ant,write_count-delete);
+ goto end;
+ }
+ if (heap_check_heap(file))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+
+ puts("- Test if: Read rrnd - same - rkey - same");
+ DBUG_PRINT("progpos",("Read rrnd - same"));
+ pos=rnd(write_count-delete-5)+5;
+ heap_scan_init(file);
+ i=5;
+ while ((error=heap_scan(file,record)) == HA_ERR_RECORD_DELETED ||
+ (error == 0 && pos))
+ {
+ if (!error)
+ pos--;
+ if (i-- == 0)
+ {
+ bmove(record3,record,reclength);
+ position=heap_position(file);
+ }
+ }
+ if (error)
+ goto err;
+ bmove(record2,record,reclength);
+ if (heap_rsame(file,record,-1) || heap_rsame(file,record2,2))
+ goto err;
+ if (bcmp(record2,record,reclength))
+ {
+ puts("heap_rsame didn't find right record");
+ goto end;
+ }
+
+ puts("- Test of read through position");
+ if (heap_rrnd(file,record,position))
+ goto err;
+ if (bcmp(record3,record,reclength))
+ {
+ puts("heap_frnd didn't find right record");
+ goto end;
+ }
+
+ printf("- heap_info\n");
+ {
+ HEAPINFO info;
+ heap_info(file,&info,0);
+ /* We have to test with delete +1 as this may be the case if the last
+ inserted row was a duplicate key */
+ if (info.records != write_count-delete ||
+ (info.deleted != delete && info.deleted != delete+1))
+ {
+ puts("Wrong info from heap_info");
+ printf("Got: records: %ld(%d) deleted: %ld(%d)\n",
+ info.records,write_count-delete,info.deleted,delete);
+ }
+ }
+
+#ifdef OLD_HEAP_VERSION
+ {
+ uint check;
+ printf("- Read through all records with rnd\n");
+ if (heap_extra(file,HA_EXTRA_RESET) || heap_extra(file,HA_EXTRA_CACHE))
+ {
+ puts("got error from heap_extra");
+ goto end;
+ }
+ ant=check=0;
+ while ((error=heap_rrnd(file,record,(ulong) -1)) != HA_ERR_END_OF_FILE &&
+ ant < write_count + 10)
+ {
+ if (!error)
+ {
+ ant++;
+ check+=calc_check(record,reclength);
+ }
+ }
+ if (ant != write_count-delete)
+ {
+ printf("rrnd: I can only find: %d records of %d\n", ant,
+ write_count-delete);
+ goto end;
+ }
+ if (heap_extra(file,HA_EXTRA_NO_CACHE))
+ {
+ puts("got error from heap_extra(HA_EXTRA_NO_CACHE)");
+ goto end;
+ }
+ }
+#endif
+
+ printf("- Read through all records with scan\n");
+ if (heap_extra(file,HA_EXTRA_RESET) || heap_extra(file,HA_EXTRA_CACHE))
+ {
+ puts("got error from heap_extra");
+ goto end;
+ }
+ ant=check2=0;
+ heap_scan_init(file);
+ while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE &&
+ ant < write_count + 10)
+ {
+ if (!error)
+ {
+ ant++;
+ check2+=calc_check(record,reclength);
+ }
+ }
+ if (ant != write_count-delete)
+ {
+ printf("scan: I can only find: %d records of %d\n", ant,
+ write_count-delete);
+ goto end;
+ }
+#ifdef OLD_HEAP_VERSION
+ if (check != check2)
+ {
+ puts("scan: Checksum didn't match reading with rrnd");
+ goto end;
+ }
+#endif
+
+
+ if (heap_extra(file,HA_EXTRA_NO_CACHE))
+ {
+ puts("got error from heap_extra(HA_EXTRA_NO_CACHE)");
+ goto end;
+ }
+
+ for (i=999, dupp_keys=found_key=0 ; i>0 ; i--)
+ {
+ if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; }
+ sprintf(key,"%6d",found_key);
+ }
+ printf("- Read through all keys with first-next-last-prev\n");
+ ant=0;
+ for (error=heap_rkey(file,record,0,key) ;
+ ! error ;
+ error=heap_rnext(file,record))
+ ant++;
+ if (ant != dupp_keys)
+ {
+ printf("first-next: I can only find: %d records of %d\n", ant,
+ dupp_keys);
+ goto end;
+ }
+
+ ant=0;
+ for (error=heap_rlast(file,record) ;
+ ! error ;
+ error=heap_rprev(file,record))
+ {
+ ant++;
+ check2+=calc_check(record,reclength);
+ }
+ if (ant != dupp_keys)
+ {
+ printf("last-prev: I can only find: %d records of %d\n", ant,
+ dupp_keys);
+ goto end;
+ }
+
+ if (testflag == 4) goto end;
+
+ printf("- Reading through all rows through keys\n");
+ if (!(file2=heap_open(filename,2,0,0,0,0,0)))
+ goto err;
+ if (heap_scan_init(file))
+ goto err;
+ while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE)
+ {
+ if (error == 0)
+ {
+ if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start))
+ {
+ printf("can't find key3: \"%.8s\"\n",
+ record+keyinfo[2].seg[0].start);
+ goto err;
+ }
+ }
+ }
+ heap_close(file2);
+
+ printf("- Creating output heap-file 2\n");
+ if (!(file2=heap_open(filename2,2,1,keyinfo,reclength,0L,0L)))
+ goto err;
+
+ printf("- Copying and removing records\n");
+ if (heap_scan_init(file))
+ goto err;
+ while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE)
+ {
+ if (error == 0)
+ {
+ if (heap_write(file2,record))
+ goto err;
+ key_check-=atoi(record);
+ write_count++;
+ if (heap_delete(file,record))
+ goto err;
+ delete++;
+ }
+ pos++;
+ }
+ if (heap_check_heap(file) || heap_check_heap(file2))
+ {
+ puts("Heap keys crashed");
+ goto err;
+ }
+
+ if (my_errno != HA_ERR_END_OF_FILE)
+ printf("error: %d from heap_rrnd\n",my_errno);
+ if (key_check)
+ printf("error: Some read got wrong: check is %ld\n",(long) key_check);
+
+end:
+ printf("\nFollowing test have been made:\n");
+ printf("Write records: %d\nUpdate records: %d\nDelete records: %d\n", write_count,update,delete);
+ heap_clear(file);
+ if (heap_close(file) || (file2 && heap_close(file2)))
+ goto err;
+ heap_delete_all(filename2);
+ heap_panic(HA_PANIC_CLOSE);
+ my_end(MY_GIVE_INFO);
+ return(0);
+err:
+ printf("Got error: %d when using heap-database\n",my_errno);
+ VOID(heap_close(file));
+ return(1);
+} /* main */
+
+
+ /* Read options */
+
+static int get_options(int argc,char *argv[])
+{
+ char *pos,*progname;
+ DEBUGGER_OFF;
+
+ progname= argv[0];
+
+ while (--argc >0 && *(pos = *(++argv)) == '-' ) {
+ switch(*++pos) {
+ case 'B': /* Big file */
+ flag=1;
+ break;
+ case 'v': /* verbose */
+ verbose=1;
+ break;
+ case 'm': /* records */
+ recant=atoi(++pos);
+ break;
+ case 's':
+ silent=1;
+ break;
+ case 't':
+ testflag=atoi(++pos); /* testmod */
+ break;
+ case 'V':
+ case 'I':
+ case '?':
+ printf("%s Ver 1.1 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
+ puts("TCX Datakonsult AB, by Monty, for your professional use\n");
+ printf("Usage: %s [-?ABIKLsWv] [-m#] [-t#]\n",progname);
+ exit(0);
+ case '#':
+ DEBUGGER_ON;
+ DBUG_PUSH (++pos);
+ break;
+ }
+ }
+ return 0;
+} /* get options */
+
+ /* Generate a random value in intervall 0 <=x <= n */
+
+static int rnd(max_value)
+int max_value;
+{
+ return (int) ((rand() & 32767)/32767.0*max_value);
+} /* rnd */
+
+
+static sig_handler endprog(int sig_number __attribute__((unused)))
+{
+#ifndef THREAD
+ if (my_dont_interrupt)
+ my_remember_signal(sig_number,endprog);
+ else
+#endif
+ {
+ heap_panic(HA_PANIC_CLOSE);
+ my_end(1);
+ exit(1);
+ }
+}
+
+static int calc_check(buf,length)
+byte *buf;
+uint length;
+{
+ int check=0;
+ while (length--)
+ check+= (int) (uchar) *(buf++);
+ return check;
+}
diff --git a/heap/hp_update.c b/heap/hp_update.c
new file mode 100644
index 00000000000..5eb4562ca5c
--- /dev/null
+++ b/heap/hp_update.c
@@ -0,0 +1,67 @@
+/* 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 */
+
+/* Update current record in heap-database */
+
+#include "heapdef.h"
+
+int heap_update(HP_INFO *info, const byte *old, const byte *new)
+{
+ uint key;
+ byte *pos;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_update");
+
+ test_active(info);
+ pos=info->current_ptr;
+
+ if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,old))
+ DBUG_RETURN(my_errno); /* Record changed */
+ if (--(share->records) < share->blength >> 1) share->blength>>= 1;
+ share->changed=1;
+
+ for (key=0 ; key < share->keys ; key++)
+ {
+ if (_hp_rec_key_cmp(share->keydef+key,old,new))
+ {
+ if (_hp_delete_key(info,share->keydef+key,old,pos,key ==
+ (uint) info->lastinx) ||
+ _hp_write_key(share,share->keydef+key,new,pos))
+ goto err;
+ }
+ }
+
+ memcpy(pos,new,(size_t) share->reclength);
+ if (++(share->records) == share->blength) share->blength+= share->blength;
+ DBUG_RETURN(0);
+
+ err:
+ if (my_errno == HA_ERR_FOUND_DUPP_KEY)
+ {
+ info->errkey=key;
+ do
+ {
+ if (_hp_rec_key_cmp(share->keydef+key,old,new))
+ {
+ if (_hp_delete_key(info,share->keydef+key,new,pos,0) ||
+ _hp_write_key(share,share->keydef+key,old,pos))
+ break;
+ }
+ } while (key-- > 0);
+ }
+ if (++(share->records) == share->blength) share->blength+= share->blength;
+ DBUG_RETURN(my_errno);
+} /* heap_update */
diff --git a/heap/hp_write.c b/heap/hp_write.c
new file mode 100644
index 00000000000..e74183276f7
--- /dev/null
+++ b/heap/hp_write.c
@@ -0,0 +1,275 @@
+/* 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 a record to heap-databas */
+
+#include "heapdef.h"
+#ifdef __WIN__
+#include <fcntl.h>
+#endif
+
+#define LOWFIND 1
+#define LOWUSED 2
+#define HIGHFIND 4
+#define HIGHUSED 8
+
+static byte *next_free_record_pos(HP_SHARE *info);
+static HASH_INFO *_hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
+ ulong records);
+
+int heap_write(HP_INFO *info, const byte *record)
+{
+ uint key;
+ byte *pos;
+ HP_SHARE *share=info->s;
+ DBUG_ENTER("heap_write");
+
+#ifndef DBUG_OFF
+ if (info->mode && O_RDONLY)
+ {
+ DBUG_RETURN(my_errno=EACCES);
+ }
+#endif
+ if (!(pos=next_free_record_pos(share)))
+ DBUG_RETURN(my_errno);
+ share->changed=1;
+
+ for (key=0 ; key < share->keys ; key++)
+ {
+ if (_hp_write_key(share,share->keydef+key,record,pos))
+ goto err;
+ }
+
+ memcpy(pos,record,(size_t) share->reclength);
+ pos[share->reclength]=1; /* Mark record as not deleted */
+ if (++share->records == share->blength)
+ share->blength+= share->blength;
+ info->current_ptr=pos;
+ info->current_hash_ptr=0;
+ info->update|=HA_STATE_AKTIV;
+ DBUG_RETURN(0);
+err:
+ info->errkey= key;
+ do
+ {
+ if (_hp_delete_key(info,share->keydef+key,record,pos,0))
+ break;
+ } while (key-- > 0);
+
+ share->deleted++;
+ *((byte**) pos)=share->del_link;
+ share->del_link=pos;
+ pos[share->reclength]=0; /* Record deleted */
+ DBUG_RETURN(my_errno);
+} /* heap_write */
+
+
+ /* Find where to place new record */
+
+static byte *next_free_record_pos(HP_SHARE *info)
+{
+ int block_pos;
+ byte *pos;
+ ulong length;
+ DBUG_ENTER("next_free_record_pos");
+
+ if (info->del_link)
+ {
+ pos=info->del_link;
+ info->del_link= *((byte**) pos);
+ info->deleted--;
+ DBUG_PRINT("exit",("Used old position: %lx",pos));
+ DBUG_RETURN(pos);
+ }
+ if (!(block_pos=(info->records % info->block.records_in_block)))
+ {
+ if (info->records > info->max_records && info->max_records)
+ {
+ my_errno=HA_ERR_RECORD_FILE_FULL;
+ DBUG_RETURN(NULL);
+ }
+ if (_hp_get_new_block(&info->block,&length))
+ DBUG_RETURN(NULL);
+ info->data_length+=length;
+ }
+ DBUG_PRINT("exit",("Used new position: %lx",
+ (byte*) info->block.level_info[0].last_blocks+block_pos*
+ info->block.recbuffer));
+ DBUG_RETURN((byte*) info->block.level_info[0].last_blocks+
+ block_pos*info->block.recbuffer);
+}
+
+
+ /* Write a hash-key to the hash-index */
+
+int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
+ const byte *record, byte *recpos)
+{
+ int flag;
+ ulong halfbuff,hashnr,first_index;
+ byte *ptr_to_rec,*ptr_to_rec2;
+ HASH_INFO *empty,*gpos,*gpos2,*pos;
+ DBUG_ENTER("hp_write_key");
+
+ LINT_INIT(gpos); LINT_INIT(gpos2);
+ LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
+
+ flag=0;
+ if (!(empty= _hp_find_free_hash(info,&keyinfo->block,info->records)))
+ DBUG_RETURN(-1); /* No more memory */
+ halfbuff= (long) info->blength >> 1;
+ pos= hp_find_hash(&keyinfo->block,(first_index=info->records-halfbuff));
+
+ if (pos != empty) /* If some records */
+ {
+ do
+ {
+ hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
+ if (flag == 0) /* First loop; Check if ok */
+ if (_hp_mask(hashnr,info->blength,info->records) != first_index)
+ break;
+ if (!(hashnr & halfbuff))
+ { /* Key will not move */
+ if (!(flag & LOWFIND))
+ {
+ if (flag & HIGHFIND)
+ {
+ flag=LOWFIND | HIGHFIND;
+ /* key shall be moved to the current empty position */
+ gpos=empty;
+ ptr_to_rec=pos->ptr_to_rec;
+ empty=pos; /* This place is now free */
+ }
+ else
+ {
+ flag=LOWFIND | LOWUSED; /* key isn't changed */
+ gpos=pos;
+ ptr_to_rec=pos->ptr_to_rec;
+ }
+ }
+ else
+ {
+ if (!(flag & LOWUSED))
+ {
+ /* Change link of previous LOW-key */
+ gpos->ptr_to_rec=ptr_to_rec;
+ gpos->next_key=pos;
+ flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED);
+ }
+ gpos=pos;
+ ptr_to_rec=pos->ptr_to_rec;
+ }
+ }
+ else
+ { /* key will be moved */
+ if (!(flag & HIGHFIND))
+ {
+ flag= (flag & LOWFIND) | HIGHFIND;
+ /* key shall be moved to the last (empty) position */
+ gpos2 = empty; empty=pos;
+ ptr_to_rec2=pos->ptr_to_rec;
+ }
+ else
+ {
+ if (!(flag & HIGHUSED))
+ {
+ /* Change link of previous hash-key and save */
+ gpos2->ptr_to_rec=ptr_to_rec2;
+ gpos2->next_key=pos;
+ flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED);
+ }
+ gpos2=pos;
+ ptr_to_rec2=pos->ptr_to_rec;
+ }
+ }
+ }
+ while ((pos=pos->next_key));
+
+ if ((flag & (LOWFIND | LOWUSED)) == LOWFIND)
+ {
+ gpos->ptr_to_rec=ptr_to_rec;
+ gpos->next_key=0;
+ }
+ if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND)
+ {
+ gpos2->ptr_to_rec=ptr_to_rec2;
+ gpos2->next_key=0;
+ }
+ }
+ /* Check if we are at the empty position */
+
+ pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_rec_hashnr(keyinfo,record),
+ info->blength,info->records+1));
+ if (pos == empty)
+ {
+ pos->ptr_to_rec=recpos;
+ pos->next_key=0;
+ }
+ else
+ {
+ /* Check if more records in same hash-nr family */
+ empty[0]=pos[0];
+ gpos=hp_find_hash(&keyinfo->block,
+ _hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
+ info->blength,info->records+1));
+ if (pos == gpos)
+ {
+ pos->ptr_to_rec=recpos;
+ pos->next_key=empty;
+ }
+ else
+ {
+ pos->ptr_to_rec=recpos;
+ pos->next_key=0;
+ _hp_movelink(pos,gpos,empty);
+ }
+
+ /* Check if dupplicated keys */
+ if ((keyinfo->flag & HA_NOSAME) && pos == gpos)
+ {
+ pos=empty;
+ do
+ {
+ if (! _hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
+ {
+ DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
+ }
+ } while ((pos=pos->next_key));
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+ /* Returns ptr to block, and allocates block if neaded */
+
+static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
+ HP_BLOCK *block, ulong records)
+{
+ uint block_pos;
+ ulong length;
+
+ if (records < block->last_allocated)
+ return hp_find_hash(block,records);
+ if (!(block_pos=(records % block->records_in_block)))
+ {
+ if (_hp_get_new_block(block,&length))
+ return(NULL);
+ info->index_length+=length;
+ }
+ block->last_allocated=records+1;
+ return((HASH_INFO*) ((byte*) block->level_info[0].last_blocks+
+ block_pos*block->recbuffer));
+}
diff --git a/heap/make-ccc b/heap/make-ccc
new file mode 100755
index 00000000000..192647298ad
--- /dev/null
+++ b/heap/make-ccc
@@ -0,0 +1,4 @@
+ccc -I./../include -I../include -DDBUG_OFF -fast -O3 -c _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create.c hp_delete.c hp_extra.c hp_hash.c hp_info.c hp_open.c hp_panic.c hp_rename.c hp_rfirst.c hp_rkey.c hp_rlast.c hp_rnext.c hp_rprev.c hp_rrnd.c hp_rsame.c hp_scan.c hp_static.c hp_update.c hp_write.c
+rm libheap.a
+ar -cr libheap.a _check.o
+