summaryrefslogtreecommitdiff
path: root/storage/maria/ma_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/maria/ma_write.c')
-rw-r--r--storage/maria/ma_write.c232
1 files changed, 136 insertions, 96 deletions
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index c62b168d008..12f29c8ee1d 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -30,9 +30,9 @@ static int w_search(MARIA_HA *info,MARIA_KEYDEF *keyinfo,
static int _ma_balance_page(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *key,
uchar *curr_buff,uchar *father_buff,
uchar *father_keypos,my_off_t father_page);
-static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page,
- uchar *key, uint *return_key_length,
- uchar **after_key);
+static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
+ uchar *page, uchar *key,
+ uint *return_key_length, uchar **after_key);
int _ma_ck_write_tree(register MARIA_HA *info, uint keynr,uchar *key,
uint key_length);
int _ma_ck_write_btree(register MARIA_HA *info, uint keynr,uchar *key,
@@ -115,7 +115,7 @@ int maria_write(MARIA_HA *info, uchar *record)
*/
if ((filepos= (*share->write_record_init)(info, record)) ==
HA_OFFSET_ERROR)
- goto err2;
+ goto err2;
}
/* Write all keys to indextree */
@@ -277,6 +277,7 @@ err:
my_errno=save_errno;
err2:
save_errno=my_errno;
+ DBUG_ASSERT(save_errno);
DBUG_PRINT("error", ("got error: %d", save_errno));
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */
@@ -294,10 +295,7 @@ int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
{
DBUG_RETURN(_ma_ck_write_tree(info, keynr, key, key_length));
}
- else
- {
- DBUG_RETURN(_ma_ck_write_btree(info, keynr, key, key_length));
- }
+ DBUG_RETURN(_ma_ck_write_btree(info, keynr, key, key_length));
} /* _ma_ck_write */
@@ -366,12 +364,18 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key,
DBUG_ENTER("_ma_enlarge_root");
nod_flag= (*root != HA_OFFSET_ERROR) ? share->base.key_reflength : 0;
- _ma_kpointer(info,info->buff+2,*root); /* if nod */
+ /* Store pointer to prev page if nod */
+ _ma_kpointer(info, info->buff + info->s->keypage_header, *root);
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar*) 0,
(uchar*) 0, (uchar*) 0, key,&s_temp);
- maria_putint(info->buff,t_length+2+nod_flag,nod_flag);
- (*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp);
- info->keyread_buff_used=info->page_changed=1; /* info->buff is used */
+
+ _ma_store_keynr(info, info->buff, (keyinfo - info->s->keyinfo));
+ _ma_store_page_used(info, info->buff, info->s->keypage_header +
+ t_length + nod_flag, nod_flag);
+ (*keyinfo->store_key)(keyinfo, info->buff + info->s->keypage_header +
+ nod_flag, &s_temp);
+ /* Mark that info->buff was used */
+ info->keyread_buff_used= info->page_changed= 1;
if ((*root= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
_ma_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff))
DBUG_RETURN(-1);
@@ -379,12 +383,14 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key,
} /* _ma_enlarge_root */
- /*
- Search after a position for a key and store it there
- Returns -1 = error
- 0 = ok
- 1 = key should be stored in higher tree
- */
+/*
+ Search after a position for a key and store it there
+
+ @return
+ @retval -1 error
+ @retval 0 ok
+ @retval 1 key should be stored in higher tree
+*/
static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
uint comp_flag, uchar *key, uint key_length, my_off_t page,
@@ -409,7 +415,7 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length,
comp_flag, &keypos, keybuff, &was_last_key);
- nod_flag= _ma_test_if_nod(temp_buff);
+ nod_flag= _ma_test_if_nod(info, temp_buff);
if (flag == 0)
{
uint tmp_key_length;
@@ -442,7 +448,8 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
keyinfo=&info->s->ft2_keyinfo;
get_key_full_length_rdonly(off, key);
key+=off;
- keypos-=keyinfo->keylength+nod_flag; /* we'll modify key entry 'in vivo' */
+ /* we'll modify key entry 'in vivo' */
+ keypos-= keyinfo->keylength + nod_flag;
error= _ma_ck_real_write_btree(info, keyinfo, key, 0,
&root, comp_flag);
_ma_dpointer(info, keypos+HA_FT_WLEN, root);
@@ -525,17 +532,17 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,
USE_WHOLE_KEY););
- nod_flag=_ma_test_if_nod(anc_buff);
- a_length= maria_data_on_page(anc_buff);
+ _ma_get_used_and_nod(info, anc_buff, a_length, nod_flag);
endpos= anc_buff+ a_length;
- prev_key=(key_pos == anc_buff+2+nod_flag ? (uchar*) 0 : key_buff);
+ prev_key= (key_pos == anc_buff + info->s->keypage_header + nod_flag ?
+ (uchar*) 0 : key_buff);
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
(key_pos == endpos ? (uchar*) 0 : key_pos),
prev_key, prev_key,
key,&s_temp);
#ifndef DBUG_OFF
- if (key_pos != anc_buff+2+nod_flag && (keyinfo->flag &
- (HA_BINARY_PACK_KEY | HA_PACK_KEY)))
+ if (key_pos != anc_buff + info->s->keypage_header + nod_flag &&
+ (keyinfo->flag & (HA_BINARY_PACK_KEY | HA_PACK_KEY)))
{
DBUG_DUMP("prev_key",(uchar*) key_buff, _ma_keylength(keyinfo,key_buff));
}
@@ -569,11 +576,11 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
(*keyinfo->store_key)(keyinfo,key_pos,&s_temp);
a_length+=t_length;
- maria_putint(anc_buff,a_length,nod_flag);
- if (a_length <= keyinfo->block_length)
+ _ma_store_page_used(info, anc_buff, a_length, nod_flag);
+ if (a_length <= (uint) keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)
{
- if (keyinfo->block_length - a_length < 32 &&
- keyinfo->flag & HA_FULLTEXT && key_pos == endpos &&
+ if (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE - a_length < 32 &&
+ (keyinfo->flag & HA_FULLTEXT) && key_pos == endpos &&
info->s->base.key_reflength <= info->s->base.rec_reflength &&
info->s->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
{
@@ -582,7 +589,7 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
Let's consider converting.
We'll compare 'key' and the first key at anc_buff
*/
- uchar *a=key, *b=anc_buff+2+nod_flag;
+ uchar *a= key, *b= anc_buff + info->s->keypage_header + nod_flag;
uint alen, blen, ft2len=info->s->ft2_keyinfo.keylength;
/* the very first key on the page is always unpacked */
DBUG_ASSERT((*b & 128) == 0);
@@ -597,25 +604,28 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
ha_compare_text(keyinfo->seg->charset, (uchar*) a, alen,
(uchar*) b, blen, 0, 0) == 0)
{
- /* yup. converting */
+ /* Yup. converting */
info->ft1_to_ft2=(DYNAMIC_ARRAY *)
my_malloc(sizeof(DYNAMIC_ARRAY), MYF(MY_WME));
my_init_dynamic_array(info->ft1_to_ft2, ft2len, 300, 50);
/*
- now, adding all keys from the page to dynarray
+ Now, adding all keys from the page to dynarray
if the page is a leaf (if not keys will be deleted later)
*/
if (!nod_flag)
{
- /* let's leave the first key on the page, though, because
- we cannot easily dispatch an empty page here */
+ /*
+ Let's leave the first key on the page, though, because
+ we cannot easily dispatch an empty page here
+ */
b+=blen+ft2len+2;
for (a=anc_buff+a_length ; b < a ; b+=ft2len+2)
insert_dynamic(info->ft1_to_ft2, b);
/* fixing the page's length - it contains only one key now */
- maria_putint(anc_buff,2+blen+ft2len+2,0);
+ _ma_store_page_used(info, anc_buff, info->s->keypage_header + blen +
+ ft2len + 2, 0);
}
/* the rest will be done when we're back from recursion */
}
@@ -645,31 +655,33 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
MARIA_KEY_PARAM s_temp;
DBUG_ENTER("maria_split_page");
LINT_INIT(after_key);
- DBUG_DUMP("buff",(uchar*) buff,maria_data_on_page(buff));
+ DBUG_DUMP("buff", buff, _ma_get_page_used(info, buff));
if (info->s->keyinfo+info->lastinx == keyinfo)
info->page_changed=1; /* Info->buff is used */
info->keyread_buff_used=1;
- nod_flag=_ma_test_if_nod(buff);
- key_ref_length=2+nod_flag;
+ nod_flag=_ma_test_if_nod(info, buff);
+ key_ref_length= info->s->keypage_header + nod_flag;
if (insert_last_key)
- key_pos= _ma_find_last_pos(keyinfo,buff,key_buff, &key_length, &after_key);
+ key_pos= _ma_find_last_pos(info, keyinfo, buff, key_buff, &key_length,
+ &after_key);
else
- key_pos= _ma_find_half_pos(nod_flag,keyinfo,buff,key_buff, &key_length,
- &after_key);
+ key_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, key_buff,
+ &key_length, &after_key);
if (!key_pos)
DBUG_RETURN(-1);
length=(uint) (key_pos-buff);
- a_length= maria_data_on_page(buff);
- maria_putint(buff,length,nod_flag);
+ a_length= _ma_get_page_used(info, buff);
+ _ma_store_page_used(info, buff, length, nod_flag);
key_pos=after_key;
if (nod_flag)
{
DBUG_PRINT("test",("Splitting nod"));
pos=key_pos-nod_flag;
- memcpy((uchar*) info->buff+2,(uchar*) pos,(size_t) nod_flag);
+ memcpy((uchar*) info->buff + info->s->keypage_header, (uchar*) pos,
+ (size_t) nod_flag);
}
/* Move middle item to key and pointer to new page */
@@ -688,8 +700,14 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
memcpy((uchar*) info->buff+key_ref_length+t_length,(uchar*) key_pos,
(size_t) length);
(*keyinfo->store_key)(keyinfo,info->buff+key_ref_length,&s_temp);
- maria_putint(info->buff,length+t_length+key_ref_length,nod_flag);
-
+ _ma_store_page_used(info, info->buff, length + t_length + key_ref_length,
+ nod_flag);
+
+ /* Copy key number */
+ info->buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
+ KEYPAGE_FLAG_SIZE]=
+ buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
+ KEYPAGE_FLAG_SIZE];
if (_ma_write_keypage(info,keyinfo,new_pos,DFLT_INIT_HITS,info->buff))
DBUG_RETURN(-1);
DBUG_DUMP("key",(uchar*) key, _ma_keylength(keyinfo,key));
@@ -697,25 +715,26 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} /* _ma_split_page */
- /*
- Calculate how to much to move to split a page in two
- Returns pointer to start of key.
- key will contain the key.
- return_key_length will contain the length of key
- after_key will contain the position to where the next key starts
- */
+/*
+ Calculate how to much to move to split a page in two
+
+ Returns pointer to start of key.
+ key will contain the key.
+ return_key_length will contain the length of key
+ after_key will contain the position to where the next key starts
+*/
-uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, uchar *page,
- uchar *key, uint *return_key_length,
+uchar *_ma_find_half_pos(MARIA_HA *info, uint nod_flag, MARIA_KEYDEF *keyinfo,
+ uchar *page, uchar *key, uint *return_key_length,
uchar **after_key)
{
uint keys,length,key_ref_length;
uchar *end,*lastpos;
DBUG_ENTER("_ma_find_half_pos");
- key_ref_length=2+nod_flag;
- length= maria_data_on_page(page)-key_ref_length;
- page+=key_ref_length;
+ key_ref_length= info->s->keypage_header + nod_flag;
+ length= _ma_get_page_used(info, page) - key_ref_length;
+ page+= key_ref_length; /* Point to first key */
if (!(keyinfo->flag &
(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
HA_BINARY_PACK_KEY)))
@@ -751,7 +770,8 @@ uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, uchar *page,
key will contain the last key
*/
-static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page,
+static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
+ uchar *page,
uchar *key, uint *return_key_length,
uchar **after_key)
{
@@ -760,8 +780,8 @@ static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page,
uchar key_buff[HA_MAX_KEY_BUFF];
DBUG_ENTER("_ma_find_last_pos");
- key_ref_length=2;
- length= maria_data_on_page(page)-key_ref_length;
+ key_ref_length= info->s->keypage_header;
+ length= _ma_get_page_used(info, page) - key_ref_length;
page+=key_ref_length;
if (!(keyinfo->flag &
(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
@@ -818,15 +838,16 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
DBUG_ENTER("_ma_balance_page");
k_length=keyinfo->keylength;
- father_length= maria_data_on_page(father_buff);
- father_keylength=k_length+info->s->base.key_reflength;
- nod_flag=_ma_test_if_nod(curr_buff);
+ father_length= _ma_get_page_used(info, father_buff);
+ father_keylength= k_length + info->s->base.key_reflength;
+ nod_flag=_ma_test_if_nod(info, curr_buff);
curr_keylength=k_length+nod_flag;
info->page_changed=1;
if ((father_key_pos != father_buff+father_length &&
(info->state->records & 1)) ||
- father_key_pos == father_buff+2+info->s->base.key_reflength)
+ father_key_pos == father_buff+ info->s->keypage_header +
+ info->s->base.key_reflength)
{
right=1;
next_page= _ma_kpos(info->s->base.key_reflength,
@@ -846,42 +867,46 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
if (!_ma_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0))
goto err;
- DBUG_DUMP("next",(uchar*) info->buff,maria_data_on_page(info->buff));
+ DBUG_DUMP("next", info->buff, _ma_get_page_used(info, info->buff));
/* Test if there is room to share keys */
- left_length= maria_data_on_page(curr_buff);
- right_length= maria_data_on_page(buff);
- keys=(left_length+right_length-4-nod_flag*2)/curr_keylength;
+ left_length= _ma_get_page_used(info, curr_buff);
+ right_length= _ma_get_page_used(info, buff);
+ keys= ((left_length+right_length-info->s->keypage_header*2-nod_flag*2)/
+ curr_keylength);
if ((right ? right_length : left_length) + curr_keylength <=
- keyinfo->block_length)
+ (uint) keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)
{ /* Merge buffs */
- new_left_length=2+nod_flag+(keys/2)*curr_keylength;
- new_right_length=2+nod_flag+((keys+1)/2)*curr_keylength;
- maria_putint(curr_buff,new_left_length,nod_flag);
- maria_putint(buff,new_right_length,nod_flag);
+ new_left_length= info->s->keypage_header+nod_flag+(keys/2)*curr_keylength;
+ new_right_length=info->s->keypage_header+nod_flag+(((keys+1)/2)*
+ curr_keylength);
+ _ma_store_page_used(info, curr_buff,new_left_length,nod_flag);
+ _ma_store_page_used(info, buff,new_right_length,nod_flag);
if (left_length < new_left_length)
{ /* Move keys buff -> leaf */
pos=curr_buff+left_length;
- memcpy((uchar*) pos,(uchar*) father_key_pos, (size_t) k_length);
- memcpy((uchar*) pos+k_length, (uchar*) buff+2,
+ memcpy(pos,father_key_pos, (size_t) k_length);
+ memcpy(pos+k_length, buff + info->s->keypage_header,
(size_t) (length=new_left_length - left_length - k_length));
- pos=buff+2+length;
- memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length);
- bmove((uchar*) buff+2,(uchar*) pos+k_length,new_right_length);
+ pos= buff + info->s->keypage_header + length;
+ memcpy(father_key_pos, pos, (size_t) k_length);
+ bmove(buff + info->s->keypage_header, pos + k_length, new_right_length);
}
else
{ /* Move keys -> buff */
- bmove_upp((uchar*) buff+new_right_length,(uchar*) buff+right_length,
- right_length-2);
+ bmove_upp(buff + new_right_length, buff + right_length,
+ right_length - info->s->keypage_header);
length=new_right_length-right_length-k_length;
- memcpy((uchar*) buff+2+length,father_key_pos,(size_t) k_length);
+ memcpy(buff + info->s->keypage_header + length, father_key_pos,
+ (size_t) k_length);
pos=curr_buff+new_left_length;
- memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length);
- memcpy((uchar*) buff+2,(uchar*) pos+k_length,(size_t) length);
+ memcpy(father_key_pos, pos, (size_t) k_length);
+ memcpy(buff + info->s->keypage_header, pos+k_length,
+ (size_t) length);
}
if (_ma_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff) ||
@@ -893,7 +918,13 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/* curr_buff[] and buff[] are full, lets split and make new nod */
extra_buff=info->buff+info->s->base.max_key_block_length;
- new_left_length=new_right_length=2+nod_flag+(keys+1)/3*curr_keylength;
+ new_left_length= new_right_length= (info->s->keypage_header + nod_flag +
+ (keys+1) / 3 * curr_keylength);
+ /*
+ 5 is the minum number of keys we can have here. This comes from
+ the fact that each full page can store at least 2 keys and in this case
+ we have a 'split' key, ie 2+2+1 = 5
+ */
if (keys == 5) /* Too few keys to balance */
new_left_length-=curr_keylength;
extra_length=nod_flag+left_length+right_length-
@@ -902,28 +933,37 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
left_length, right_length,
new_left_length, new_right_length,
extra_length));
- maria_putint(curr_buff,new_left_length,nod_flag);
- maria_putint(buff,new_right_length,nod_flag);
- maria_putint(extra_buff,extra_length+2,nod_flag);
+ _ma_store_page_used(info, curr_buff,new_left_length,nod_flag);
+ _ma_store_page_used(info, buff,new_right_length,nod_flag);
+ /* Copy key number */
+ bzero(extra_buff, info->s->keypage_header);
+ extra_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
+ KEYPAGE_FLAG_SIZE]=
+ buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
+ KEYPAGE_FLAG_SIZE];
+ _ma_store_page_used(info, extra_buff, extra_length + info->s->keypage_header,
+ nod_flag);
/* move first largest keys to new page */
pos=buff+right_length-extra_length;
- memcpy((uchar*) extra_buff+2,pos,(size_t) extra_length);
+ memcpy(extra_buff + info->s->keypage_header, pos,
+ (size_t) extra_length);
/* Save new parting key */
memcpy(tmp_part_key, pos-k_length,k_length);
/* Make place for new keys */
- bmove_upp((uchar*) buff+new_right_length,(uchar*) pos-k_length,
- right_length-extra_length-k_length-2);
+ bmove_upp(buff+ new_right_length, pos - k_length,
+ right_length - extra_length - k_length - info->s->keypage_header);
/* Copy keys from left page */
pos= curr_buff+new_left_length;
- memcpy((uchar*) buff+2,(uchar*) pos+k_length,
+ memcpy(buff + info->s->keypage_header, pos + k_length,
(size_t) (length=left_length-new_left_length-k_length));
/* Copy old parting key */
- memcpy((uchar*) buff+2+length,father_key_pos,(size_t) k_length);
+ memcpy(buff + info->s->keypage_header + length,
+ father_key_pos, (size_t) k_length);
/* Move new parting keys up to caller */
- memcpy((uchar*) (right ? key : father_key_pos),pos,(size_t) k_length);
- memcpy((uchar*) (right ? father_key_pos : key),tmp_part_key, k_length);
+ memcpy((right ? key : father_key_pos),pos,(size_t) k_length);
+ memcpy((right ? father_key_pos : key),tmp_part_key, k_length);
if ((new_pos= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
goto err;
@@ -970,7 +1010,7 @@ static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2)
{
uint not_used[2];
return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg,
- (uchar*) key1, (uchar*) key2, USE_WHOLE_KEY, SEARCH_SAME,
+ key1, key2, USE_WHOLE_KEY, SEARCH_SAME,
not_used);
}