mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 21:12:26 +01:00
3b43cb2960
_mi_compare_text -> mi_compate_text Changes according Monty's suggestions
215 lines
6.6 KiB
C
215 lines
6.6 KiB
C
/* 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
|
|
|
|
#include "my_sys.h"
|
|
|
|
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
|
|
{
|
|
uint not_used;
|
|
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
|
|
param->search_flag, ¬_used);
|
|
}
|
|
|
|
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;
|
|
HA_KEYSEG *keyseg;
|
|
|
|
DBUG_ENTER("heap_open");
|
|
|
|
pthread_mutex_lock(&THR_LOCK_heap);
|
|
if (!(share = hp_find_named_heap(name)))
|
|
{
|
|
DBUG_PRINT("info",("Initializing new table"));
|
|
for (i=key_segs=max_length=0 ; i < keys ; i++)
|
|
{
|
|
key_segs+= keydef[i].keysegs;
|
|
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
|
|
key_segs++;
|
|
bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
|
|
bzero((char*) &keydef[i].rb_tree ,sizeof(keydef[i].rb_tree));
|
|
for (j=length=0 ; j < keydef[i].keysegs; j++)
|
|
{
|
|
length+=keydef[i].seg[j].length;
|
|
if (keydef[i].seg[j].null_bit)
|
|
{
|
|
if (!(keydef[i].flag & HA_NULL_ARE_EQUAL))
|
|
keydef[i].flag |= HA_NULL_PART_KEY;
|
|
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
|
|
keydef[i].rb_tree.size_of_element++;
|
|
}
|
|
}
|
|
keydef[i].length= length;
|
|
length+= keydef[i].rb_tree.size_of_element +
|
|
((keydef[i].algorithm == HA_KEY_ALG_BTREE) ? sizeof(byte*) : 0);
|
|
if (length > max_length)
|
|
max_length= length;
|
|
}
|
|
if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
|
|
keys*sizeof(HP_KEYDEF)+
|
|
key_segs*sizeof(HA_KEYSEG),
|
|
MYF(MY_ZEROFILL))))
|
|
{
|
|
pthread_mutex_unlock(&THR_LOCK_heap);
|
|
DBUG_RETURN(0);
|
|
}
|
|
share->keydef= (HP_KEYDEF*) (share + 1);
|
|
keyseg= (HA_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++)
|
|
{
|
|
HP_KEYDEF *keyinfo= share->keydef + i;
|
|
uint nsegs= keydef[i].keysegs;
|
|
|
|
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
|
|
{
|
|
init_tree(&keyinfo->rb_tree, 0, 0, 0, (qsort_cmp2)keys_compare, 1,
|
|
NULL, NULL);
|
|
keyinfo->delete_key= hp_rb_delete_key;
|
|
keyinfo->write_key= hp_rb_write_key;
|
|
nsegs++;
|
|
}
|
|
else
|
|
{
|
|
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
|
|
max_records);
|
|
keyinfo->delete_key= hp_delete_key;
|
|
keyinfo->write_key= hp_write_key;
|
|
}
|
|
keyinfo->seg= keyseg;
|
|
memcpy(keyseg, keydef[i].seg,
|
|
(size_t) (sizeof(keyseg[0]) * nsegs));
|
|
keyseg+= nsegs;
|
|
}
|
|
|
|
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,MY_MUTEX_INIT_FAST));
|
|
#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)+
|
|
2 * 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->recbuf= (byte*) (info->lastkey + share->max_key_length);
|
|
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);
|
|
}
|