Commit 6724abae authored by Michael Widenius's avatar Michael Widenius

Added MARIA_PAGE structure to keep all information about a maria key page.

This allowed me to remove a lot of parameters to functions, local variables,
duplicate code and identical constructs.  It should also make the code easier
to read.
Changed all marking of page as changed to use offset instead of pointers; This removed
one theoretical problem where dynamic_array may have been moved between two calls.
In addition I changed some functions from return my_bool


include/maria.h:
  Changes to use MARIA_PAGE
storage/maria/ma_check.c:
  Changes to use MARIA_PAGE
  Folded lines longer > 79 characters
storage/maria/ma_delete.c:
  Changes to use MARIA_PAGE
  Changed _ma_ck_delete(), ma_log_delete(), ma_write_undo_key_delete() and _ma_ck_real_delete() to return type my_bool
  Removed some calls to maria_print_error() as the caller (maria_delete() and maria_write()) also prints the error
storage/maria/ma_ft_update.c:
  Fix needed as _ma_ck_delete() now returns my_bool
  New parameter for ma_write_keypage.
storage/maria/ma_key_recover.c:
  Changes to use MARIA_PAGE
storage/maria/ma_key_recover.h:
  Updated function prototypes
storage/maria/ma_page.c:
  Changes to use MARIA_PAGE
  Added _ma_page_setup() for old functions that doesn't (yet) use MARIA_PAGE natively
storage/maria/ma_range.c:
  Changes to use MARIA_PAGE
storage/maria/ma_rt_index.c:
  Changes to use MARIA_PAGE
  Changed maria_rtree_delete() and maria_rtree_real_delete() to return type my_bool
  Removed one 'if (node_flag) as this was always true
  Changed lable 'err1' to 'err' as there was no other error lables
  Moved allocation of page_buff outside of loop for fewer alloc/free calls
  Changed n_pages and m_pages to uint as 65000 pages is more than enough
storage/maria/ma_rt_index.h:
  Updated function prototypes
storage/maria/ma_rt_key.c:
  Changes to use MARIA_PAGE
storage/maria/ma_rt_key.h:
  Updated function prototypes
storage/maria/ma_rt_mbr.c:
  Changes to use MARIA_PAGE
storage/maria/ma_rt_mbr.h:
  Updated function prototypes
storage/maria/ma_rt_split.c:
  Changes to use MARIA_PAGE
storage/maria/ma_search.c:
  Changes to use MARIA_PAGE
storage/maria/ma_write.c:
  Changes to use MARIA_PAGE
  Changed _ma_ck_write_btree_with_log(), _ma_ck_real_write_btree(), ma_enlarge_root() to use return type my_bool
  Don't set *root to HA_OFFSET_ERROR in case of error
  Removed maria_print_error() calls as caller will do this
  Simplified logic in balance_page by introducing pointers to left and right pages
storage/maria/maria_chk.c:
  Changes to use MARIA_PAGE
storage/maria/maria_def.h:
  Changes to use MARIA_PAGE
  Removed some not used macros
  Added macros for MARIA_PAGE handling
parent 3cc4babd
......@@ -161,6 +161,7 @@ struct st_maria_handler; /* For referense */
typedef struct st_maria_handler MARIA_HA;
struct st_maria_s_param;
struct st_maria_keydef;
struct st_maria_page;
typedef struct st_maria_key /* Internal info about a key */
{
......@@ -194,7 +195,7 @@ typedef struct st_maria_keydef /* Key definition with open & info */
HA_KEYSEG *seg, *end;
struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */
int (*bin_search)(const MARIA_KEY *key, uchar *page,
int (*bin_search)(const MARIA_KEY *key, const struct st_maria_page *page,
uint32 comp_flag, uchar **ret_pos, uchar *buff,
my_bool *was_last_key);
uint (*get_key)(MARIA_KEY *key, uint page_flag, uint nod_flag,
......@@ -207,7 +208,7 @@ typedef struct st_maria_keydef /* Key definition with open & info */
void (*store_key)(struct st_maria_keydef *keyinfo, uchar *key_pos,
struct st_maria_s_param *s_temp);
my_bool (*ck_insert)(MARIA_HA *inf, MARIA_KEY *key);
int (*ck_delete)(MARIA_HA *inf, MARIA_KEY *klen);
my_bool (*ck_delete)(MARIA_HA *inf, MARIA_KEY *klen);
MARIA_KEY *(*make_key)(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,
uchar *key, const uchar *record,
MARIA_RECORD_POS filepos, ulonglong trid);
......
......@@ -58,8 +58,8 @@
/* Functions defined in this file */
static int check_k_link(HA_CHECK *param, MARIA_HA *info, my_off_t next_link);
static int chk_index(HA_CHECK *param, MARIA_HA *info,MARIA_KEYDEF *keyinfo,
my_off_t page, uchar *buff, ha_rows *keys,
static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
MARIA_PAGE *page, ha_rows *keys,
ha_checksum *key_checksum, uint level);
static uint isam_key_length(MARIA_HA *info,MARIA_KEYDEF *keyinfo);
static ha_checksum calc_checksum(ha_rows count);
......@@ -468,6 +468,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo;
char buff[22],buff2[22];
MARIA_PAGE page;
DBUG_ENTER("maria_chk_key");
if (!(param->testflag & T_SILENT))
......@@ -522,9 +523,9 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
_ma_check_print_error(param, "Key tree %u is empty", key + 1);
goto do_stat;
}
if (!_ma_fetch_keypage(info, keyinfo, share->state.key_root[key],
if (_ma_fetch_keypage(&page, info, keyinfo, share->state.key_root[key],
PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS,
info->buff, 0, 0))
info->buff, 0))
{
report_keypage_fault(param, info, share->state.key_root[key]);
if (!(param->testflag & T_INFO))
......@@ -537,8 +538,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
param->keydata=param->totaldata=0;
param->key_blocks=0;
param->max_level=0;
if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
&keys, param->key_crc+key,1))
if (chk_index(param, info,keyinfo, &page, &keys, param->key_crc+key,1))
DBUG_RETURN(-1);
if (!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL | HA_RTREE_INDEX)))
{
......@@ -659,6 +659,7 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info,
{
char llbuff[22],llbuff2[22];
MARIA_SHARE *share= info->s;
MARIA_PAGE ma_page;
DBUG_ENTER("chk_index_down");
/* Key blocks must lay within the key file length entirely. */
......@@ -692,14 +693,15 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info,
/* purecov: end */
}
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, buff, 0, 0))
if (_ma_fetch_keypage(&ma_page, info, keyinfo, page,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, buff, 0))
{
report_keypage_fault(param, info, page);
goto err;
}
param->key_file_blocks+=keyinfo->block_length;
if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level))
if (chk_index(param, info, keyinfo, &ma_page, keys, key_checksum,level))
goto err;
DBUG_RETURN(0);
......@@ -804,11 +806,11 @@ int maria_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull,
/* Check if index is ok */
static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t page, uchar *buff, ha_rows *keys,
MARIA_PAGE *anc_page, ha_rows *keys,
ha_checksum *key_checksum, uint level)
{
int flag;
uint used_length,comp_flag,page_flag,nod_flag;
uint comp_flag, page_flag, nod_flag;
uchar *temp_buff, *keypos, *old_keypos, *endpos;
my_off_t next_page,record;
MARIA_SHARE *share= info->s;
......@@ -817,7 +819,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uchar tmp_key_buff[MARIA_MAX_KEY_BUFF];
MARIA_KEY tmp_key;
DBUG_ENTER("chk_index");
DBUG_DUMP("buff", buff, _ma_get_page_used(share, buff));
DBUG_DUMP("buff", anc_page->buff, anc_page->size);
/* TODO: implement appropriate check for RTree keys */
if (keyinfo->flag & (HA_SPATIAL | HA_RTREE_INDEX))
......@@ -837,22 +839,22 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
else
comp_flag=SEARCH_SAME; /* Keys in positionorder */
page_flag= _ma_get_keypage_flag(share, buff);
_ma_get_used_and_nod_with_flag(share, page_flag, buff, used_length,
nod_flag);
old_keypos= buff + share->keypage_header;
keypos= old_keypos+ nod_flag;
endpos= buff + used_length;
page_flag= anc_page->flag;
nod_flag= anc_page->node;
old_keypos= anc_page->buff + share->keypage_header;
keypos= old_keypos + nod_flag;
endpos= anc_page->buff + anc_page->size;
param->keydata+= used_length;
param->keydata+= anc_page->size;
param->totaldata+= keyinfo->block_length; /* INFO */
param->key_blocks++;
if (level > param->max_level)
param->max_level=level;
if (_ma_get_keynr(share, buff) != (uint) (keyinfo - share->keyinfo))
if (_ma_get_keynr(share, anc_page->buff) !=
(uint) (keyinfo - share->keyinfo))
_ma_check_print_error(param, "Page at %s is not marked for index %u",
llstr(page, llbuff),
llstr(anc_page->pos, llbuff),
(uint) (keyinfo - share->keyinfo));
if ((page_flag & KEYPAGE_FLAG_HAS_TRANSID) &&
!share->base.born_transactional)
......@@ -860,13 +862,14 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_check_print_error(param,
"Page at %s is marked with HAS_TRANSID even if "
"table is not transactional",
llstr(page, llbuff));
llstr(anc_page->pos, llbuff));
}
if (used_length > (uint) keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)
if (anc_page->size > (uint) keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)
{
_ma_check_print_error(param,"Page at %s has impossible (too big) pagelength",
llstr(page,llbuff));
_ma_check_print_error(param,
"Page at %s has impossible (too big) pagelength",
llstr(anc_page->pos, llbuff));
goto err;
}
......@@ -895,7 +898,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_check_print_error(param,
"Page length and length of keys don't match at "
"page: %s",
llstr(page,llbuff));
llstr(anc_page->pos,llbuff));
goto err;
}
if (share->data_file_type == BLOCK_RECORD &&
......@@ -906,7 +909,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_check_print_error(param,
"Found key marked for transid on page that is not "
"marked for transid at: %s",
llstr(page,llbuff));
llstr(anc_page->pos,llbuff));
goto err;
}
......@@ -922,10 +925,10 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
if ((comp_flag & SEARCH_FIND) && flag == 0)
_ma_check_print_error(param,"Found duplicated key at page %s",
llstr(page,llbuff));
llstr(anc_page->pos,llbuff));
else
_ma_check_print_error(param,"Key in wrong position at page %s",
llstr(page,llbuff));
llstr(anc_page->pos,llbuff));
goto err;
}
......@@ -976,7 +979,8 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
"Number of words in the 2nd level tree "
"does not match the number in the header. "
"Parent word in on the page %s, offset %u",
llstr(page,llbuff), (uint) (old_keypos-buff));
llstr(anc_page->pos,llbuff),
(uint) (old_keypos - anc_page->buff));
goto err;
}
(*keys)+=tmp_keys-1;
......@@ -993,9 +997,12 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
#ifndef DBUG_OFF
char llbuff2[22], llbuff3[22];
#endif
_ma_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
_ma_check_print_error(param,
"Found key at page %s that points to record "
"outside datafile",
llstr(anc_page->pos,llbuff));
DBUG_PRINT("test",("page: %s record: %s filelength: %s",
llstr(page,llbuff),llstr(record,llbuff2),
llstr(anc_page->pos,llbuff),llstr(record,llbuff2),
llstr(share->state.state.data_file_length,llbuff3)));
DBUG_DUMP_KEY("key", &tmp_key);
DBUG_DUMP("new_in_page", old_keypos, (uint) (keypos-old_keypos));
......@@ -1008,8 +1015,8 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_check_print_error(param,
"Keyblock size at page %s is not correct. "
"Block length: %u key length: %u",
llstr(page, llbuff), used_length,
(uint) (keypos - buff));
llstr(anc_page->pos, llbuff), anc_page->size,
(uint) (keypos - anc_page->buff));
goto err;
}
my_afree((uchar*) temp_buff);
......@@ -1180,7 +1187,8 @@ static int check_static_record(HA_CHECK *param, MARIA_HA *info, int extend,
share->base.pack_reclength))
{
_ma_check_print_error(param,
"got error: %d when reading datafile at position: %s",
"got error: %d when reading datafile at position: "
"%s",
my_errno, llstr(pos, llbuff));
return 1;
}
......@@ -1269,7 +1277,8 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
if (block_info.block_len < share->base.min_block_length)
{
_ma_check_print_error(param,
"Deleted block with impossible length %lu at %s",
"Deleted block with impossible length %lu "
"at %s",
block_info.block_len,llstr(pos,llbuff));
DBUG_RETURN(1);
}
......@@ -1278,7 +1287,8 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
(block_info.prev_filepos != HA_OFFSET_ERROR &&
block_info.prev_filepos >= share->state.state.data_file_length))
{
_ma_check_print_error(param,"Delete link points outside datafile at %s",
_ma_check_print_error(param,"Delete link points outside datafile "
"at %s",
llstr(pos,llbuff));
DBUG_RETURN(1);
}
......@@ -1347,7 +1357,9 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
flag == 1 ? READING_NEXT : 0))
{
_ma_check_print_error(param,
"got error: %d when reading datafile at position: %s", my_errno, llstr(block_info.filepos, llbuff));
"got error: %d when reading datafile at "
"position: %s", my_errno,
llstr(block_info.filepos, llbuff));
DBUG_RETURN(1);
}
......@@ -1371,7 +1383,8 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
if (share->state.state.data_file_length < block_info.next_filepos)
{
_ma_check_print_error(param,
"Found next-recordlink that points outside datafile at %s",
"Found next-recordlink that points outside "
"datafile at %s",
llstr(block_info.filepos,llbuff));
got_error=1;
break;
......@@ -1446,7 +1459,8 @@ static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend,
share->pack.ref_length, READING_NEXT))
{
_ma_check_print_error(param,
"got error: %d when reading datafile at position: %s",
"got error: %d when reading datafile at position: "
"%s",
my_errno, llstr(pos, llbuff));
DBUG_RETURN(1);
}
......@@ -1470,7 +1484,8 @@ static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend,
block_info.filepos, block_info.rec_len, READING_NEXT))
{
_ma_check_print_error(param,
"got error: %d when reading datafile at position: %s",
"got error: %d when reading datafile at position: "
"%s",
my_errno, llstr(block_info.filepos, llbuff));
DBUG_RETURN(1);
}
......@@ -1615,7 +1630,8 @@ static int check_page_layout(HA_CHECK *param, MARIA_HA *info,
if (empty != head_empty)
{
_ma_check_print_error(param,
"Page %9s: Wrong empty size. Stored: %5u Actual: %5u",
"Page %9s: Wrong empty size. Stored: %5u "
"Actual: %5u",
llstr(page_pos, llbuff), head_empty, empty);
param->err_count++;
}
......@@ -1738,7 +1754,9 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, uchar *record,
&bitmap_pattern))
{
_ma_check_print_error(param,
"Page %9s: Row: %3d has an extent with wrong information in bitmap: Page %9s Page_type: %d Bitmap: %d",
"Page %9s: Row: %3d has an extent with "
"wrong information in bitmap: "
"Page %9s Page_type: %d Bitmap: %d",
llstr(page, llbuff), row,
llstr(extent_page, llbuff2),
page_type, bitmap_pattern);
......@@ -1908,7 +1926,8 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
llstr(page, llbuff));
else
_ma_check_print_error(param,
"Page %9s: Wrong data in bitmap. Page_type: %d empty_space: %u Bitmap-bits: %d",
"Page %9s: Wrong data in bitmap. Page_type: "
"%d empty_space: %u Bitmap-bits: %d",
llstr(page, llbuff), page_type,
empty_space, bitmap_pattern);
if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE))
......@@ -1958,11 +1977,13 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
_ma_scan_end_block_record(info);
if (full_page_count != param->full_page_count)
_ma_check_print_error(param, "Full page count read through records was %s but we found %s pages while scanning table",
_ma_check_print_error(param, "Full page count read through records was %s "
"but we found %s pages while scanning table",
llstr(param->full_page_count, llbuff),
llstr(full_page_count, llbuff2));
if (tail_count != param->tail_count)
_ma_check_print_error(param, "Tail count read through records was %s but we found %s tails while scanning table",
_ma_check_print_error(param, "Tail count read through records was %s but "
"we found %s tails while scanning table",
llstr(param->tail_count, llbuff),
llstr(tail_count, llbuff2));
......@@ -2051,7 +2072,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
(HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
{
_ma_check_print_warning(param,
"Record checksum is not the same as checksum stored in the index file");
"Record checksum is not the same as checksum "
"stored in the index file");
error=1;
}
else if (!extend)
......@@ -2063,7 +2085,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
!(share->keyinfo[key].flag &
(HA_FULLTEXT | HA_SPATIAL | HA_RTREE_INDEX)))
{
_ma_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records",
_ma_check_print_error(param,"Checksum for key: %2d doesn't match "
"checksum for records",
key+1);
error=1;
}
......@@ -2084,7 +2107,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
share->state.state.data_file_length)
{
_ma_check_print_warning(param,
"Found %s record data and %s unused data and %s deleted data",
"Found %s record data and %s unused data and %s "
"deleted data",
llstr(param->used, llbuff),
llstr(param->empty,llbuff2),
llstr(param->del_length,llbuff3));
......@@ -2092,7 +2116,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
"Total %s Should be: %s",
llstr((param->used+param->empty +
param->del_length), llbuff),
llstr(share->state.state.data_file_length,llbuff2));
llstr(share->state.state.data_file_length,
llbuff2));
}
if (param->del_blocks != share->state.state.del)
{
......@@ -2104,7 +2129,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
if (param->splits != share->state.split)
{
_ma_check_print_warning(param,
"Found %10s parts Should be: %s parts",
"Found %10s parts Should be: "
"%s parts",
llstr(param->splits, llbuff),
llstr(share->state.split,llbuff2));
}
......@@ -2126,9 +2152,11 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
my_off_t2double(param->used))/
ulonglong2double((ulonglong) share->base.reclength *
param->records)*100.0));
printf("Recordspace used:%9.0f%% Empty space:%12d%% Blocks/Record: %6.2f\n",
printf("Recordspace used:%9.0f%% Empty space:%12d%% "
"Blocks/Record: %6.2f\n",
(ulonglong2double(param->used - param->link_used)/
ulonglong2double(param->used-param->link_used+param->empty)*100.0),
ulonglong2double(param->used-param->link_used+param->empty) *
100.0),
(!param->records ? 100 :
(int) (ulonglong2double(param->del_length+param->empty)/
my_off_t2double(param->used)*100.0)),
......@@ -2569,7 +2597,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
DBUG_DUMP("record", (uchar*) sort_param.record,
share->base.default_rec_buff_size);
_ma_check_print_warning(param,
"Duplicate key %2d for record at %10s against new record at %10s",
"Duplicate key %2d for record at %10s against "
"new record at %10s",
info->errkey+1,
llstr(sort_param.current_filepos, llbuff),
llstr(info->dup_key_pos,llbuff2));
......@@ -2629,7 +2658,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
if (rep_quick && del+sort_info.dupp != share->state.state.del)
{
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
_ma_check_print_error(param,"Couldn't fix table with quick recovery: "
"Found wrong number of deleted records");
_ma_check_print_error(param,"Run recovery again without -q");
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
......@@ -2833,6 +2863,7 @@ int maria_movepoint(register MARIA_HA *info, uchar *record,
uint i;
uchar *key_buff;
MARIA_SHARE *share= info->s;
MARIA_PAGE page;
DBUG_ENTER("maria_movepoint");
key_buff= info->lastkey_buff + share->base.max_key_length;
......@@ -2845,18 +2876,19 @@ int maria_movepoint(register MARIA_HA *info, uchar *record,
0);
if (key.keyinfo->flag & HA_NOSAME)
{ /* Change pointer direct */
uint nod_flag;
MARIA_KEYDEF *keyinfo;
keyinfo=share->keyinfo+i;
if (_ma_search(info, &key, (uint32) (SEARCH_SAME | SEARCH_SAVE_BUFF),
share->state.key_root[i]))
DBUG_RETURN(-1);
nod_flag= _ma_test_if_nod(share, info->buff);
_ma_dpointer(share, info->int_keypos - nod_flag -
_ma_page_setup(&page, info, keyinfo, info->last_keypage,
info->keyread_buff);
_ma_dpointer(share, info->int_keypos - page.node -
share->rec_reflength,newpos);
if (_ma_write_keypage(info, keyinfo, info->last_keypage,
PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS,
info->buff))
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS))
DBUG_RETURN(-1);
}
else
......@@ -3053,11 +3085,12 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
MARIA_KEYDEF *keyinfo,
my_off_t pagepos, File new_file)
{
uint length,nod_flag,used_length;
uint length,nod_flag;
uchar *buff,*keypos,*endpos;
my_off_t new_page_pos,next_page;
MARIA_SHARE *share= info->s;
MARIA_KEY key;
MARIA_PAGE page;
DBUG_ENTER("sort_one_index");
/* cannot walk over R-tree indices */
......@@ -3072,18 +3105,18 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
_ma_check_print_error(param,"Not enough memory for key block");
DBUG_RETURN(-1);
}
if (!_ma_fetch_keypage(info, keyinfo, pagepos,PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, buff, 0, 0))
if (_ma_fetch_keypage(&page, info, keyinfo, pagepos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, buff, 0))
{
report_keypage_fault(param, info, pagepos);
goto err;
}
if ((nod_flag=_ma_test_if_nod(share, buff)) || keyinfo->flag & HA_FULLTEXT)
if ((nod_flag= page.node) || keyinfo->flag & HA_FULLTEXT)
{
uint page_flag= _ma_get_keypage_flag(share, buff);
used_length= _ma_get_page_used(share, buff);
keypos=buff + share->keypage_header + nod_flag;
endpos=buff + used_length;
keypos= page.buff + share->keypage_header + nod_flag;
endpos= page.buff + page.size;
for ( ;; )
{
......@@ -3097,13 +3130,13 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
DBUG_PRINT("error",
("From page: %ld, keyoffset: %lu used_length: %d",
(ulong) pagepos, (ulong) (keypos - buff),
(int) used_length));
DBUG_DUMP("buff",(uchar*) buff,used_length);
(int) page.size));
DBUG_DUMP("buff", page.buff, page.size);
goto err;
}
}
if (keypos >= endpos ||
!(*keyinfo->get_key)(&key, page_flag, nod_flag, &keypos))
!(*keyinfo->get_key)(&key, page.flag, nod_flag, &keypos))
break;
DBUG_ASSERT(keypos <= endpos);
if (keyinfo->flag & HA_FULLTEXT)
......@@ -3126,7 +3159,7 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
}
/* Fill block with zero and write it to the new index file */
length= _ma_get_page_used(share, buff);
length= page.size;
bzero((uchar*) buff+length,keyinfo->block_length-length);
put_crc(buff, new_page_pos, share);
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
......@@ -3198,9 +3231,11 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info,
uint keynr= _ma_get_keynr(share, buff);
if (keynr != MARIA_DELETE_KEY_NR)
{
MARIA_PAGE page;
DBUG_ASSERT(keynr < share->base.keys);
if (_ma_compact_keypage(info, share->keyinfo + keynr, pos,
buff, ~(TrID) 0))
_ma_page_setup(&page, info, share->keyinfo + keynr, pos, buff);
if (_ma_compact_keypage(&page, ~(TrID) 0))
{
_ma_check_print_error(param,
"Page %9s: Got error %d when reading index "
......@@ -3822,7 +3857,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if (rep_quick && del+sort_info.dupp != share->state.state.del)
{
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
_ma_check_print_error(param,"Couldn't fix table with quick recovery: "
"Found wrong number of deleted records");
_ma_check_print_error(param,"Run recovery again without -q");
got_error=1;
param->retry_repair=1;
......@@ -3850,7 +3886,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if (param->testflag & T_CALC_CHECKSUM)
share->state.state.checksum=param->glob_crc;
if (my_chsize(share->kfile.file, share->state.state.key_file_length, 0, MYF(0)))
if (my_chsize(share->kfile.file, share->state.state.key_file_length, 0,
MYF(0)))
_ma_check_print_warning(param,
"Can't change size of indexfile, error: %d",
my_errno);
......@@ -4198,8 +4235,9 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
{
uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
sort_param[i].keyinfo->seg->charset->mbmaxlen;
uint ft_max_word_len_for_sort=
(FT_MAX_WORD_LEN_FOR_SORT *
sort_param[i].keyinfo->seg->charset->mbmaxlen);
sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
}
......@@ -4325,7 +4363,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (rep_quick && del+sort_info.dupp != share->state.state.del)
{
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
_ma_check_print_error(param,"Couldn't fix table with quick recovery: "
"Found wrong number of deleted records");
_ma_check_print_error(param,"Run recovery again without -q");
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
......@@ -4351,7 +4390,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (param->testflag & T_CALC_CHECKSUM)
share->state.state.checksum=param->glob_crc;
if (my_chsize(share->kfile.file, share->state.state.key_file_length, 0, MYF(0)))
if (my_chsize(share->kfile.file, share->state.state.key_file_length, 0,
MYF(0)))
_ma_check_print_warning(param,
"Can't change size of indexfile, error: %d",
my_errno);
......@@ -4794,11 +4834,13 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
block_info.next_filepos >=
share->state.state.data_file_length) ||
(block_info.prev_filepos != HA_OFFSET_ERROR &&
block_info.prev_filepos >= share->state.state.data_file_length))
block_info.prev_filepos >=
share->state.state.data_file_length))
{
if (!searching)
_ma_check_print_info(param,
"Delete link points outside datafile at %s",
"Delete link points outside datafile at "
"%s",
llstr(pos,llbuff));
error=1;
}
......@@ -4881,14 +4923,16 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
{
if (param->max_record_length >= block_info.rec_len)
{
_ma_check_print_error(param,"Not enough memory for blob at %s (need %lu)",
_ma_check_print_error(param,"Not enough memory for blob at %s "
"(need %lu)",
llstr(sort_param->start_recpos,llbuff),
(ulong) block_info.rec_len);
DBUG_RETURN(1);
}
else
{
_ma_check_print_info(param,"Not enough memory for blob at %s (need %lu); Row skipped",
_ma_check_print_info(param,"Not enough memory for blob at %s "
"(need %lu); Row skipped",
llstr(sort_param->start_recpos,llbuff),
(ulong) block_info.rec_len);
goto try_next;
......@@ -4941,7 +4985,8 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
parallel_flag))
{
_ma_check_print_info(param,
"Read error for block at: %s (error: %d); Skipped",
"Read error for block at: %s (error: %d); "
"Skipped",
llstr(block_info.filepos,llbuff),my_errno);
goto try_next;
}
......@@ -4950,13 +4995,18 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
pos=block_info.next_filepos;
if (pos == HA_OFFSET_ERROR && left_length)
{
_ma_check_print_info(param,"Wrong block with wrong total length starting at %s",
_ma_check_print_info(param,
"Wrong block with wrong total length "
"starting at %s",
llstr(sort_param->start_recpos,llbuff));
goto try_next;
}
if (pos + MARIA_BLOCK_INFO_HEADER_LENGTH > sort_param->read_cache.end_of_file)
if (pos + MARIA_BLOCK_INFO_HEADER_LENGTH >
sort_param->read_cache.end_of_file)
{
_ma_check_print_info(param,"Found link that points at %s (outside data file) at %s",
_ma_check_print_info(param,
"Found link that points at %s (outside data "
"file) at %s",
llstr(pos,llbuff2),
llstr(sort_param->start_recpos,llbuff));
goto try_next;
......@@ -5261,7 +5311,8 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a)
sort_info->info->cur_row.lastpos= get_record_for_key(sort_param->keyinfo,
a);
_ma_check_print_warning(param,
"Duplicate key %2u for record at %10s against record at %10s",
"Duplicate key %2u for record at %10s against "
"record at %10s",
sort_param->key + 1,
llstr(sort_info->info->cur_row.lastpos, llbuff),
llstr(get_record_for_key(sort_param->keyinfo,
......@@ -5435,7 +5486,7 @@ static my_off_t get_record_for_key(MARIA_KEYDEF *keyinfo,
} /* get_record_for_key */
/* Insert a key in sort-key-blocks */
/* Insert a key in sort-key-blocks */
static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
register SORT_KEY_BLOCKS *key_block,
......@@ -5465,7 +5516,9 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
key_block->inited=1;
if (key_block == sort_info->key_block_end)
{
_ma_check_print_error(param,"To many key-block-levels; Try increasing sort_key_blocks");
_ma_check_print_error(param,
"To many key-block-levels; "
"Try increasing sort_key_blocks");
DBUG_RETURN(1);
}
a_length= share->keypage_header + nod_flag;
......@@ -5517,10 +5570,10 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
/* If we read the page from the key cache, we have to write it back to it */
if (page_link->changed)
{
MARIA_PAGE page;
pop_dynamic(&info->pinned_pages);
if (_ma_write_keypage(info, keyinfo, filepos,
PAGECACHE_LOCK_WRITE_UNLOCK,
DFLT_INIT_HITS, anc_buff))
_ma_page_setup(&page, info, keyinfo, filepos, anc_buff);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_WRITE_UNLOCK, DFLT_INIT_HITS))
DBUG_RETURN(1);
}
else
......@@ -5557,8 +5610,8 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param)
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
{
_ma_check_print_error(param,
"Quick-recover aborted; Run recovery without switch -q or with "
"switch -qq");
"Quick-recover aborted; Run recovery without switch "
"-q or with switch -qq");
DBUG_RETURN(1);
}
if (key_info->s->options & HA_OPTION_COMPRESS_RECORD)
......@@ -5646,10 +5699,12 @@ int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param)
/* If we read the page from the key cache, we have to write it back */
if (page_link->changed)
{
MARIA_PAGE page;
pop_dynamic(&info->pinned_pages);
if (_ma_write_keypage(info, keyinfo, filepos,
PAGECACHE_LOCK_WRITE_UNLOCK,
DFLT_INIT_HITS, key_block->buff))
_ma_page_setup(&page, info, keyinfo, filepos, key_block->buff);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_WRITE_UNLOCK,
DFLT_INIT_HITS))
goto err;
}
else
......@@ -5865,8 +5920,8 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
if (!*org_info)
{
_ma_check_print_error(param,
"Got error %d when trying to open re-created indexfile",
my_errno);
"Got error %d when trying to open re-created "
"indexfile", my_errno);
goto end;
}
/* We are modifing */
......@@ -6644,13 +6699,17 @@ static void _ma_check_print_not_visible_error(HA_CHECK *param, TrID used_trid)
if (!ma_control_file_inited())
{
_ma_check_print_warning(param,
"Found row with transaction id %s but no maria_control_file was specified. The table may be corrupted",
"Found row with transaction id %s but no "
"maria_control_file was specified. "
"The table may be corrupted",
llstr(used_trid, buff));
}
else
{
_ma_check_print_error(param,
"Found row with transaction id %s when max transaction id according to maria_control_file is %s",
"Found row with transaction id %s when max "
"transaction id according to maria_control_file "
"is %s",
llstr(used_trid, buff),
llstr(param->max_trid, buff2));
}
......
......@@ -19,16 +19,13 @@
#include "ma_key_recover.h"
static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
my_off_t page, uchar *anc_buff,
MARIA_PINNED_PAGE *anc_page_link);
MARIA_PAGE *page);
static int del(MARIA_HA *info, MARIA_KEY *key,
my_off_t anc_page, uchar *anc_buff, my_off_t leaf_page,
uchar *leaf_buff, MARIA_PINNED_PAGE *leaf_page_link,
uchar *keypos, my_off_t next_block, uchar *ret_key);
static int underflow(MARIA_HA *info,MARIA_KEYDEF *keyinfo,
my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link, uchar *keypos);
MARIA_PAGE *anc_page, MARIA_PAGE *leaf_page,
uchar *keypos, my_off_t next_block, uchar *ret_key_buff);
static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
MARIA_PAGE *anc_page, MARIA_PAGE *leaf_page,
uchar *keypos);
static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag,
uchar *keypos, uchar *lastkey, uchar *page_end,
my_off_t *next_block, MARIA_KEY_PARAM *s_temp);
......@@ -161,7 +158,7 @@ int maria_delete(MARIA_HA *info,const uchar *record)
of key->data. This would allows us to remove the copying of the key here.
*/
int _ma_ck_delete(register MARIA_HA *info, MARIA_KEY *key)
my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key)
{
MARIA_SHARE *share= info->s;
int res;
......@@ -191,77 +188,78 @@ int _ma_ck_delete(register MARIA_HA *info, MARIA_KEY *key)
_ma_fast_unlock_key_del(info);
}
_ma_unpin_all_pages_and_finalize_row(info, lsn);
DBUG_RETURN(res);
DBUG_RETURN(res != 0);
} /* _ma_ck_delete */
int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
my_off_t *root)
{
int error;
uint nod_flag;
my_bool result= 0;
my_off_t old_root;
uchar *root_buff;
MARIA_PINNED_PAGE *page_link;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE page;
DBUG_ENTER("_ma_ck_real_delete");
if ((old_root=*root) == HA_OFFSET_ERROR)
{
maria_print_error(info->s, HA_ERR_CRASHED);
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1);
}
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MARIA_MAX_KEY_BUFF*2)))
{
DBUG_PRINT("error",("Couldn't allocate memory"));
DBUG_RETURN(my_errno=ENOMEM);
my_errno=ENOMEM;
DBUG_RETURN(1);
}
DBUG_PRINT("info",("root_page: %ld", (long) old_root));
if (!_ma_fetch_keypage(info, keyinfo, old_root,
PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, root_buff, 0,
&page_link))
if (_ma_fetch_keypage(&page, info, keyinfo, old_root,
PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, root_buff, 0))
{
error= -1;
result= 1;
goto err;
}
if ((error= d_search(info, key, (keyinfo->flag & HA_FULLTEXT ?
SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT:
SEARCH_SAME),
old_root, root_buff, page_link)) > 0)
&page)))
{
if (error == 2)
if (error < 0)
result= 1;
else if (error == 2)
{
DBUG_PRINT("test",("Enlarging of root when deleting"));
error= _ma_enlarge_root(info, key, root);
if (_ma_enlarge_root(info, key, root))
result= 1;
}
else /* error == 1 */
{
uint used_length;
MARIA_SHARE *share= info->s;
_ma_get_used_and_nod(share, root_buff, used_length, nod_flag);
page_link->changed= 1;
if (used_length <= nod_flag + share->keypage_header + 1)
page_mark_changed(info, &page);
if (page.size <= page.node + share->keypage_header + 1)
{
error=0;
if (nod_flag)
*root= _ma_kpos(nod_flag, root_buff +share->keypage_header +
nod_flag);
if (page.node)
*root= _ma_kpos(page.node, root_buff +share->keypage_header +
page.node);
else
*root=HA_OFFSET_ERROR;
if (_ma_dispose(info, old_root, 0))
error= -1;
result= 1;
}
else
error= _ma_write_keypage(info,keyinfo, old_root,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, root_buff);
else if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
result= 1;
}
}
err:
my_afree((uchar*) root_buff);
DBUG_PRINT("exit",("Return: %d",error));
DBUG_RETURN(error);
DBUG_PRINT("exit",("Return: %d",result));
DBUG_RETURN(result);
} /* _ma_ck_real_delete */
......@@ -278,31 +276,29 @@ int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
*/
static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
my_off_t anc_page, uchar *anc_buff,
MARIA_PINNED_PAGE *anc_page_link)
MARIA_PAGE *anc_page)
{
int flag,ret_value,save_flag;
uint nod_flag, page_flag;
my_bool last_key;
uchar *leaf_buff,*keypos;
my_off_t leaf_page,next_block;
uchar lastkey[MARIA_MAX_KEY_BUFF];
MARIA_PINNED_PAGE *leaf_page_link;
MARIA_KEY_PARAM s_temp;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE leaf_page;
DBUG_ENTER("d_search");
DBUG_DUMP("page",anc_buff,_ma_get_page_used(share, anc_buff));
DBUG_DUMP("page", anc_page->buff, anc_page->size);
flag=(*keyinfo->bin_search)(key, anc_buff, comp_flag, &keypos, lastkey,
flag=(*keyinfo->bin_search)(key, anc_page, comp_flag, &keypos, lastkey,
&last_key);
if (flag == MARIA_FOUND_WRONG_KEY)
{
DBUG_PRINT("error",("Found wrong key"));
DBUG_RETURN(-1);
}
page_flag= _ma_get_keypage_flag(share, anc_buff);
nod_flag= _ma_test_if_nod(share, anc_buff);
page_flag= anc_page->flag;
nod_flag= anc_page->node;
if (!flag && (keyinfo->flag & HA_FULLTEXT))
{
......@@ -324,7 +320,7 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
else
{
/* we need exact match only if not in ft1->ft2 conversion mode */
flag=(*keyinfo->bin_search)(key, anc_buff, comp_flag, &keypos,
flag=(*keyinfo->bin_search)(key, anc_page, comp_flag, &keypos,
lastkey, &last_key);
}
/* fall through to normal delete */
......@@ -343,7 +339,6 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
if (!(tmp_key_length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag,
&kpos)))
{
maria_print_error(share, HA_ERR_CRASHED);
my_errno= HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
......@@ -374,10 +369,10 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
ft_intXstore(kpos, subkeys);
if (!ret_value)
{
anc_page_link->changed= 1;
ret_value= _ma_write_keypage(info, keyinfo, anc_page,
page_mark_changed(info, anc_page);
ret_value= _ma_write_keypage(anc_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, anc_buff);
DFLT_INIT_HITS);
}
DBUG_PRINT("exit",("Return: %d",ret_value));
DBUG_RETURN(ret_value);
......@@ -385,11 +380,10 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
}
}
leaf_buff=0;
LINT_INIT(leaf_page);
if (nod_flag)
{
/* Read left child page */
leaf_page= _ma_kpos(nod_flag,keypos);
leaf_page.pos= _ma_kpos(nod_flag,keypos);
if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MARIA_MAX_KEY_BUFF*2)))
{
......@@ -397,9 +391,9 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
my_errno=ENOMEM;
DBUG_RETURN(-1);
}
if (!_ma_fetch_keypage(info,keyinfo,leaf_page,
if (_ma_fetch_keypage(&leaf_page, info,keyinfo, leaf_page.pos,
PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, leaf_buff,
0, &leaf_page_link))
0))
goto err;
}
......@@ -408,28 +402,28 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
if (!nod_flag)
{
DBUG_PRINT("error",("Didn't find key"));
maria_print_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED; /* This should newer happend */
goto err;
}
save_flag=0;
ret_value= d_search(info, key, comp_flag, leaf_page, leaf_buff,
leaf_page_link);
ret_value= d_search(info, key, comp_flag, &leaf_page);
}
else
{ /* Found key */
uint tmp;
uint anc_buff_length= _ma_get_page_used(share, anc_buff);
uint anc_page_flag= _ma_get_keypage_flag(share, anc_buff);
uint anc_buff_length= anc_page->size;
uint anc_page_flag= anc_page->flag;
my_off_t next_block;
if (!(tmp= remove_key(keyinfo, anc_page_flag, nod_flag, keypos, lastkey,
anc_buff + anc_buff_length,
anc_page->buff + anc_buff_length,
&next_block, &s_temp)))
goto err;
anc_page_link->changed= 1;
page_mark_changed(info, anc_page);
anc_buff_length-= tmp;
_ma_store_page_used(share, anc_buff, anc_buff_length);
anc_page->size= anc_buff_length;
page_store_size(share, anc_page);
/*
Log initial changes on pages
......@@ -437,7 +431,7 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
page
*/
if (share->now_transactional &&
_ma_log_delete(info, anc_page, anc_buff, s_temp.key_pos,
_ma_log_delete(anc_page, s_temp.key_pos,
s_temp.changed_length, s_temp.move_length))
DBUG_RETURN(-1);
......@@ -450,23 +444,20 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
/* Page will be written by caller if we return 1 */
DBUG_RETURN(1);
}
if (_ma_write_keypage(info, keyinfo, anc_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS,
anc_buff))
if (_ma_write_keypage(anc_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS))
DBUG_RETURN(-1);
DBUG_RETURN(0);
}
save_flag=1; /* Mark that anc_buff is changed */
ret_value= del(info, key, anc_page, anc_buff,
leaf_page, leaf_buff, leaf_page_link,
ret_value= del(info, key, anc_page, &leaf_page,
keypos, next_block, lastkey);
}
if (ret_value >0)
{
save_flag=1;
if (ret_value == 1)
ret_value= underflow(info, keyinfo, anc_page, anc_buff,
leaf_page, leaf_buff, leaf_page_link, keypos);
ret_value= underflow(info, keyinfo, anc_page, &leaf_page, keypos);
else
{
/* This can only happen with variable length keys */
......@@ -475,33 +466,33 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
last_key.data= lastkey;
last_key.keyinfo= keyinfo;
if (!_ma_get_last_key(&last_key, anc_buff, keypos))
if (!_ma_get_last_key(&last_key, anc_page, keypos))
goto err;
ret_value= _ma_insert(info, key, anc_buff, keypos, anc_page,
last_key.data, (my_off_t) 0, (uchar*) 0,
(MARIA_PINNED_PAGE*) 0, (uchar*) 0, (my_bool) 0);
ret_value= _ma_insert(info, key, anc_page, keypos,
last_key.data,
(MARIA_PAGE*) 0, (uchar*) 0, (my_bool) 0);
}
}
if (ret_value == 0 && _ma_get_page_used(share, anc_buff) >
if (ret_value == 0 && anc_page->size >
(uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
{
/* parent buffer got too big ; We have to split the page */
save_flag=1;
ret_value= _ma_split_page(info, key, anc_page, anc_buff,
ret_value= _ma_split_page(info, key, anc_page,
(uint) (keyinfo->block_length -
KEYPAGE_CHECKSUM_SIZE),
(uchar*) 0, 0, 0, lastkey, 0) | 2;
}
if (save_flag && ret_value != 1)
{
anc_page_link->changed= 1;
ret_value|= _ma_write_keypage(info, keyinfo, anc_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, anc_buff);
page_mark_changed(info, anc_page);
if (_ma_write_keypage(anc_page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
ret_value= -1;
}
else
{
DBUG_DUMP("page", anc_buff, _ma_get_page_used(share, anc_buff));
DBUG_DUMP("page", anc_page->buff, anc_page->size);
}
my_afree(leaf_buff);
DBUG_PRINT("exit",("Return: %d",ret_value));
......@@ -529,8 +520,8 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
@param ret_key_buff Key before keypos in anc_buff
@notes
leaf_buff must be written to disk if retval > 0
anc_buff is not updated on disk. Caller should do this
leaf_page must be written to disk if retval > 0
anc_page is not updated on disk. Caller should do this
@return
@retval < 0 Error
......@@ -542,65 +533,60 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
*/
static int del(MARIA_HA *info, MARIA_KEY *key,
my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link,
MARIA_PAGE *anc_page, MARIA_PAGE *leaf_page,
uchar *keypos, my_off_t next_block, uchar *ret_key_buff)
{
int ret_value,length;
uint a_length, page_flag, nod_flag, leaf_length, new_leaf_length;
my_off_t next_page;
uchar keybuff[MARIA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key;
uchar *anc_buff;
MARIA_KEY_PARAM s_temp;
MARIA_PINNED_PAGE *next_page_link;
MARIA_KEY tmp_key;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_KEY ret_key;
MARIA_PAGE next_page;
DBUG_ENTER("del");
DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", (long) leaf_page,
(ulong) keypos));
DBUG_DUMP("leaf_buff", leaf_page->buff, leaf_page->size);
page_flag= _ma_get_keypage_flag(share, leaf_buff);
_ma_get_used_and_nod_with_flag(share, page_flag, leaf_buff, leaf_length,
nod_flag);
DBUG_DUMP("leaf_buff", leaf_buff, leaf_length);
page_flag= leaf_page->flag;
leaf_length= leaf_page->size;
nod_flag= leaf_page->node;
endpos= leaf_buff + leaf_length;
endpos= leaf_page->buff + leaf_length;
tmp_key.keyinfo= keyinfo;
tmp_key.data= keybuff;
if (!(key_start= _ma_get_last_key(&tmp_key, leaf_buff, endpos)))
if (!(key_start= _ma_get_last_key(&tmp_key, leaf_page, endpos)))
DBUG_RETURN(-1);
if (nod_flag)
{
next_page= _ma_kpos(nod_flag,endpos);
next_page.pos= _ma_kpos(nod_flag,endpos);
if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MARIA_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1);
if (!_ma_fetch_keypage(info, keyinfo, next_page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, next_buff, 0, &next_page_link))
if (_ma_fetch_keypage(&next_page, info, keyinfo, next_page.pos,
PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, next_buff, 0))
ret_value= -1;
else
{
DBUG_DUMP("next_page", next_buff, _ma_get_page_used(share, next_buff));
if ((ret_value= del(info, key, anc_page, anc_buff, next_page,
next_buff, next_page_link, keypos, next_block,
ret_key_buff)) >0)
DBUG_DUMP("next_page", next_page.buff, next_page.size);
if ((ret_value= del(info, key, anc_page, &next_page,
keypos, next_block, ret_key_buff)) >0)
{
/* Get new length after key was deleted */
endpos=leaf_buff+_ma_get_page_used(share, leaf_buff);
endpos= leaf_page->buff+ leaf_page->size;
if (ret_value == 1)
{
ret_value= underflow(info, keyinfo, leaf_page, leaf_buff, next_page,
next_buff, next_page_link, endpos);
if (ret_value == 0 &&
_ma_get_page_used(share, leaf_buff) >
ret_value= underflow(info, keyinfo, leaf_page, &next_page,
endpos);
if (ret_value == 0 && leaf_page->size >
(uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
{
ret_value= (_ma_split_page(info, key,
leaf_page, leaf_buff,
ret_value= (_ma_split_page(info, key, leaf_page,
(uint) (keyinfo->block_length -
KEYPAGE_CHECKSUM_SIZE),
(uchar*) 0, 0, 0,
......@@ -610,24 +596,23 @@ static int del(MARIA_HA *info, MARIA_KEY *key,
else
{
DBUG_PRINT("test",("Inserting of key when deleting"));
if (!_ma_get_last_key(&tmp_key, leaf_buff, endpos))
if (!_ma_get_last_key(&tmp_key, leaf_page, endpos))
goto err;
ret_value= _ma_insert(info, key, leaf_buff, endpos,
leaf_page, tmp_key.data, (my_off_t) 0,
(uchar*) 0, (MARIA_PINNED_PAGE *) 0,
(uchar*) 0, 0);
ret_value= _ma_insert(info, key, leaf_page, endpos,
tmp_key.data, (MARIA_PAGE *) 0, (uchar*) 0,
0);
}
}
leaf_page_link->changed= 1;
page_mark_changed(info, leaf_page);
/*
If ret_value <> 0, then leaf_page underflowed and caller will have
to handle underflow and write leaf_page to disk.
We can't write it here, as if leaf_page is empty we get an assert
in _ma_write_keypage.
*/
if (ret_value == 0 && _ma_write_keypage(info, keyinfo, leaf_page,
if (ret_value == 0 && _ma_write_keypage(leaf_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, leaf_buff))
DFLT_INIT_HITS))
goto err;
}
my_afree(next_buff);
......@@ -640,15 +625,15 @@ static int del(MARIA_HA *info, MARIA_KEY *key,
happen in quick mode), in which ase it will now temporary have 0 keys
on it. This will be corrected by the caller as we will return 0.
*/
new_leaf_length= (uint) (key_start - leaf_buff);
_ma_store_page_used(share, leaf_buff, new_leaf_length);
new_leaf_length= (uint) (key_start - leaf_page->buff);
leaf_page->size= new_leaf_length;
page_store_size(share, leaf_page);
if (share->now_transactional &&
_ma_log_suffix(info, leaf_page, leaf_buff, leaf_length,
new_leaf_length))
_ma_log_suffix(leaf_page, leaf_length, new_leaf_length))
goto err;
leaf_page_link->changed= 1; /* Safety */
page_mark_changed(info, leaf_page); /* Safety */
if (new_leaf_length <= (info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH :
(uint) keyinfo->underflow_block_length))
{
......@@ -658,15 +643,15 @@ static int del(MARIA_HA *info, MARIA_KEY *key,
else
{
ret_value= 0;
if (_ma_write_keypage(info, keyinfo, leaf_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS,
leaf_buff))
if (_ma_write_keypage(leaf_page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
}
/* Place last key in ancestor page on deleted key position */
a_length= _ma_get_page_used(share, anc_buff);
endpos=anc_buff+a_length;
a_length= anc_page->size;
anc_buff= anc_page->buff;
endpos= anc_buff + a_length;
ret_key.keyinfo= keyinfo;
ret_key.data= ret_key_buff;
......@@ -674,7 +659,7 @@ static int del(MARIA_HA *info, MARIA_KEY *key,
prev_key= 0;
if (keypos != anc_buff+share->keypage_header + share->base.key_reflength)
{
if (!_ma_get_last_key(&ret_key, anc_buff, keypos))
if (!_ma_get_last_key(&ret_key, anc_page, keypos))
goto err;
prev_key= ret_key.data;
}
......@@ -690,17 +675,20 @@ static int del(MARIA_HA *info, MARIA_KEY *key,
key_start= keypos;
if (tmp_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
SEARCH_PAGE_KEY_HAS_TRANSID))
_ma_mark_page_with_transid(share, anc_buff);
{
_ma_mark_page_with_transid(share, anc_page);
}
/* Save pointer to next leaf on parent page */
if (!(*keyinfo->get_key)(&ret_key, page_flag, share->base.key_reflength,
&keypos))
goto err;
_ma_kpointer(info,keypos - share->base.key_reflength,next_block);
_ma_store_page_used(share, anc_buff, a_length + length);
anc_page->size= a_length + length;
page_store_size(share, anc_page);
if (share->now_transactional &&
_ma_log_add(info, anc_page, anc_buff, a_length,
_ma_log_add(anc_page, a_length,
key_start, s_temp.changed_length, s_temp.move_length, 1))
goto err;
......@@ -733,10 +721,8 @@ static int del(MARIA_HA *info, MARIA_KEY *key,
@retval -1 error
*/
static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link,
static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
MARIA_PAGE *anc_page, MARIA_PAGE *leaf_page,
uchar *keypos)
{
int t_length;
......@@ -744,35 +730,36 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint next_buff_length, new_buff_length, key_reflength;
uint unchanged_leaf_length, new_leaf_length, new_anc_length;
uint anc_page_flag, page_flag;
my_off_t next_page;
uchar anc_key_buff[MARIA_MAX_KEY_BUFF], leaf_key_buff[MARIA_MAX_KEY_BUFF];
uchar *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*prev_key;
uchar *endpos, *next_keypos, *anc_pos, *half_pos, *prev_key;
uchar *anc_buff, *leaf_buff;
uchar *after_key, *anc_end_pos;
MARIA_KEY_PARAM key_deleted, key_inserted;
MARIA_SHARE *share= info->s;
MARIA_PINNED_PAGE *next_page_link;
my_bool first_key;
MARIA_KEY tmp_key, anc_key, leaf_key;
MARIA_PAGE next_page;
DBUG_ENTER("underflow");
DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page,
DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page->pos,
(ulong) keypos));
DBUG_DUMP("anc_buff", anc_buff, _ma_get_page_used(share, anc_buff));
DBUG_DUMP("leaf_buff", leaf_buff, _ma_get_page_used(share, leaf_buff));
DBUG_DUMP("anc_buff", anc_page->buff, anc_page->size);
DBUG_DUMP("leaf_buff", leaf_page->buff, leaf_page->size);
anc_page_flag= _ma_get_keypage_flag(share, anc_buff);
buff=info->buff;
anc_page_flag= anc_page->flag;
anc_buff= anc_page->buff;
leaf_buff= leaf_page->buff;
info->keyread_buff_used=1;
next_keypos=keypos;
nod_flag= _ma_test_if_nod(share, leaf_buff);
nod_flag= leaf_page->node;
p_length= nod_flag+share->keypage_header;
anc_length= _ma_get_page_used(share, anc_buff);
leaf_length= _ma_get_page_used(share, leaf_buff);
key_reflength=share->base.key_reflength;
anc_length= anc_page->size;
leaf_length= leaf_page->size;
key_reflength= share->base.key_reflength;
if (share->keyinfo+info->lastinx == keyinfo)
info->page_changed=1;
first_key= keypos == anc_buff + share->keypage_header + key_reflength;
tmp_key.data= buff;
tmp_key.data= info->buff;
anc_key.data= anc_key_buff;
leaf_key.data= leaf_key_buff;
tmp_key.keyinfo= leaf_key.keyinfo= anc_key.keyinfo= keyinfo;
......@@ -791,85 +778,89 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
*/
if (keyinfo->flag & HA_BINARY_PACK_KEY)
{
if (!(next_keypos= _ma_get_key(&tmp_key, anc_buff, keypos)))
if (!(next_keypos= _ma_get_key(&tmp_key, anc_page, keypos)))
goto err;
}
else
{
/* Avoid length error check if packed key */
tmp_key.data[0]= tmp_key.data[1]= 0;
/* Got to end of found key */
buff[0]=buff[1]=0; /* Avoid length error check if packed key */
if (!(*keyinfo->get_key)(&tmp_key, anc_page_flag, key_reflength,
&next_keypos))
goto err;
}
next_page= _ma_kpos(key_reflength,next_keypos);
if (!_ma_fetch_keypage(info,keyinfo, next_page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, buff, 0, &next_page_link))
next_page.pos= _ma_kpos(key_reflength, next_keypos);
if (_ma_fetch_keypage(&next_page, info, keyinfo, next_page.pos,
PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, info->buff, 0))
goto err;
next_buff_length= _ma_get_page_used(share, buff);
next_page_flag= _ma_get_keypage_flag(share,buff);
DBUG_DUMP("next", buff, next_buff_length);
next_buff_length= next_page.size;
next_page_flag= next_page.flag;
DBUG_DUMP("next", next_page.buff, next_page.size);
/* find keys to make a big key-page */
bmove(next_keypos-key_reflength, buff + share->keypage_header,
bmove(next_keypos-key_reflength, next_page.buff + share->keypage_header,
key_reflength);
if (!_ma_get_last_key(&anc_key, anc_buff, next_keypos) ||
!_ma_get_last_key(&leaf_key, leaf_buff, leaf_buff+leaf_length))
if (!_ma_get_last_key(&anc_key, anc_page, next_keypos) ||
!_ma_get_last_key(&leaf_key, leaf_page, leaf_buff+leaf_length))
goto err;
/* merge pages and put parting key from anc_buff between */
/* merge pages and put parting key from anc_page between */
prev_key= (leaf_length == p_length ? (uchar*) 0 : leaf_key.data);
t_length= (*keyinfo->pack_key)(&anc_key, nod_flag, buff+p_length,
t_length= (*keyinfo->pack_key)(&anc_key, nod_flag, next_page.buff+p_length,
prev_key, prev_key, &key_inserted);
tmp_length= next_buff_length - p_length;
endpos= buff+tmp_length+leaf_length+t_length;
/* buff will always be larger than before !*/
bmove_upp(endpos, buff + next_buff_length, tmp_length);
memcpy(buff, leaf_buff,(size_t) leaf_length);
(*keyinfo->store_key)(keyinfo, buff+leaf_length, &key_inserted);
buff_length= (uint) (endpos-buff);
_ma_store_page_used(share, buff, buff_length);
endpos= next_page.buff + tmp_length + leaf_length + t_length;
/* next_page.buff will always be larger than before !*/
bmove_upp(endpos, next_page.buff + next_buff_length, tmp_length);
memcpy(next_page.buff, leaf_buff,(size_t) leaf_length);
(*keyinfo->store_key)(keyinfo, next_page.buff+leaf_length, &key_inserted);
buff_length= (uint) (endpos - next_page.buff);
/* Set page flag from combination of both key pages and parting key */
page_flag= (next_page_flag |
_ma_get_keypage_flag(share, leaf_buff));
page_flag= next_page_flag | leaf_page->flag;
if (anc_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
SEARCH_PAGE_KEY_HAS_TRANSID))
page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
_ma_store_keypage_flag(share, buff, page_flag);
/* remove key from anc_buff */
next_page.size= buff_length;
next_page.flag= page_flag;
page_store_info(share, &next_page);
/* remove key from anc_page */
if (!(s_length=remove_key(keyinfo, anc_page_flag, key_reflength, keypos,
anc_key_buff, anc_buff+anc_length,
(my_off_t *) 0, &key_deleted)))
goto err;
new_anc_length= anc_length - s_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
anc_page->size= new_anc_length;
page_store_size(share, anc_page);
if (buff_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
{
/* All keys fitted into one page */
next_page_link->changed= 1;
if (_ma_dispose(info, next_page, 0))
page_mark_changed(info, &next_page);
if (_ma_dispose(info, next_page.pos, 0))
goto err;
memcpy(leaf_buff, buff, (size_t) buff_length);
memcpy(leaf_buff, next_page.buff, (size_t) buff_length);
leaf_page->size= next_page.size;
leaf_page->flag= next_page.flag;
if (share->now_transactional)
{
/* Log changes to parent page */
if (_ma_log_delete(info, anc_page, anc_buff, key_deleted.key_pos,
if (_ma_log_delete(anc_page, key_deleted.key_pos,
key_deleted.changed_length,
key_deleted.move_length))
goto err;
/*
Log changes to leaf page. Data for leaf page is in buff
Log changes to leaf page. Data for leaf page is in leaf_buff
which contains original leaf_buff, parting key and next_buff
*/
if (_ma_log_suffix(info, leaf_page, leaf_buff,
leaf_length, buff_length))
if (_ma_log_suffix(leaf_page, leaf_length, buff_length))
goto err;
}
}
......@@ -879,9 +870,9 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
Balancing didn't free a page, so we have to split 'buff' into two
pages:
- Find key in middle of buffer
- Store everything before key in 'leaf_buff'
- Pack key into anc_buff at position of deleted key
Note that anc_buff may overflow! (is handled by caller)
- Store everything before key in 'leaf_page'
- Pack key into anc_page at position of deleted key
Note that anc_page may overflow! (is handled by caller)
- Store remaining keys in next_page (buff)
*/
MARIA_KEY_PARAM anc_key_inserted;
......@@ -891,23 +882,24 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
DBUG_PRINT("test",("anc_buff: 0x%lx anc_end_pos: 0x%lx",
(long) anc_buff, (long) anc_end_pos));
if (!first_key && !_ma_get_last_key(&anc_key, anc_buff, keypos))
if (!first_key && !_ma_get_last_key(&anc_key, anc_page, keypos))
goto err;
if (!(half_pos= _ma_find_half_pos(info, &leaf_key, nod_flag, buff,
&after_key)))
if (!(half_pos= _ma_find_half_pos(&leaf_key, &next_page, &after_key)))
goto err;
new_leaf_length= (uint) (half_pos-buff);
memcpy(leaf_buff, buff, (size_t) new_leaf_length);
_ma_store_page_used(share, leaf_buff, new_leaf_length);
_ma_store_keypage_flag(share, leaf_buff, page_flag);
new_leaf_length= (uint) (half_pos - next_page.buff);
memcpy(leaf_buff, next_page.buff, (size_t) new_leaf_length);
leaf_page->size= new_leaf_length;
leaf_page->flag= page_flag;
page_store_info(share, leaf_page);
/* Correct new keypointer to leaf_page */
half_pos=after_key;
_ma_kpointer(info,
leaf_key.data+leaf_key.data_length + leaf_key.ref_length,
next_page);
leaf_key.data + leaf_key.data_length + leaf_key.ref_length,
next_page.pos);
/* Save key in anc_buff */
/* Save key in anc_page */
prev_key= (first_key ? (uchar*) 0 : anc_key.data);
t_length= (*keyinfo->pack_key)(&leaf_key, key_reflength,
(keypos == anc_end_pos ? (uchar*) 0 :
......@@ -920,14 +912,16 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
bmove(keypos,keypos-t_length,(uint) (anc_end_pos-keypos)+t_length);
(*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted);
new_anc_length+= t_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
anc_page->size= new_anc_length;
page_store_size(share, anc_page);
if (leaf_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
SEARCH_PAGE_KEY_HAS_TRANSID))
_ma_mark_page_with_transid(share, anc_buff);
_ma_mark_page_with_transid(share, anc_page);
/* Store key first in new page */
if (nod_flag)
bmove(buff+share->keypage_header, half_pos-nod_flag,
bmove(next_page.buff + share->keypage_header, half_pos-nod_flag,
(size_t) nod_flag);
if (!(*keyinfo->get_key)(&leaf_key, page_flag, nod_flag, &half_pos))
goto err;
......@@ -935,11 +929,12 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
(uchar*) 0, (uchar*) 0,
&key_inserted);
/* t_length will always be > 0 for a new page !*/
tmp_length= (size_t) ((buff + buff_length) - half_pos);
bmove(buff+p_length+t_length, half_pos, tmp_length);
(*keyinfo->store_key)(keyinfo,buff+p_length, &key_inserted);
tmp_length= (size_t) ((next_page.buff + buff_length) - half_pos);
bmove(next_page.buff + p_length + t_length, half_pos, tmp_length);
(*keyinfo->store_key)(keyinfo, next_page.buff + p_length, &key_inserted);
new_buff_length= tmp_length + t_length + p_length;
_ma_store_page_used(share, buff, new_buff_length);
next_page.size= new_buff_length;
page_store_size(share, &next_page);
/* keypage flag is already up to date */
if (share->now_transactional)
......@@ -952,8 +947,7 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
ma_log_add ensures that we don't log changes that is outside of
key block size, as the REDO code can't handle that
*/
if (_ma_log_add(info, anc_page, anc_buff, anc_length,
keypos,
if (_ma_log_add(anc_page, anc_length, keypos,
anc_key_inserted.move_length +
max(anc_key_inserted.changed_length -
anc_key_inserted.move_length,
......@@ -967,8 +961,7 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
This contains original data with new data added at end
*/
DBUG_ASSERT(leaf_length <= new_leaf_length);
if (_ma_log_suffix(info, leaf_page, leaf_buff, leaf_length,
new_leaf_length))
if (_ma_log_suffix(leaf_page, leaf_length, new_leaf_length))
goto err;
/*
Log changes to next page
......@@ -989,22 +982,19 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
*/
DBUG_ASSERT(new_buff_length <= next_buff_length);
if (_ma_log_prefix(info, next_page, buff,
key_inserted.changed_length,
if (_ma_log_prefix(&next_page, key_inserted.changed_length,
(int) (new_buff_length - next_buff_length)))
goto err;
}
next_page_link->changed= 1;
if (_ma_write_keypage(info, keyinfo, next_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS,
buff))
page_mark_changed(info, &next_page);
if (_ma_write_keypage(&next_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS))
goto err;
}
leaf_page_link->changed= 1;
if (_ma_write_keypage(info, keyinfo, leaf_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS,
leaf_buff))
page_mark_changed(info, leaf_page);
if (_ma_write_keypage(leaf_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS))
goto err;
DBUG_RETURN(new_anc_length <=
((info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH :
......@@ -1013,16 +1003,16 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
DBUG_PRINT("test",("use left page"));
keypos= _ma_get_last_key(&anc_key, anc_buff, keypos);
keypos= _ma_get_last_key(&anc_key, anc_page, keypos);
if (!keypos)
goto err;
next_page= _ma_kpos(key_reflength,keypos);
if (!_ma_fetch_keypage(info, keyinfo, next_page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, buff, 0, &next_page_link))
next_page.pos= _ma_kpos(key_reflength,keypos);
if (_ma_fetch_keypage(&next_page, info, keyinfo, next_page.pos,
PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, info->buff, 0))
goto err;
buff_length= _ma_get_page_used(share, buff);
endpos= buff + buff_length;
DBUG_DUMP("prev",buff,buff_length);
buff_length= next_page.size;
endpos= next_page.buff + buff_length;
DBUG_DUMP("prev", next_page.buff, next_page.size);
/* find keys to make a big key-page */
bmove(next_keypos - key_reflength, leaf_buff + share->keypage_header,
......@@ -1031,10 +1021,10 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
if (!(*keyinfo->get_key)(&anc_key, anc_page_flag, key_reflength,
&next_keypos))
goto err;
if (!_ma_get_last_key(&leaf_key, buff, endpos))
if (!_ma_get_last_key(&leaf_key, &next_page, endpos))
goto err;
/* merge pages and put parting key from anc_buff between */
/* merge pages and put parting key from anc_page between */
prev_key= (leaf_length == p_length ? (uchar*) 0 : leaf_key.data);
t_length=(*keyinfo->pack_key)(&anc_key, nod_flag,
(leaf_length == p_length ?
......@@ -1055,16 +1045,17 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
key_inserted.move_length);
new_buff_length= buff_length + leaf_length - p_length + t_length;
_ma_store_page_used(share, buff, new_buff_length);
page_flag= (_ma_get_keypage_flag(share, buff) |
_ma_get_keypage_flag(share, leaf_buff));
page_flag= next_page.flag | leaf_page->flag;
if (anc_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
SEARCH_PAGE_KEY_HAS_TRANSID))
page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
_ma_store_keypage_flag(share, buff, page_flag);
/* remove key from anc_buff */
next_page.size= new_buff_length;
next_page.flag= page_flag;
page_store_info(share, &next_page);
/* remove key from anc_page */
if (!(s_length= remove_key(keyinfo, anc_page_flag, key_reflength, keypos,
anc_key_buff,
anc_buff+anc_length, (my_off_t *) 0,
......@@ -1072,20 +1063,21 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
goto err;
new_anc_length= anc_length - s_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
anc_page->size= new_anc_length;
page_store_size(share, anc_page);
if (new_buff_length <= (uint) (keyinfo->block_length -
KEYPAGE_CHECKSUM_SIZE))
{
/* All keys fitted into one page */
leaf_page_link->changed= 1;
if (_ma_dispose(info, leaf_page, 0))
page_mark_changed(info, leaf_page);
if (_ma_dispose(info, leaf_page->pos, 0))
goto err;
if (share->now_transactional)
{
/* Log changes to parent page */
if (_ma_log_delete(info, anc_page, anc_buff, key_deleted.key_pos,
if (_ma_log_delete(anc_page, key_deleted.key_pos,
key_deleted.changed_length, key_deleted.move_length))
goto err;
......@@ -1093,19 +1085,18 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
Log changes to next page. Data for leaf page is in buff
that contains original leaf_buff, parting key and next_buff
*/
if (_ma_log_suffix(info, next_page, buff,
buff_length, new_buff_length))
if (_ma_log_suffix(&next_page, buff_length, new_buff_length))
goto err;
}
}
else
{
/*
Balancing didn't free a page, so we have to split 'buff' into two
Balancing didn't free a page, so we have to split 'next_page' into two
pages
- Find key in middle of buffer (buff)
- Pack key at half_buff into anc_buff at position of deleted key
Note that anc_buff may overflow! (is handled by caller)
- Pack key at half_buff into anc_page at position of deleted key
Note that anc_page may overflow! (is handled by caller)
- Move everything after middlekey to 'leaf_buff'
- Shorten buff at 'endpos'
*/
......@@ -1116,19 +1107,18 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
anc_pos= 0; /* First key */
else
{
if (!_ma_get_last_key(&anc_key, anc_buff, keypos))
if (!_ma_get_last_key(&anc_key, anc_page, keypos))
goto err;
anc_pos= anc_key.data;
}
if (!(endpos= _ma_find_half_pos(info, &leaf_key, nod_flag, buff,
&half_pos)))
if (!(endpos= _ma_find_half_pos(&leaf_key, &next_page, &half_pos)))
goto err;
/* Correct new keypointer to leaf_page */
_ma_kpointer(info,leaf_key.data + leaf_key.data_length +
leaf_key.ref_length, leaf_page);
leaf_key.ref_length, leaf_page->pos);
/* Save key in anc_buff */
/* Save key in anc_page */
DBUG_DUMP("anc_buff", anc_buff, new_anc_length);
DBUG_DUMP_KEY("key_to_anc", &leaf_key);
anc_end_pos= anc_buff + new_anc_length;
......@@ -1144,10 +1134,12 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
bmove(keypos,keypos-t_length,(uint) (anc_end_pos-keypos)+t_length);
(*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted);
new_anc_length+= t_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
anc_page->size= new_anc_length;
page_store_size(share, anc_page);
if (leaf_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
SEARCH_PAGE_KEY_HAS_TRANSID))
_ma_mark_page_with_transid(share, anc_buff);
_ma_mark_page_with_transid(share, anc_page);
/* Store first key on new page */
if (nod_flag)
......@@ -1159,15 +1151,19 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
t_length=(*keyinfo->pack_key)(&leaf_key, nod_flag, (uchar*) 0,
(uchar*) 0, (uchar*) 0, &key_inserted);
/* t_length will always be > 0 for a new page !*/
tmp_length= (size_t) ((buff + new_buff_length) - half_pos);
tmp_length= (size_t) ((next_page.buff + new_buff_length) - half_pos);
DBUG_PRINT("info",("t_length: %d length: %d",t_length, (int) tmp_length));
bmove(leaf_buff+p_length+t_length, half_pos, tmp_length);
(*keyinfo->store_key)(keyinfo,leaf_buff+p_length, &key_inserted);
new_leaf_length= tmp_length + t_length + p_length;
_ma_store_page_used(share, leaf_buff, new_leaf_length);
_ma_store_keypage_flag(share, leaf_buff, page_flag);
new_buff_length= (uint) (endpos - buff);
_ma_store_page_used(share, buff, new_buff_length);
leaf_page->size= new_leaf_length;
leaf_page->flag= page_flag;
page_store_info(share, leaf_page);
new_buff_length= (uint) (endpos - next_page.buff);
next_page.size= new_buff_length;
page_store_size(share, &next_page);
if (share->now_transactional)
{
......@@ -1179,8 +1175,7 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
ma_log_add() ensures that we don't log changes that is outside of
key block size, as the REDO code can't handle that
*/
if (_ma_log_add(info, anc_page, anc_buff, anc_length,
keypos,
if (_ma_log_add(anc_page, anc_length, keypos,
anc_key_inserted.move_length +
max(anc_key_inserted.changed_length -
anc_key_inserted.move_length,
......@@ -1194,8 +1189,7 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
This contains original data with new data added first
*/
DBUG_ASSERT(leaf_length <= new_leaf_length);
if (_ma_log_prefix(info, leaf_page, leaf_buff,
new_leaf_length - unchanged_leaf_length,
if (_ma_log_prefix(leaf_page, new_leaf_length - unchanged_leaf_length,
(int) (new_leaf_length - leaf_length)))
goto err;
/*
......@@ -1204,20 +1198,18 @@ static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
*/
DBUG_ASSERT(new_buff_length <= buff_length);
if (_ma_log_suffix(info, next_page, buff,
buff_length, new_buff_length))
if (_ma_log_suffix(&next_page, buff_length, new_buff_length))
goto err;
}
leaf_page_link->changed= 1;
if (_ma_write_keypage(info, keyinfo, leaf_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS,
leaf_buff))
page_mark_changed(info, leaf_page);
if (_ma_write_keypage(leaf_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS))
goto err;
}
next_page_link->changed= 1;
if (_ma_write_keypage(info, keyinfo, next_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS, buff))
page_mark_changed(info, &next_page);
if (_ma_write_keypage(&next_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS))
goto err;
DBUG_RETURN(new_anc_length <=
......@@ -1412,24 +1404,25 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag,
*/
my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, const uchar *buff,
const uchar *key_pos, uint changed_length,
uint move_length)
my_bool _ma_log_delete(MARIA_PAGE *ma_page, const uchar *key_pos,
uint changed_length, uint move_length)
{
LSN lsn;
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 9 + 7], *log_pos;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
MARIA_SHARE *share= info->s;
uint translog_parts;
uint offset= (uint) (key_pos - buff);
uint offset= (uint) (key_pos - ma_page->buff);
MARIA_HA *info= ma_page->info;
MARIA_SHARE *share= info->s;
my_off_t page;
DBUG_ENTER("_ma_log_delete");
DBUG_PRINT("enter", ("page: %lu changed_length: %u move_length: %d",
(ulong) page, changed_length, move_length));
(ulong) ma_page->pos, changed_length, move_length));
DBUG_ASSERT(share->now_transactional && move_length);
DBUG_ASSERT(offset + changed_length <= _ma_get_page_used(share, buff));
DBUG_ASSERT(offset + changed_length <= ma_page->size);
/* Store address of new root page */
page/= share->block_size;
page= ma_page->pos / share->block_size;
page_store(log_data + FILEID_STORE_SIZE, page);
log_pos= log_data+ FILEID_STORE_SIZE + PAGE_STORE_SIZE;
log_pos[0]= KEY_OP_OFFSET;
......@@ -1444,15 +1437,16 @@ my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, const uchar *buff,
int2store(log_pos+1, changed_length);
log_pos+= 3;
translog_parts= 2;
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= buff + offset;
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= ma_page->buff + offset;
log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length;
}
#ifdef EXTRA_DEBUG_KEY_CHANGES
{
int page_length= _ma_get_page_used(share, buff);
int page_length= ma_page->size;
ha_checksum crc;
crc= my_checksum(0, buff + LSN_STORE_SIZE, page_length - LSN_STORE_SIZE);
crc= my_checksum(0, ma_page->buff + LSN_STORE_SIZE,
page_length - LSN_STORE_SIZE);
log_pos[0]= KEY_OP_CHECK;
int2store(log_pos+1, page_length);
int4store(log_pos+3, crc);
......@@ -1483,7 +1477,7 @@ my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, const uchar *buff,
Logging of undos
****************************************************************************/
int _ma_write_undo_key_delete(MARIA_HA *info, const MARIA_KEY *key,
my_bool _ma_write_undo_key_delete(MARIA_HA *info, const MARIA_KEY *key,
my_off_t new_root, LSN *res_lsn)
{
MARIA_SHARE *share= info->s;
......
......@@ -220,9 +220,12 @@ int _ma_ft_update(MARIA_HA *info, uint keynr, uchar *keybuf,
{
MARIA_KEY key;
_ma_ft_make_key(info, &key, keynr, keybuf, old_word, pos);
if ((error= _ma_ck_delete(info, &key)))
if (_ma_ck_delete(info, &key))
{
error= -1;
goto err;
}
}
if (cmp > 0 || cmp2)
{
MARIA_KEY key;
......@@ -317,6 +320,7 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, MARIA_KEY *key)
uint length, key_length;
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
MARIA_KEY tmp_key;
MARIA_PAGE page;
DBUG_ENTER("_ma_ft_convert_to_ft2");
/* we'll generate one pageful at once, and insert the rest one-by-one */
......@@ -344,9 +348,11 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, MARIA_KEY *key)
@todo RECOVERY BUG this is not logged yet. Ok as this code is never
called, but soon it will be.
*/
if ((root= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR ||
_ma_write_keypage(info, keyinfo, root, page_link->write_lock,
DFLT_INIT_HITS, info->buff))
if ((root= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR)
DBUG_RETURN(-1);
_ma_page_setup(&page, info, keyinfo, root, info->buff);
if (_ma_write_keypage(&page, page_link->write_lock, DFLT_INIT_HITS))
DBUG_RETURN(-1);
/* inserting the rest of key values */
......
......@@ -295,19 +295,21 @@ my_bool write_hook_for_undo_key_delete(enum translog_record_type type,
Write log entry for page that has got data added or deleted at start of page
*/
my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
uchar *buff, uint changed_length,
my_bool _ma_log_prefix(MARIA_PAGE *ma_page, uint changed_length,
int move_length)
{
uint translog_parts;
LSN lsn;
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7 + 7 + 2], *log_pos;
uchar *buff= ma_page->buff;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
pgcache_page_no_t page;
MARIA_HA *info= ma_page->info;
DBUG_ENTER("_ma_log_prefix");
DBUG_PRINT("enter", ("page: %lu changed_length: %u move_length: %d",
(ulong) page, changed_length, move_length));
(ulong) ma_page->pos, changed_length, move_length));
page/= info->s->block_size;
page= ma_page->pos / info->s->block_size;
log_pos= log_data + FILEID_STORE_SIZE;
page_store(log_pos, page);
log_pos+= PAGE_STORE_SIZE;
......@@ -357,7 +359,7 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
#ifdef EXTRA_DEBUG_KEY_CHANGES
{
int page_length= _ma_get_page_used(info->s, buff);
int page_length= ma_page->size;
ha_checksum crc;
crc= my_checksum(0, buff + LSN_STORE_SIZE, page_length - LSN_STORE_SIZE);
log_pos[0]= KEY_OP_CHECK;
......@@ -386,19 +388,21 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
Write log entry for page that has got data added or deleted at end of page
*/
my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page,
uchar *buff, uint org_length, uint new_length)
my_bool _ma_log_suffix(MARIA_PAGE *ma_page, uint org_length, uint new_length)
{
LSN lsn;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10 + 7 + 2], *log_pos;
uchar *buff= ma_page->buff;
int diff;
uint translog_parts, extra_length;
MARIA_HA *info= ma_page->info;
pgcache_page_no_t page;
DBUG_ENTER("_ma_log_suffix");
DBUG_PRINT("enter", ("page: %lu org_length: %u new_length: %u",
(ulong) page, org_length, new_length));
(ulong) ma_page->pos, org_length, new_length));
page/= info->s->block_size;
page= ma_page->pos / info->s->block_size;
log_pos= log_data + FILEID_STORE_SIZE;
page_store(log_pos, page);
......@@ -459,8 +463,8 @@ my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page,
/**
@brief Log that a key was added to the page
@param buff Page buffer
@param buff_length Original length of buff (before key was added)
@param ma_page Changed page
@param org_page_length Length of data in page before key was added
@note
If handle_overflow is set, then we have to protect against
......@@ -469,22 +473,25 @@ my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page,
in memory temporary contains more data than block_size
*/
my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
uint buff_length, uchar *key_pos,
my_bool _ma_log_add(MARIA_PAGE *ma_page,
uint org_page_length, uchar *key_pos,
uint changed_length, int move_length,
my_bool handle_overflow __attribute__ ((unused)))
{
LSN lsn;
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3 + 3 + 3 + 3 + 7 + 2];
uchar *log_pos;
uchar *buff= ma_page->buff;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
MARIA_HA *info= ma_page->info;
uint offset= (uint) (key_pos - buff);
uint page_length= info->s->block_size - KEYPAGE_CHECKSUM_SIZE;
uint translog_parts;
pgcache_page_no_t page_pos;
DBUG_ENTER("_ma_log_add");
DBUG_PRINT("enter", ("page: %lu org_page_length: %u changed_length: %u "
"move_length: %d",
(ulong) page, buff_length, changed_length,
(ulong) ma_page->pos, org_page_length, changed_length,
move_length));
DBUG_ASSERT(info->s->now_transactional);
......@@ -493,20 +500,20 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
to do the page
*/
log_pos= log_data + FILEID_STORE_SIZE;
page/= info->s->block_size;
page_store(log_pos, page);
page_pos= ma_page->pos / info->s->block_size;
page_store(log_pos, page_pos);
log_pos+= PAGE_STORE_SIZE;
/* Store keypage_flag */
*log_pos++= KEY_OP_SET_PAGEFLAG;
*log_pos++= buff[KEYPAGE_TRANSFLAG_OFFSET];
if (buff_length + move_length > page_length)
if (org_page_length + move_length > page_length)
{
/*
Overflow. Cut either key or data from page end so that key fits
The code that splits the too big page will ignore logging any
data over page_length
data over org_page_length
*/
DBUG_ASSERT(handle_overflow);
if (offset + changed_length > page_length)
......@@ -516,15 +523,15 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
}
else
{
uint diff= buff_length + move_length - page_length;
uint diff= org_page_length + move_length - page_length;
log_pos[0]= KEY_OP_DEL_SUFFIX;
int2store(log_pos+1, diff);
log_pos+= 3;
buff_length= page_length - move_length;
org_page_length= page_length - move_length;
}
}
if (offset == buff_length)
if (offset == org_page_length)
log_pos[0]= KEY_OP_ADD_SUFFIX;
else
{
......@@ -553,8 +560,8 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
{
MARIA_SHARE *share= info->s;
ha_checksum crc;
uint save_page_length= _ma_get_page_used(share, buff);
uint new_length= buff_length + move_length;
uint save_page_length= ma_page->size;
uint new_length= org_page_length + move_length;
_ma_store_page_used(share, buff, new_length);
crc= my_checksum(0, buff + LSN_STORE_SIZE, new_length - LSN_STORE_SIZE);
log_pos[0]= KEY_OP_CHECK;
......@@ -822,22 +829,22 @@ uint _ma_apply_redo_index(MARIA_HA *info,
LSN lsn, const uchar *header, uint head_length)
{
MARIA_SHARE *share= info->s;
pgcache_page_no_t page= page_korr(header);
pgcache_page_no_t page_pos= page_korr(header);
MARIA_PINNED_PAGE page_link;
uchar *buff;
const uchar *header_end= header + head_length;
uint page_offset= 0;
uint nod_flag, page_length, keypage_header;
uint page_offset= 0, org_page_length;
uint nod_flag, page_length, keypage_header, keynr;
int result;
uint org_page_length;
MARIA_PAGE page;
DBUG_ENTER("_ma_apply_redo_index");
DBUG_PRINT("enter", ("page: %lu", (ulong) page));
DBUG_PRINT("enter", ("page: %lu", (ulong) page_pos));
/* Set header to point at key data */
header+= PAGE_STORE_SIZE;
if (!(buff= pagecache_read(share->pagecache, &share->kfile,
page, 0, 0,
page_pos, 0, 0,
PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE,
&page_link.link)))
{
......@@ -852,9 +859,12 @@ uint _ma_apply_redo_index(MARIA_HA *info,
goto err;
}
_ma_get_used_and_nod(share, buff, page_length, nod_flag);
keynr= _ma_get_keynr(share, buff);
_ma_page_setup(&page, info, share->keyinfo + keynr, page_pos, buff);
nod_flag= page.node;
org_page_length= page_length= page.size;
keypage_header= share->keypage_header;
org_page_length= page_length;
DBUG_PRINT("redo", ("page_length: %u", page_length));
/* Apply modifications to page */
......@@ -1007,16 +1017,15 @@ uint _ma_apply_redo_index(MARIA_HA *info,
case KEY_OP_COMPACT_PAGE:
{
TrID transid= transid_korr(header);
uint keynr= _ma_get_keynr(share, buff);
DBUG_PRINT("redo", ("key_op_compact_page"));
header+= TRANSID_SIZE;
if (_ma_compact_keypage(info, share->keyinfo + keynr, (my_off_t) 0,
buff, transid))
if (_ma_compact_keypage(&page, transid))
{
result= 1;
goto err;
}
page_length= page.size;
}
case KEY_OP_NONE:
default:
......@@ -1028,6 +1037,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
DBUG_ASSERT(header == header_end);
/* Write modified page */
page.size= page_length;
_ma_store_page_used(share, buff, page_length);
/*
......
......@@ -49,7 +49,7 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn,
int _ma_write_undo_key_insert(MARIA_HA *info, const MARIA_KEY *key,
my_off_t *root, my_off_t new_root,
LSN *res_lsn);
int _ma_write_undo_key_delete(MARIA_HA *info, const MARIA_KEY *key,
my_bool _ma_write_undo_key_delete(MARIA_HA *info, const MARIA_KEY *key,
my_off_t new_root, LSN *res_lsn);
my_bool write_hook_for_clr_end(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info, LSN *lsn,
......@@ -65,23 +65,16 @@ extern my_bool write_hook_for_undo_key_delete(enum translog_record_type type,
LSN *lsn, void *hook_arg);
void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn);
my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
uchar *buff, uint changed_length,
int move_length);
my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page,
uchar *buff, uint org_length,
my_bool _ma_log_prefix(MARIA_PAGE *page, uint changed_length, int move_length);
my_bool _ma_log_suffix(MARIA_PAGE *page, uint org_length,
uint new_length);
my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
uint buff_length, uchar *key_pos,
my_bool _ma_log_add(MARIA_PAGE *page, uint buff_length, uchar *key_pos,
uint changed_length, int move_length,
my_bool handle_overflow);
my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, const uchar *buff,
const uchar *key_pos, uint changed_length,
uint move_length);
my_bool _ma_log_change(MARIA_HA *info, my_off_t page, const uchar *buff,
const uchar *key_pos, uint length);
my_bool _ma_log_new(MARIA_HA *info, my_off_t page, const uchar *buff,
uint page_length, uint key_nr, my_bool root_page);
my_bool _ma_log_delete(MARIA_PAGE *page, const uchar *key_pos,
uint changed_length, uint move_length);
my_bool _ma_log_change(MARIA_PAGE *page, const uchar *key_pos, uint length);
my_bool _ma_log_new(MARIA_PAGE *page, my_bool root_page);
uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn,
const uchar *header, uint length);
......
......@@ -44,14 +44,50 @@
#include "trnman.h"
#include "ma_key_recover.h"
/* Fetch a key-page in memory */
/**
Fill MARIA_PAGE structure for usage with _ma_write_keypage
*/
void _ma_page_setup(MARIA_PAGE *page, MARIA_HA *info,
const MARIA_KEYDEF *keyinfo, my_off_t pos,
uchar *buff)
{
MARIA_SHARE *share= info->s;
page->info= info;
page->keyinfo= keyinfo;
page->buff= buff;
page->pos= pos;
page->size= _ma_get_page_used(share, buff);
page->flag= _ma_get_keypage_flag(share, buff);
page->node= ((page->flag & KEYPAGE_FLAG_ISNOD) ?
share->base.key_reflength : 0);
}
/**
Fetch a key-page in memory
@fn _ma_fetch_keypage()
@param page Fill this struct with information about read page
@param info Maria handler
@param keyinfo Key definition for used key
@param pos Position for page (in bytes)
@param lock Lock type for page
@param level Importance of page; Priority for page cache
@param buff Buffer to use for page
@param return_buffer Set to 1 if we want to force useage of buff
uchar *_ma_fetch_keypage(register MARIA_HA *info,
const MARIA_KEYDEF *keyinfo __attribute__ ((unused)),
@return
@retval 0 ok
@retval 1 error
*/
my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info,
const MARIA_KEYDEF *keyinfo,
my_off_t pos, enum pagecache_page_lock lock,
int level, uchar *buff,
int return_buffer __attribute__ ((unused)),
MARIA_PINNED_PAGE **page_link_res)
my_bool return_buffer __attribute__ ((unused)))
{
uchar *tmp;
MARIA_PINNED_PAGE page_link;
......@@ -70,9 +106,7 @@ uchar *_ma_fetch_keypage(register MARIA_HA *info,
page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
page_link.changed= 0;
push_dynamic(&info->pinned_pages, (void*) &page_link);
*page_link_res= dynamic_element(&info->pinned_pages,
info->pinned_pages.elements-1,
MARIA_PINNED_PAGE *);
page->link_offset= info->pinned_pages.elements-1;
}
if (tmp == info->buff)
......@@ -83,12 +117,27 @@ uchar *_ma_fetch_keypage(register MARIA_HA *info,
info->last_keypage=HA_OFFSET_ERROR;
maria_print_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
DBUG_RETURN(1);
}
info->last_keypage= pos;
/*
Setup page structure to make pages easy to use
This is same as page_fill_info, but here inlined as this si used
so often.
*/
page->info= info;
page->keyinfo= keyinfo;
page->buff= tmp;
page->pos= pos;
page->size= _ma_get_page_used(share, tmp);
page->flag= _ma_get_keypage_flag(share, tmp);
page->node= ((page->flag & KEYPAGE_FLAG_ISNOD) ?
share->base.key_reflength : 0);
#ifdef EXTRA_DEBUG
{
uint page_size= _ma_get_page_used(share, tmp);
uint page_size= page->size;
if (page_size < 4 || page_size > block_size ||
_ma_get_keynr(share, tmp) != keyinfo->key_nr)
{
......@@ -103,55 +152,58 @@ uchar *_ma_fetch_keypage(register MARIA_HA *info,
}
}
#endif
DBUG_RETURN(tmp);
DBUG_RETURN(0);
} /* _ma_fetch_keypage */
/* Write a key-page on disk */
int _ma_write_keypage(register MARIA_HA *info,
register const MARIA_KEYDEF *keyinfo
__attribute__((unused)),
my_off_t pos, enum pagecache_page_lock lock,
int level, uchar *buff)
my_bool _ma_write_keypage(MARIA_PAGE *page, enum pagecache_page_lock lock,
int level)
{
MARIA_SHARE *share= info->s;
MARIA_PINNED_PAGE page_link;
MARIA_SHARE *share= page->info->s;
uint block_size= share->block_size;
int res;
uchar *buff= page->buff;
my_bool res;
MARIA_PINNED_PAGE page_link;
DBUG_ENTER("_ma_write_keypage");
#ifdef EXTRA_DEBUG /* Safety check */
{
uint page_length, nod;
_ma_get_used_and_nod(share, buff, page_length, nod);
if (pos < share->base.keystart ||
pos+block_size > share->state.state.key_file_length ||
(pos & (maria_block_size-1)))
uint page_length, nod_flag;
page_length= _ma_get_page_used(share, buff);
nod_flag= _ma_test_if_nod(share, buff);
DBUG_ASSERT(page->size == page_length);
DBUG_ASSERT(page->flag == _ma_get_keypage_flag(share, buff));
if (page->pos < share->base.keystart ||
page->pos+block_size > share->state.state.key_file_length ||
(page->pos & (maria_block_size-1)))
{
DBUG_PRINT("error",("Trying to write inside key status region: "
"key_start: %lu length: %lu page: %lu",
(long) share->base.keystart,
(long) share->state.state.key_file_length,
(long) pos));
(long) page->pos));
my_errno=EINVAL;
DBUG_ASSERT(0);
DBUG_RETURN((-1));
DBUG_RETURN(1);
}
DBUG_PRINT("page",("write page at: %lu",(long) pos));
DBUG_PRINT("page",("write page at: %lu",(long) page->pos));
DBUG_DUMP("buff", buff, page_length);
DBUG_ASSERT(page_length >= share->keypage_header + nod +
keyinfo->minlength || maria_in_recovery);
DBUG_ASSERT(page_length >= share->keypage_header + nod_flag +
page->keyinfo->minlength || maria_in_recovery);
}
#endif
/* Verify that keynr is correct */
DBUG_ASSERT(_ma_get_keynr(share, buff) == keyinfo->key_nr);
DBUG_ASSERT(_ma_get_keynr(share, buff) == page->keyinfo->key_nr);
#if defined(EXTRA_DEBUG) && defined(HAVE_purify) && defined(NOT_ANYMORE)
{
/* This is here to catch uninitialized bytes */
uint length= _ma_get_page_used(share, buff);
uint length= page->size;
ulong crc= my_checksum(0, buff, length);
int4store(buff + block_size - KEYPAGE_CHECKSUM_SIZE, crc);
}
......@@ -159,15 +211,15 @@ int _ma_write_keypage(register MARIA_HA *info,
#ifdef IDENTICAL_PAGES_AFTER_RECOVERY
{
uint length= _ma_get_page_used(share, buff);
uint length= page->size;
DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE);
bzero(buff + length, block_size - length);
}
#endif
DBUG_ASSERT(share->pagecache->block_size == block_size);
res= pagecache_write(share->pagecache,
&share->kfile, (pgcache_page_no_t) (pos / block_size),
&share->kfile,
(pgcache_page_no_t) (page->pos / block_size),
level, buff, share->page_type,
lock,
lock == PAGECACHE_LOCK_LEFT_WRITELOCKED ?
......@@ -182,7 +234,7 @@ int _ma_write_keypage(register MARIA_HA *info,
/* It was not locked before, we have to unlock it when we unpin pages */
page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
page_link.changed= 1;
push_dynamic(&info->pinned_pages, (void*) &page_link);
push_dynamic(&page->info->pinned_pages, (void*) &page_link);
}
DBUG_RETURN(res);
}
......@@ -441,26 +493,26 @@ static my_bool _ma_log_compact_keypage(MARIA_HA *info, my_off_t page,
retval 1 Error; my_errno contains the error
*/
my_bool _ma_compact_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t page_pos, uchar *page, TrID min_read_from)
my_bool _ma_compact_keypage(MARIA_PAGE *ma_page, TrID min_read_from)
{
MARIA_SHARE *share= keyinfo->share;
MARIA_HA *info= ma_page->info;
MARIA_SHARE *share= info->s;
MARIA_KEY key;
uchar *start_of_page, *endpos, *start_of_empty_space;
uchar *page, *endpos, *start_of_empty_space;
uint page_flag, nod_flag, saved_space;
my_bool page_has_transid;
DBUG_ENTER("_ma_compact_keypage");
page_flag= _ma_get_keypage_flag(share, page);
page_flag= ma_page->flag;
if (!(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
DBUG_RETURN(0); /* No transaction id on page */
nod_flag= _ma_test_if_nod(share, page);
endpos= page + _ma_get_page_used(share, page);
nod_flag= ma_page->node;
page= ma_page->buff;
endpos= page + ma_page->size;
key.data= info->lastkey_buff;
key.keyinfo= keyinfo;
key.keyinfo= (MARIA_KEYDEF*) ma_page->keyinfo;
start_of_page= page;
page_has_transid= 0;
page+= share->keypage_header + nod_flag;
key.data[0]= 0; /* safety */
......@@ -468,7 +520,7 @@ my_bool _ma_compact_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
saved_space= 0;
do
{
if (!(page= (*keyinfo->skip_key)(&key, 0, 0, page)))
if (!(page= (*ma_page->keyinfo->skip_key)(&key, 0, 0, page)))
{
DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
(long) page));
......@@ -514,26 +566,25 @@ my_bool _ma_compact_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
This is always true if any transid was removed
*/
uint copy_length= (uint) (endpos - start_of_empty_space) - saved_space;
uint page_length;
if (copy_length)
memmove(start_of_empty_space, start_of_empty_space + saved_space,
copy_length);
page_length= (uint) (start_of_empty_space + copy_length - start_of_page);
_ma_store_page_used(share, start_of_page, page_length);
ma_page->size= (uint) (start_of_empty_space + copy_length - ma_page->buff);
page_store_size(share, ma_page);
}
if (!page_has_transid)
{
page_flag&= ~KEYPAGE_FLAG_HAS_TRANSID;
_ma_store_keypage_flag(share, start_of_page, page_flag);
ma_page->flag&= ~KEYPAGE_FLAG_HAS_TRANSID;
_ma_store_keypage_flag(share, ma_page->buff, ma_page->flag);
/* Clear packed transid (in case of zerofill) */
bzero(start_of_page + LSN_STORE_SIZE, TRANSID_SIZE);
bzero(ma_page->buff + LSN_STORE_SIZE, TRANSID_SIZE);
}
if (share->now_transactional)
{
if (_ma_log_compact_keypage(info, page_pos, min_read_from))
if (_ma_log_compact_keypage(info, ma_page->pos, min_read_from))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
......
......@@ -24,7 +24,7 @@
static ha_rows _ma_record_pos(MARIA_HA *,const uchar *, key_part_map,
enum ha_rkey_function);
static double _ma_search_pos(MARIA_HA *, MARIA_KEY *, uint32, my_off_t);
static uint _ma_keynr(MARIA_HA *, MARIA_KEYDEF *, uchar *, uchar *, uint *);
static uint _ma_keynr(MARIA_PAGE *page, uchar *keypos, uint *ret_max_key);
/**
......@@ -205,25 +205,25 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
uint32 nextflag, my_off_t pos)
{
int flag;
uint nod_flag,keynr,max_keynr;
uint keynr, max_keynr;
my_bool after_key;
uchar *keypos, *buff;
uchar *keypos;
double offset;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE page;
DBUG_ENTER("_ma_search_pos");
LINT_INIT(max_keynr);
if (pos == HA_OFFSET_ERROR)
DBUG_RETURN(0.5);
if (!(buff= _ma_fetch_keypage(info,keyinfo, pos,
if (_ma_fetch_keypage(&page, info, keyinfo, pos,
PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS,
info->buff, 1, 0)))
info->buff, 1))
goto err;
flag= (*keyinfo->bin_search)(key, buff, nextflag, &keypos,
flag= (*keyinfo->bin_search)(key, &page, nextflag, &keypos,
info->lastkey_buff, &after_key);
nod_flag=_ma_test_if_nod(info->s, buff);
keynr= _ma_keynr(info,keyinfo,buff,keypos,&max_keynr);
keynr= _ma_keynr(&page, keypos, &max_keynr);
if (flag)
{
......@@ -234,10 +234,10 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
Try to find a smaller, better matching key.
Matches keynr + [0-1]
*/
if (flag > 0 && ! nod_flag)
if (flag > 0 && ! page.node)
offset= 1.0;
else if ((offset= _ma_search_pos(info, key, nextflag,
_ma_kpos(nod_flag,keypos))) < 0)
_ma_kpos(page.node,keypos))) < 0)
DBUG_RETURN(offset);
}
else
......@@ -247,7 +247,7 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
Matches keynr+1
*/
offset=1.0; /* Matches keynr+1 */
if ((nextflag & SEARCH_FIND) && nod_flag &&
if ((nextflag & SEARCH_FIND) && page.node &&
((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
(nextflag & (SEARCH_PREFIX | SEARCH_NO_FIND | SEARCH_LAST |
SEARCH_PART_KEY))))
......@@ -257,12 +257,12 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
Matches keynr + [0-1]
*/
if ((offset= _ma_search_pos(info, key, SEARCH_FIND,
_ma_kpos(nod_flag,keypos))) < 0)
_ma_kpos(page.node,keypos))) < 0)
DBUG_RETURN(offset); /* Read error */
}
}
DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d",
keynr,offset,max_keynr,nod_flag,flag));
keynr,offset,max_keynr,page.node,flag));
DBUG_RETURN((keynr+offset)/(max_keynr+1));
err:
DBUG_PRINT("exit",("Error: %d",my_errno));
......@@ -272,40 +272,39 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
/* Get keynummer of current key and max number of keys in nod */
static uint _ma_keynr(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
uchar *page, uchar *keypos, uint *ret_max_key)
static uint _ma_keynr(MARIA_PAGE *page, uchar *keypos, uint *ret_max_key)
{
uint page_flag, nod_flag, used_length, keynr, max_key;
uchar t_buff[MARIA_MAX_KEY_BUFF],*end;
uint page_flag, nod_flag, keynr, max_key;
uchar t_buff[MARIA_MAX_KEY_BUFF], *pos, *end;
const MARIA_KEYDEF *keyinfo= page->keyinfo;
MARIA_KEY key;
page_flag= _ma_get_keypage_flag(info->s, page);
_ma_get_used_and_nod_with_flag(info->s, page_flag, page, used_length,
nod_flag);
end= page+ used_length;
page+= info->s->keypage_header + nod_flag;
page_flag= page->flag;
nod_flag= page->node;
pos= page->buff + page->info->s->keypage_header + nod_flag;
end= page->buff + page->size;
if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
*ret_max_key= (uint) (end-page)/(keyinfo->keylength+nod_flag);
return (uint) (keypos-page)/(keyinfo->keylength+nod_flag);
*ret_max_key= (uint) (end - pos)/(keyinfo->keylength+nod_flag);
return (uint) (keypos - pos)/(keyinfo->keylength+nod_flag);
}
max_key=keynr=0;
t_buff[0]=0; /* Safety */
key.data= t_buff;
key.keyinfo= keyinfo;
key.keyinfo= (MARIA_KEYDEF*) keyinfo;
while (page < end)
while (pos < end)
{
if (!(page= (*keyinfo->skip_key)(&key, page_flag, nod_flag, page)))
if (!(pos= (*keyinfo->skip_key)(&key, page_flag, nod_flag, pos)))
{
DBUG_ASSERT(0);
return 0; /* Error */
}
max_key++;
if (page == keypos)
if (pos == keypos)
keynr= max_key;
}
*ret_max_key=max_key;
......
......@@ -36,8 +36,8 @@ typedef struct st_page_level
typedef struct st_page_list
{
ulong n_pages;
ulong m_pages;
uint n_pages;
uint m_pages;
stPageLevel *pages;
} stPageList;
......@@ -56,7 +56,8 @@ typedef struct st_page_list
static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint32 search_flag,
uint nod_cmp_flag, my_off_t page, int level)
uint nod_cmp_flag, my_off_t page_pos,
int level)
{
MARIA_SHARE *share= info->s;
uint nod_flag;
......@@ -64,16 +65,18 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uchar *page_buf, *k, *last;
int key_data_length;
uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level;
MARIA_PAGE page;
if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
{
my_errno= HA_ERR_OUT_OF_MEM;
return -1;
}
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, page_buf, 0, 0))
goto err1;
nod_flag= _ma_test_if_nod(share, page_buf);
if (_ma_fetch_keypage(&page, info, keyinfo, page_pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, page_buf, 0))
goto err;
nod_flag= page.node;
key_data_length= keyinfo->keylength - share->base.rec_reflength;
......@@ -85,7 +88,7 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
{
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
}
last= rt_PAGE_END(share, page_buf);
last= rt_PAGE_END(&page);
for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length, nod_flag))
{
......@@ -109,7 +112,7 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
break;
default: /* error */
case -1:
goto err1;
goto err;
}
}
}
......@@ -166,7 +169,7 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_afree((uchar*)page_buf);
return res;
err1:
err:
my_afree((uchar*)page_buf);
info->cur_row.lastpos= HA_OFFSET_ERROR;
return -1;
......@@ -302,26 +305,28 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint32 search_flag)
*/
static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint key_length, my_off_t page, int level)
uint key_length, my_off_t page_pos, int level)
{
MARIA_SHARE *share= info->s;
uchar *page_buf, *last, *k;
uint nod_flag, key_data_length;
int res;
uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level;
MARIA_PAGE page;
if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
return -1;
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, page_buf, 0, 0))
goto err1;
nod_flag= _ma_test_if_nod(share, page_buf);
if (_ma_fetch_keypage(&page, info, keyinfo, page_pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, page_buf, 0))
goto err;
nod_flag= page.node;
key_data_length= keyinfo->keylength - share->base.rec_reflength;
if (info->maria_rtree_recursion_depth >= level)
{
k= page_buf + *saved_key;
k= page.buff + *saved_key;
if (!nod_flag)
{
/* Only leaf pages contain data references. */
......@@ -331,9 +336,9 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
else
{
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
k= rt_PAGE_FIRST_KEY(share, page.buff, nod_flag);
}
last= rt_PAGE_END(share, page_buf);
last= rt_PAGE_END(&page);
for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length, nod_flag))
{
......@@ -344,14 +349,14 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_kpos(nod_flag, k), level + 1)))
{
case 0: /* found - exit from recursion */
*saved_key= k - page_buf;
*saved_key= k - page.buff;
goto ok;
case 1: /* not found - continue searching */
info->maria_rtree_recursion_depth= level;
break;
default:
case -1: /* error */
goto err1;
goto err;
}
}
else
......@@ -376,14 +381,14 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
info->last_key.data_length + info->last_key.ref_length);
info->maria_rtree_recursion_depth= level;
*saved_key= k - page_buf;
*saved_key= k - page.buff;
if (after_key < last)
{
uchar *keyread_buff= info->keyread_buff;
info->last_rtree_keypos= saved_key;
memcpy(keyread_buff, page_buf, keyinfo->block_length);
info->int_maxpos= rt_PAGE_END(share, keyread_buff);
memcpy(keyread_buff, page.buff, page.size);
info->int_maxpos= keyread_buff + page.size;
info->keyread_buff_used= 0;
}
else
......@@ -403,7 +408,7 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_afree((uchar*)page_buf);
return res;
err1:
err:
my_afree((uchar*)page_buf);
info->cur_row.lastpos= HA_OFFSET_ERROR;
return -1;
......@@ -497,18 +502,18 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length)
Returns a pointer inside the page_buf buffer.
*/
#ifdef PICK_BY_PERIMETER
static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
const MARIA_KEY *key,
const uchar *page_buf,
uint nod_flag)
static const uchar *maria_rtree_pick_key(const MARIA_KEY *key,
const MARIA_PAGE *page)
{
double increase;
double best_incr;
double perimeter;
double best_perimeter;
uchar *best_key= NULL;
uchar *k= rt_PAGE_FIRST_KEY(page_buf, nod_flag);
uchar *last= rt_PAGE_END(info, page_buf);
const MARIA_HA *info= page->info;
uchar *k= rt_PAGE_FIRST_KEY(info->s, page->buf, page->node);
uchar *last= rt_PAGE_END(info, page);
LINT_INIT(best_perimeter);
LINT_INIT(best_key);
......@@ -533,24 +538,23 @@ static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
#endif /*PICK_BY_PERIMETER*/
#ifdef PICK_BY_AREA
static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
const MARIA_KEY *key,
const uchar *page_buf,
uint nod_flag)
static const uchar *maria_rtree_pick_key(const MARIA_KEY *key,
const MARIA_PAGE *page)
{
const MARIA_HA *info= page->info;
MARIA_SHARE *share= info->s;
double increase;
double best_incr= DBL_MAX;
double area;
double best_area;
const uchar *best_key= NULL;
const uchar *k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
const uchar *last= rt_PAGE_END(share, page_buf);
const uchar *k= rt_PAGE_FIRST_KEY(share, page->buff, page->node);
const uchar *last= rt_PAGE_END(page);
LINT_INIT(best_area);
for (; k < last;
k= rt_PAGE_NEXT_KEY(share, k, key->data_length, nod_flag))
k= rt_PAGE_NEXT_KEY(share, k, key->data_length, page->node))
{
/* The following is safe as -1.0 is an exact number */
if ((increase= maria_rtree_area_increase(key->keyinfo->seg, k, key->data,
......@@ -582,16 +586,16 @@ static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
*/
static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEY *key,
my_off_t page, my_off_t *new_page,
my_off_t page_pos, my_off_t *new_page,
int ins_level, int level)
{
uint nod_flag, page_link_idx;
uint nod_flag;
uint key_length= key->data_length;
int res;
uchar *page_buf, *k;
MARIA_PINNED_PAGE *page_link;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE page;
DBUG_ENTER("maria_rtree_insert_req");
if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length +
......@@ -600,19 +604,18 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEY *key,
my_errno= HA_ERR_OUT_OF_MEM;
DBUG_RETURN(-1); /* purecov: inspected */
}
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, page_buf, 0, &page_link))
goto err1;
page_link_idx= page_link_to_idx(info);
nod_flag= _ma_test_if_nod(share, page_buf);
if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, page_buf, 0))
goto err;
nod_flag= page.node;
DBUG_PRINT("rtree", ("page: %lu level: %d ins_level: %d nod_flag: %u",
(ulong) page, level, ins_level, nod_flag));
(ulong) page.pos, level, ins_level, nod_flag));
if ((ins_level == -1 && nod_flag) || /* key: go down to leaf */
(ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */
{
if (!(k= (uchar *)maria_rtree_pick_key(info, key, page_buf, nod_flag)))
goto err1;
if (!(k= (uchar *)maria_rtree_pick_key(key, &page)))
goto err;
/* k is now a pointer inside the page_buf buffer */
switch ((res= maria_rtree_insert_req(info, key,
_ma_kpos(nod_flag, k), new_page,
......@@ -622,13 +625,12 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEY *key,
{
maria_rtree_combine_rect(keyinfo->seg, k, key->data, k, key_length);
if (share->now_transactional &&
_ma_log_change(info, page, page_buf, k, key_length))
goto err1;
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
goto err1;
_ma_log_change(&page, k, key_length))
goto err;
page_mark_changed(info, &page);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
goto ok;
}
case 1: /* child was split */
......@@ -648,43 +650,42 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEY *key,
/* set proper MBR for key */
if (maria_rtree_set_key_mbr(info, &k_key, _ma_kpos(nod_flag, k)))
goto err1;
goto err;
if (share->now_transactional &&
_ma_log_change(info, page, page_buf, k, key_length))
goto err1;
_ma_log_change(&page, k, key_length))
goto err;
/* add new key for new page */
_ma_kpointer(info, new_key_buff - nod_flag, *new_page);
if (maria_rtree_set_key_mbr(info, &new_key, *new_page))
goto err1;
res= maria_rtree_add_key(info, &new_key, page_buf, page, new_page);
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
goto err1;
goto err;
res= maria_rtree_add_key(&new_key, &page, new_page);
page_mark_changed(info, &page);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
goto ok;
}
default:
case -1: /* error */
{
goto err1;
goto err;
}
}
}
else
{
res= maria_rtree_add_key(info, key, page_buf, page, new_page);
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
goto err1;
res= maria_rtree_add_key(key, &page, new_page);
page_mark_changed(info, &page);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
}
ok:
my_afree(page_buf);
DBUG_RETURN(res);
err1:
err:
res= -1; /* purecov: inspected */
goto ok; /* purecov: inspected */
}
......@@ -712,13 +713,14 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level,
MARIA_KEYDEF *keyinfo= key->keyinfo;
int res;
my_off_t new_page;
MARIA_PINNED_PAGE *page_link;
enum pagecache_page_lock write_lock;
DBUG_ENTER("maria_rtree_insert_level");
if ((old_root= share->state.key_root[keyinfo->key_nr]) == HA_OFFSET_ERROR)
{
MARIA_PINNED_PAGE tmp_page_link;
MARIA_PINNED_PAGE tmp_page_link, *page_link;
MARIA_PAGE page;
page_link= &tmp_page_link;
if ((old_root= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
HA_OFFSET_ERROR)
......@@ -728,15 +730,13 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level,
bzero(info->buff, share->block_size);
_ma_store_keynr(share, info->buff, keyinfo->key_nr);
_ma_store_page_used(share, info->buff, share->keypage_header);
_ma_page_setup(&page, info, keyinfo, old_root, info->buff);
if (share->now_transactional &&
_ma_log_new(info, old_root, info->buff, share->keypage_header,
keyinfo->key_nr, 1))
if (share->now_transactional && _ma_log_new(&page, 1))
DBUG_RETURN(1);
res= maria_rtree_add_key(info, key, info->buff, old_root, NULL);
if (_ma_write_keypage(info, keyinfo, old_root, write_lock,
DFLT_INIT_HITS, info->buff))
res= maria_rtree_add_key(key, &page, NULL);
if (_ma_write_keypage(&page, write_lock, DFLT_INIT_HITS))
DBUG_RETURN(1);
*root= old_root;
DBUG_RETURN(res);
......@@ -754,8 +754,9 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level,
uchar *new_root_buf, *new_key_buff;
my_off_t new_root;
uint nod_flag= share->base.key_reflength;
MARIA_PINNED_PAGE tmp_page_link;
MARIA_PINNED_PAGE tmp_page_link, *page_link;
MARIA_KEY new_key;
MARIA_PAGE page;
page_link= &tmp_page_link;
DBUG_PRINT("rtree", ("root was split, grow a new root"));
......@@ -767,19 +768,18 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level,
}
bzero(new_root_buf, share->block_size);
if (nod_flag)
_ma_store_keypage_flag(share, new_root_buf, KEYPAGE_FLAG_ISNOD);
_ma_store_keynr(share, new_root_buf, keyinfo->key_nr);
_ma_store_page_used(share, new_root_buf, share->keypage_header);
if ((new_root= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
HA_OFFSET_ERROR)
goto err1;
goto err;
write_lock= page_link->write_lock;
if (share->now_transactional &&
_ma_log_new(info, new_root, new_root_buf, share->keypage_header,
keyinfo->key_nr, 1))
goto err1;
_ma_page_setup(&page, info, keyinfo, new_root, new_root_buf);
if (share->now_transactional && _ma_log_new(&page, 1))
goto err;
/* Point to some free space */
new_key_buff= new_root_buf + keyinfo->block_length + nod_flag;
......@@ -791,28 +791,26 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level,
_ma_kpointer(info, new_key_buff - nod_flag, old_root);
if (maria_rtree_set_key_mbr(info, &new_key, old_root))
goto err1;
if (maria_rtree_add_key(info, &new_key, new_root_buf, new_root, NULL)
goto err;
if (maria_rtree_add_key(&new_key, &page, NULL)
== -1)
goto err1;
goto err;
_ma_kpointer(info, new_key_buff - nod_flag, new_page);
if (maria_rtree_set_key_mbr(info, &new_key, new_page))
goto err1;
if (maria_rtree_add_key(info, &new_key, new_root_buf, new_root, NULL)
goto err;
if (maria_rtree_add_key(&new_key, &page, NULL)
== -1)
goto err1;
if (_ma_write_keypage(info, keyinfo, new_root, write_lock,
DFLT_INIT_HITS, new_root_buf))
goto err1;
goto err;
if (_ma_write_keypage(&page, write_lock, DFLT_INIT_HITS))
goto err;
*root= new_root;
DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u",
(ulong) new_root, 0,
_ma_test_if_nod(share, new_root_buf)));
(ulong) new_root, 0, page.node));
my_afree((uchar*)new_root_buf);
my_afree(new_root_buf);
break;
err1:
my_afree((uchar*)new_root_buf);
err:
my_afree(new_root_buf);
DBUG_RETURN(-1); /* purecov: inspected */
}
default:
......@@ -867,11 +865,11 @@ my_bool maria_rtree_insert(MARIA_HA *info, MARIA_KEY *key)
Fill reinsert page buffer
RETURN
-1 Error
1 Error
0 OK
*/
static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList,
static my_bool maria_rtree_fill_reinsert_list(stPageList *ReinsertList,
my_off_t page, int level)
{
DBUG_ENTER("maria_rtree_fill_reinsert_list");
......@@ -881,7 +879,7 @@ static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList,
ReinsertList->m_pages += REINSERT_BUFFER_INC;
if (!(ReinsertList->pages= (stPageLevel*)my_realloc((uchar*)ReinsertList->pages,
ReinsertList->m_pages * sizeof(stPageLevel), MYF(MY_ALLOW_ZERO_PTR))))
goto err1;
goto err;
}
/* save page to ReinsertList */
ReinsertList->pages[ReinsertList->n_pages].offs= page;
......@@ -889,8 +887,8 @@ static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList,
ReinsertList->n_pages++;
DBUG_RETURN(0);
err1:
DBUG_RETURN(-1); /* purecov: inspected */
err:
DBUG_RETURN(1); /* purecov: inspected */
}
......@@ -905,16 +903,16 @@ static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList,
*/
static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
my_off_t page, uint *page_size,
my_off_t page_pos, uint *page_size,
stPageList *ReinsertList, int level)
{
ulong i;
uint nod_flag, page_link_idx;
uint nod_flag;
int res;
uchar *page_buf, *last, *k;
MARIA_PINNED_PAGE *page_link;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE page;
DBUG_ENTER("maria_rtree_delete_req");
if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
......@@ -922,16 +920,15 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
my_errno= HA_ERR_OUT_OF_MEM;
DBUG_RETURN(-1); /* purecov: inspected */
}
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, page_buf, 0, &page_link))
goto err1;
page_link_idx= page_link_to_idx(info);
nod_flag= _ma_test_if_nod(share, page_buf);
if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, page_buf, 0))
goto err;
nod_flag= page.node;
DBUG_PRINT("rtree", ("page: %lu level: %d nod_flag: %u",
(ulong) page, level, nod_flag));
(ulong) page_pos, level, nod_flag));
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
last= rt_PAGE_END(share, page_buf);
last= rt_PAGE_END(&page);
for (i= 0;
k < last;
......@@ -965,15 +962,15 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
if (maria_rtree_set_key_mbr(info, &tmp_key,
_ma_kpos(nod_flag, k)))
goto err1;
goto err;
if (share->now_transactional &&
_ma_log_change(info, page, page_buf, k, key->data_length))
goto err1;
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page,
_ma_log_change(&page, k, key->data_length))
goto err;
page_mark_changed(info, &page)
if (_ma_write_keypage(&page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
goto err1;
DFLT_INIT_HITS))
goto err;
}
else
{
......@@ -986,7 +983,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
if (maria_rtree_fill_reinsert_list(ReinsertList,
_ma_kpos(nod_flag, k),
level + 1))
goto err1;
goto err;
/*
Delete the key that references the block. This makes the
block disappear from the index. Hence we need to insert
......@@ -995,15 +992,13 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
subtree. So we need to re-insert its keys on the same
level later to reintegrate the subtrees.
*/
if (maria_rtree_delete_key(info, page_buf, k, key->data_length,
nod_flag, page))
goto err1;
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
goto err1;
*page_size= _ma_get_page_used(share, page_buf);
if (maria_rtree_delete_key(&page, k, key->data_length))
goto err;
page_mark_changed(info, &page);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
*page_size= page.size;
}
goto ok;
......@@ -1014,22 +1009,20 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
}
case 2: /* vacuous case: last key in the leaf */
{
if (maria_rtree_delete_key(info, page_buf, k, key->data_length,
nod_flag, page))
goto err1;
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
goto err1;
*page_size= _ma_get_page_used(share, page_buf);
if (maria_rtree_delete_key(&page, k, key->data_length))
goto err;
page_mark_changed(info, &page);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
*page_size= page.size;
res= 0;
goto ok;
}
default: /* error */
case -1:
{
goto err1;
goto err;
}
}
}
......@@ -1040,26 +1033,23 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
if (!maria_rtree_key_cmp(keyinfo->seg, key->data, k, key->data_length,
MBR_EQUAL | MBR_DATA))
{
page_link_from_idx(info, page_link_idx)->changed= 1;
if (maria_rtree_delete_key(info, page_buf, k, key->data_length,
nod_flag, page))
goto err1;
*page_size= _ma_get_page_used(share, page_buf);
page_mark_changed(info, &page);
if (maria_rtree_delete_key(&page, k, key->data_length))
goto err;
*page_size= page.size;
if (*page_size == info->s->keypage_header)
{
/* last key in the leaf */
res= 2;
if (_ma_dispose(info, page, 0))
goto err1;
if (_ma_dispose(info, page.pos, 0))
goto err;
}
else
{
res= 0;
if (_ma_write_keypage(info, keyinfo, page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
goto err1;
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
}
goto ok;
}
......@@ -1071,7 +1061,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
my_afree((uchar*)page_buf);
DBUG_RETURN(res);
err1:
err:
my_afree((uchar*)page_buf);
DBUG_RETURN(-1); /* purecov: inspected */
}
......@@ -1081,11 +1071,11 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
Delete key - interface function
RETURN
-1 Error
1 Error
0 Deleted
*/
int maria_rtree_delete(MARIA_HA *info, MARIA_KEY *key)
my_bool maria_rtree_delete(MARIA_HA *info, MARIA_KEY *key)
{
MARIA_SHARE *share= info->s;
my_off_t new_root= share->state.key_root[key->keyinfo->key_nr];
......@@ -1104,18 +1094,16 @@ int maria_rtree_delete(MARIA_HA *info, MARIA_KEY *key)
err:
_ma_fast_unlock_key_del(info);
_ma_unpin_all_pages_and_finalize_row(info, lsn);
DBUG_RETURN(res);
DBUG_RETURN(res != 0);
}
int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
my_off_t *root)
{
int res;
uint page_size, page_link_idx;
uint page_size;
stPageList ReinsertList;
my_off_t old_root;
MARIA_PINNED_PAGE *page_link, *root_page_link;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
uint key_data_length= key->data_length;
......@@ -1125,7 +1113,7 @@ int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
HA_OFFSET_ERROR)
{
my_errno= HA_ERR_END_OF_FILE;
DBUG_RETURN(-1); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
DBUG_PRINT("rtree", ("starting deletion at root page: %lu",
(ulong) old_root));
......@@ -1139,8 +1127,7 @@ int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
case 2: /* empty */
{
*root= HA_OFFSET_ERROR;
res= 0;
goto err;
break;
}
case 0: /* deleted */
{
......@@ -1151,44 +1138,47 @@ int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
tmp_key.data_length= key->data_length;
tmp_key.ref_length= key->ref_length;
tmp_key.flag= 0; /* Safety */
uchar *page_buf;
MARIA_PAGE page;
for (i= 0; i < ReinsertList.n_pages; ++i)
if (ReinsertList.n_pages)
{
uchar *page_buf, *k, *last;
if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
{
my_errno= HA_ERR_OUT_OF_MEM;
goto err1;
goto err;
}
if (!_ma_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs,
for (i= 0; i < ReinsertList.n_pages; ++i)
{
uchar *k, *last;
if (_ma_fetch_keypage(&page, info, keyinfo, ReinsertList.pages[i].offs,
PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, page_buf, 0, &page_link))
goto err1;
page_link_idx= page_link_to_idx(info);
nod_flag= _ma_test_if_nod(share, page_buf);
DFLT_INIT_HITS, page_buf, 0))
goto err;
nod_flag= page.node;
DBUG_PRINT("rtree", ("reinserting keys from "
"page: %lu level: %d nod_flag: %u",
(ulong) ReinsertList.pages[i].offs,
ReinsertList.pages[i].level, nod_flag));
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
last= rt_PAGE_END(share, page_buf);
k= rt_PAGE_FIRST_KEY(share, page.buff, nod_flag);
last= rt_PAGE_END(&page);
for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length,
nod_flag))
{
int res;
tmp_key.data= k;
if ((res=
maria_rtree_insert_level(info, &tmp_key,
if ((res= maria_rtree_insert_level(info, &tmp_key,
ReinsertList.pages[i].level,
root)) == -1)
{
my_afree(page_buf);
goto err1;
goto err;
}
if (res)
{
ulong j;
uint j;
DBUG_PRINT("rtree", ("root has been split, adjust levels"));
for (j= i; j < ReinsertList.n_pages; j++)
{
......@@ -1199,54 +1189,50 @@ int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
}
}
}
res= 0;
page_mark_changed(info, &page);
if (_ma_dispose(info, page.pos, 0))
{
my_afree(page_buf);
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_dispose(info, ReinsertList.pages[i].offs, 0))
goto err1;
goto err;
}
}
if (ReinsertList.pages)
my_afree(page_buf);
my_free((uchar*) ReinsertList.pages, MYF(0));
}
/* check for redundant root (not leaf, 1 child) and eliminate */
if ((old_root= *root) == HA_OFFSET_ERROR)
goto err1;
if (!_ma_fetch_keypage(info, keyinfo, old_root,
goto err;
if (_ma_fetch_keypage(&page, info, keyinfo, old_root,
PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, info->buff, 0, &root_page_link))
goto err1;
nod_flag= _ma_test_if_nod(share, info->buff);
page_size= _ma_get_page_used(share, info->buff);
if (nod_flag && (page_size == share->keypage_header + key_data_length +
DFLT_INIT_HITS, info->buff, 0))
goto err;
nod_flag= page.node;
if (nod_flag && (page.size == share->keypage_header + key_data_length +
nod_flag))
{
*root= _ma_kpos(nod_flag,
rt_PAGE_FIRST_KEY(share, info->buff, nod_flag));
root_page_link->changed= 1;
if (_ma_dispose(info, old_root, 0))
goto err1;
page_mark_changed(info, &page);
if (_ma_dispose(info, page.pos, 0))
goto err;
}
info->update= HA_STATE_DELETED;
res= 0;
goto err;
err1:
res= -1;
goto err; /* purecov: inspected */
break;
}
case 1: /* not found */
{
my_errno= HA_ERR_KEY_NOT_FOUND;
res= -1;
goto err; /* purecov: inspected */
goto err;
}
default:
case -1: /* error */
res= -1;
default:
goto err; /* purecov: inspected */
}
DBUG_RETURN(0);
err:
DBUG_RETURN(res);
DBUG_RETURN(1);
}
......@@ -1267,6 +1253,7 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag)
ha_rows res= 0;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE page;
if (flag & MBR_DISJOINT)
return info->state->records;
......@@ -1275,18 +1262,19 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag)
return HA_POS_ERROR;
if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
return HA_POS_ERROR;
if (!_ma_fetch_keypage(info, keyinfo, root, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, page_buf, 0, 0))
goto err1;
nod_flag= _ma_test_if_nod(share, page_buf);
if (_ma_fetch_keypage(&page, info, keyinfo, root,
PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS, page_buf,
0))
goto err;
nod_flag= page.node;
key_data_length= key->data_length;
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
last= rt_PAGE_END(share, page_buf);
k= rt_PAGE_FIRST_KEY(share, page.buff, nod_flag);
last= rt_PAGE_END(&page);
for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length,
nod_flag), i++)
for (; k < last;
k= rt_PAGE_NEXT_KEY(share, k, key_data_length, nod_flag), i++)
{
if (nod_flag)
{
......@@ -1297,16 +1285,16 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag)
{
if (flag & (MBR_CONTAIN | MBR_INTERSECT))
{
area += 1;
area+= 1;
}
else if (flag & (MBR_WITHIN | MBR_EQUAL))
{
if (!maria_rtree_key_cmp(keyinfo->seg, key->data, k, key_data_length,
MBR_WITHIN))
area += 1;
area+= 1;
}
else
goto err1;
goto err;
}
else
{
......@@ -1323,7 +1311,7 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag)
key_data_length) / k_area);
}
else
goto err1;
goto err;
}
}
else
......@@ -1344,7 +1332,7 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag)
my_afree((uchar*)page_buf);
return res;
err1:
err:
my_afree(page_buf);
return HA_POS_ERROR;
}
......
......@@ -22,15 +22,16 @@
#define rt_PAGE_FIRST_KEY(share, page, nod_flag) (page + share->keypage_header + nod_flag)
#define rt_PAGE_NEXT_KEY(share, key, key_length, nod_flag) (key + key_length +\
(nod_flag ? nod_flag : share->base.rec_reflength))
#define rt_PAGE_END(share, page) (page + _ma_get_page_used(share, page))
#define rt_PAGE_END(page) ((page)->buff + (page)->size)
#define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length - KEYPAGE_CHECKSUM_SIZE) / 3)
my_bool maria_rtree_insert(MARIA_HA *info, MARIA_KEY *key);
int maria_rtree_delete(MARIA_HA *info, MARIA_KEY *key);
my_bool maria_rtree_delete(MARIA_HA *info, MARIA_KEY *key);
int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key,
int ins_level, my_off_t *root);
int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, my_off_t *root);
my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
my_off_t *root);
int maria_rtree_find_first(MARIA_HA *info, MARIA_KEY *key, uint search_flag);
int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint32 search_flag);
......@@ -39,21 +40,7 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length);
ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag);
int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
my_off_t page_offs, uchar *page,
int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page,
my_off_t *new_page_offs);
/**
When you obtain a MARIA_PINNED_PAGE* link (by calling
_ma_fetch_keypage()/_ma_new()/etc), it is valid only until the next call to
those functions on this MARIA_HA*, because that next call may cause a
realloc of the pinned_pages DYNAMIC_ARRAY, causing the first link to become
wrong. The _index_ in the array is however invariant, so in these situations
you should save the index immediately and use it to later obtain an
up-to-date link.
*/
#define page_link_to_idx(INFO) ((INFO)->pinned_pages.elements - 1)
#define page_link_from_idx(INFO, IDX) \
dynamic_element(&(INFO)->pinned_pages, (IDX), MARIA_PINNED_PAGE *)
#endif /*HAVE_RTREE_KEYS*/
#endif /* _rt_index_h */
......@@ -31,13 +31,14 @@
1 Split
*/
int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEY *key,
uchar *page_buf, my_off_t page, my_off_t *new_page)
int maria_rtree_add_key(const MARIA_KEY *key, MARIA_PAGE *page,
my_off_t *new_page)
{
MARIA_HA *info= page->info;
MARIA_SHARE *share= info->s;
uint page_size= _ma_get_page_used(share, page_buf);
uint nod_flag= _ma_test_if_nod(share, page_buf);
uchar *key_pos= rt_PAGE_END(share, page_buf);
uint page_size= page->size;
uint nod_flag= page->node;
uchar *key_pos= rt_PAGE_END(page);
uint tot_key_length= key->data_length + key->ref_length + nod_flag;
DBUG_ENTER("maria_rtree_add_key");
......@@ -54,16 +55,15 @@ int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEY *key,
}
/* save key */
memcpy(key_pos, key->data - nod_flag, tot_key_length);
page_size+= tot_key_length;
_ma_store_page_used(share, page_buf, page_size);
page->size+= tot_key_length;
page_store_size(share, page);
if (share->now_transactional &&
_ma_log_add(info, page, page_buf, key_pos - page_buf,
_ma_log_add(page, key_pos - page->buff,
key_pos, tot_key_length, tot_key_length, 0))
DBUG_RETURN(-1);
DBUG_RETURN(0);
}
DBUG_RETURN(maria_rtree_split_page(info, key, page, page_buf, new_page)
? -1 : 1);
DBUG_RETURN(maria_rtree_split_page(key, page, new_page) ? -1 : 1);
}
......@@ -74,27 +74,24 @@ int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEY *key,
key_length is only the data part of the key
*/
int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key,
uint key_length, uint nod_flag, my_off_t page)
int maria_rtree_delete_key(MARIA_PAGE *page, uchar *key, uint key_length)
{
MARIA_HA *info= page->info;
MARIA_SHARE *share= info->s;
uint16 page_size= _ma_get_page_used(share, page_buf);
uint key_length_with_nod_flag;
uchar *key_start;
key_start= key - nod_flag;
if (!nod_flag)
key_start= key - page->node;
if (!page->node)
key_length+= share->base.rec_reflength;
memmove(key_start, key + key_length, page_size - key_length -
(key - page_buf));
key_length_with_nod_flag= key_length + nod_flag;
page_size-= key_length_with_nod_flag;
_ma_store_page_used(share, page_buf, page_size);
memmove(key_start, key + key_length, page->size - key_length -
(key - page->buff));
key_length_with_nod_flag= key_length + page->node;
page->size-= key_length_with_nod_flag;
page_store_size(share, page);
if (share->now_transactional &&
_ma_log_delete(info, page, page_buf, key_start, 0,
key_length_with_nod_flag))
_ma_log_delete(page, key_start, 0, key_length_with_nod_flag))
return -1;
return 0;
}
......@@ -107,15 +104,15 @@ int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key,
int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEY *key,
my_off_t child_page)
{
MARIA_PAGE page;
DBUG_ENTER("maria_rtree_set_key_mbr");
if (!_ma_fetch_keypage(info, key->keyinfo, child_page,
if (_ma_fetch_keypage(&page, info, key->keyinfo, child_page,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->buff, 0, 0))
DFLT_INIT_HITS, info->buff, 0))
DBUG_RETURN(-1);
DBUG_RETURN(maria_rtree_page_mbr(info, key->keyinfo->seg,
info->buff, key->data,
key->data_length));
DBUG_RETURN(maria_rtree_page_mbr(key->keyinfo->seg,
&page, key->data, key->data_length));
}
#endif /*HAVE_RTREE_KEYS*/
......@@ -21,10 +21,9 @@
#ifdef HAVE_RTREE_KEYS
int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEY *key, uchar *page_buf,
my_off_t page, my_off_t *new_page);
int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key,
uint key_length, uint nod_flag, my_off_t page);
int maria_rtree_add_key(const MARIA_KEY *key, MARIA_PAGE *page,
my_off_t *new_page);
int maria_rtree_delete_key(MARIA_PAGE *page, uchar *key, uint key_length);
int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEY *key,
my_off_t child_page);
......
......@@ -743,16 +743,17 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
Calculates key page total MBR= MBR(key1) + MBR(key2) + ...
Stores into *to.
*/
int maria_rtree_page_mbr(const MARIA_HA *info, const HA_KEYSEG *keyseg,
const uchar *page_buf,
int maria_rtree_page_mbr(const HA_KEYSEG *keyseg,
MARIA_PAGE *page,
uchar *to, uint key_length)
{
MARIA_HA *info= page->info;
MARIA_SHARE *share= info->s;
uint inc= 0;
uint k_len= key_length;
uint nod_flag= _ma_test_if_nod(share, page_buf);
uint nod_flag= page->node;
const uchar *k;
const uchar *last= rt_PAGE_END(share, page_buf);
const uchar *last= rt_PAGE_END(page);
for (; (int)key_length > 0; keyseg += 2)
{
......@@ -764,7 +765,7 @@ int maria_rtree_page_mbr(const MARIA_HA *info, const HA_KEYSEG *keyseg,
return 1;
}
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
k= rt_PAGE_FIRST_KEY(share, page->buff, nod_flag);
switch ((enum ha_base_keytype) keyseg->type) {
case HA_KEYTYPE_INT8:
......
......@@ -34,8 +34,7 @@ double maria_rtree_area_increase(const HA_KEYSEG *keyseg, const uchar *a,
uint key_length, double *ab_area);
double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
uint key_length, double *ab_perim);
int maria_rtree_page_mbr(const MARIA_HA *info, const HA_KEYSEG *keyseg,
const uchar *page_buf,
uchar* c, uint key_length);
int maria_rtree_page_mbr(const HA_KEYSEG *keyseg, MARIA_PAGE *page,
uchar *key, uint key_length);
#endif /*HAVE_RTREE_KEYS*/
#endif /* _rt_mbr_h */
......@@ -295,9 +295,7 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries,
@param length_diff by how much the page has shrunk during split
*/
static my_bool _ma_log_rt_split(MARIA_HA *info,
my_off_t page,
const uchar *buff __attribute__((unused)),
static my_bool _ma_log_rt_split(MARIA_PAGE *page,
const uchar *key_with_nod_flag,
uint full_length,
const uchar *log_internal_copy,
......@@ -305,18 +303,20 @@ static my_bool _ma_log_rt_split(MARIA_HA *info,
const uchar *log_key_copy,
uint length_diff)
{
MARIA_HA *info= page->info;
MARIA_SHARE *share= info->s;
LSN lsn;
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 1 + 2 + 1 + 2 + 2 + 7],
*log_pos;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 5];
uint translog_parts, extra_length= 0;
my_off_t page_pos;
DBUG_ENTER("_ma_log_rt_split");
DBUG_PRINT("enter", ("page: %lu", (ulong) page));
DBUG_ASSERT(share->now_transactional);
page/= share->block_size;
page_store(log_data + FILEID_STORE_SIZE, page);
page_pos= page->pos / share->block_size;
page_store(log_data + FILEID_STORE_SIZE, page_pos);
log_pos= log_data+ FILEID_STORE_SIZE + PAGE_STORE_SIZE;
log_pos[0]= KEY_OP_DEL_SUFFIX;
log_pos++;
......@@ -346,10 +346,11 @@ static my_bool _ma_log_rt_split(MARIA_HA *info,
#ifdef EXTRA_DEBUG_KEY_CHANGES
{
int page_length= _ma_get_page_used(share, buff);
int page_length= page->size;
ha_checksum crc;
uchar *check_start= log_pos;
crc= my_checksum(0, buff + LSN_STORE_SIZE, page_length - LSN_STORE_SIZE);
crc= my_checksum(0, page->buff + LSN_STORE_SIZE,
page_length - LSN_STORE_SIZE);
log_pos[0]= KEY_OP_CHECK;
log_pos++;
int2store(log_pos, page_length);
......@@ -380,10 +381,10 @@ static my_bool _ma_log_rt_split(MARIA_HA *info,
If new_page_offs==NULL, won't create new page (for redo phase).
*/
int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
my_off_t page_offs, uchar *page,
int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page,
my_off_t *new_page_offs)
{
MARIA_HA *info= page->info;
MARIA_SHARE *share= info->s;
const my_bool transactional= share->now_transactional;
int n1, n2; /* Number of items in groups */
......@@ -395,11 +396,12 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
double *old_coord;
int n_dim;
uchar *source_cur, *cur1, *cur2;
uchar *new_page, *log_internal_copy, *log_internal_copy_ptr,
uchar *new_page_buff, *log_internal_copy, *log_internal_copy_ptr,
*log_key_copy= NULL;
int err_code= 0;
uint nod_flag= _ma_test_if_nod(share, page);
uint org_length= _ma_get_page_used(share, page), new_length;
uint new_page_length;
uint nod_flag= page->node;
uint org_length= page->size;
uint full_length= key->data_length + (nod_flag ? nod_flag :
key->ref_length);
uint key_data_length= key->data_length;
......@@ -421,7 +423,7 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
next_coord= coord_buf;
stop= task + max_keys;
source_cur= rt_PAGE_FIRST_KEY(share, page, nod_flag);
source_cur= rt_PAGE_FIRST_KEY(share, page->buff, nod_flag);
for (cur= task;
cur < stop;
......@@ -440,7 +442,7 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
old_coord= next_coord;
if (split_maria_rtree_node(task, max_keys + 1,
_ma_get_page_used(share, page) + full_length + 2,
page->size + full_length + 2,
full_length,
rt_PAGE_MIN_SIZE(keyinfo->block_length),
2, 2, &next_coord, n_dim))
......@@ -450,7 +452,7 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
}
/* Allocate buffer for new page and piece of log record */
if (!(new_page= (uchar*) my_alloca((uint)keyinfo->block_length +
if (!(new_page_buff= (uchar*) my_alloca((uint)keyinfo->block_length +
(transactional ?
(max_keys * (2 + 2) +
1 + 2 + 1 + 2) : 0))))
......@@ -458,12 +460,13 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
err_code= -1;
goto split_err;
}
log_internal_copy= log_internal_copy_ptr= new_page + keyinfo->block_length;
bzero(new_page, share->block_size);
log_internal_copy= log_internal_copy_ptr= new_page_buff +
keyinfo->block_length;
bzero(new_page_buff, share->block_size);
stop= task + (max_keys + 1);
cur1= rt_PAGE_FIRST_KEY(share, page, nod_flag);
cur2= rt_PAGE_FIRST_KEY(share, new_page, nod_flag);
cur1= rt_PAGE_FIRST_KEY(share, page->buff, nod_flag);
cur2= rt_PAGE_FIRST_KEY(share, new_page_buff, nod_flag);
n1= n2= 0;
for (cur= task; cur < stop; cur++)
......@@ -493,11 +496,11 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
memcpy(to_with_nod_flag, cur_key_with_nod_flag, full_length);
if (log_this_change)
{
uint to_with_nod_flag_offs= to_with_nod_flag - page;
uint to_with_nod_flag_offs= to_with_nod_flag - page->buff;
if (likely(cur_key != key->data))
{
/* this memcpy() is internal to the page (source in the page) */
uint cur_key_with_nod_flag_offs= cur_key_with_nod_flag - page;
uint cur_key_with_nod_flag_offs= cur_key_with_nod_flag - page->buff;
int2store(log_internal_copy_ptr, to_with_nod_flag_offs);
log_internal_copy_ptr+= 2;
int2store(log_internal_copy_ptr, cur_key_with_nod_flag_offs);
......@@ -519,36 +522,37 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
{ /* verify that above loop didn't touch header bytes */
uint i;
for (i= 0; i < share->keypage_header; i++)
DBUG_ASSERT(new_page[i]==0);
DBUG_ASSERT(new_page_buff[i]==0);
}
if (nod_flag)
_ma_store_keypage_flag(share, new_page, KEYPAGE_FLAG_ISNOD);
_ma_store_keynr(share, new_page, keyinfo->key_nr);
_ma_store_page_used(share, new_page, share->keypage_header +
n2 * full_length);
new_length= share->keypage_header + n1 * full_length;
_ma_store_page_used(share, page, new_length);
_ma_store_keypage_flag(share, new_page_buff, KEYPAGE_FLAG_ISNOD);
_ma_store_keynr(share, new_page_buff, keyinfo->key_nr);
new_page_length= share->keypage_header + n2 * full_length;
_ma_store_page_used(share, new_page_buff, new_page_length);
page->size= share->keypage_header + n1 * full_length;
page_store_size(share, page);
if ((*new_page_offs= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
HA_OFFSET_ERROR)
err_code= -1;
else
{
MARIA_PAGE new_page;
_ma_page_setup(&new_page, info, keyinfo, *new_page_offs, new_page_buff);
if (transactional &&
( /* log change to split page */
_ma_log_rt_split(info, page_offs, page, key->data - nod_flag,
_ma_log_rt_split(page, key->data - nod_flag,
full_length, log_internal_copy,
log_internal_copy_ptr - log_internal_copy,
log_key_copy, org_length - new_length) ||
log_key_copy, org_length - page->size) ||
/* and to new page */
_ma_log_new(info, *new_page_offs, new_page,
share->keypage_header + n2 * full_length,
keyinfo->key_nr, 0)))
_ma_log_new(&new_page, 0)))
err_code= -1;
if ( _ma_write_keypage(info, keyinfo, *new_page_offs,
page_link->write_lock,
DFLT_INIT_HITS, new_page))
if (_ma_write_keypage(&new_page, page_link->write_lock,
DFLT_INIT_HITS))
err_code= -1;
}
DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs));
......
......@@ -18,7 +18,8 @@
#include "ma_fulltext.h"
#include "m_ctype.h"
static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos);
static my_bool _ma_get_prev_key(MARIA_KEY *key, MARIA_PAGE *ma_page,
uchar *keypos);
/* Check that new index is ok */
......@@ -62,8 +63,9 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
int error,flag;
uint page_flag, nod_flag, used_length;
uchar *keypos,*maxpos;
uchar lastkey[MARIA_MAX_KEY_BUFF],*buff;
uchar lastkey[MARIA_MAX_KEY_BUFF];
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE page;
DBUG_ENTER("_ma_search");
DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu",
(ulong) pos, nextflag, (ulong) info->cur_row.lastpos));
......@@ -78,21 +80,21 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
DBUG_RETURN(1); /* Search at upper levels */
}
if (!(buff= _ma_fetch_keypage(info, keyinfo, pos,
if (_ma_fetch_keypage(&page, info, keyinfo, pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->keyread_buff,
test(!(nextflag & SEARCH_SAVE_BUFF)), 0)))
test(!(nextflag & SEARCH_SAVE_BUFF))))
goto err;
DBUG_DUMP("page", buff, _ma_get_page_used(info->s, buff));
DBUG_DUMP("page", page.buff, page.size);
flag= (*keyinfo->bin_search)(key, buff, nextflag, &keypos, lastkey,
flag= (*keyinfo->bin_search)(key, &page, nextflag, &keypos, lastkey,
&last_key_not_used);
if (flag == MARIA_FOUND_WRONG_KEY)
DBUG_RETURN(-1);
page_flag= _ma_get_keypage_flag(info->s, buff);
_ma_get_used_and_nod_with_flag(info->s, page_flag, buff, used_length,
nod_flag);
maxpos= buff + used_length -1;
page_flag= page.flag;
used_length= page.size;
nod_flag= page.node;
maxpos= page.buff + used_length -1;
if (flag)
{
......@@ -103,7 +105,7 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
if (flag >0)
{
if (nextflag & (SEARCH_SMALLER | SEARCH_LAST) &&
keypos == buff + info->s->keypage_header + nod_flag)
keypos == page.buff + info->s->keypage_header + nod_flag)
DBUG_RETURN(1); /* Bigger than key */
}
else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
......@@ -126,21 +128,22 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
}
if (pos != info->last_keypage)
{
uchar *old_buff=buff;
if (!(buff= _ma_fetch_keypage(info,keyinfo, pos,
uchar *old_buff= page.buff;
if (_ma_fetch_keypage(&page, info, keyinfo, pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,DFLT_INIT_HITS,
info->keyread_buff,
test(!(nextflag & SEARCH_SAVE_BUFF)), 0)))
test(!(nextflag & SEARCH_SAVE_BUFF))))
goto err;
keypos=buff+(keypos-old_buff);
maxpos=buff+(maxpos-old_buff);
/* Restore position if page buffer moved */
keypos= page.buff + (keypos - old_buff);
maxpos= page.buff + (maxpos - old_buff);
}
info->last_key.keyinfo= keyinfo;
if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
{
uint not_used[2];
if (_ma_get_prev_key(&info->last_key, buff, keypos))
if (_ma_get_prev_key(&info->last_key, &page, keypos))
goto err;
/*
We have to use key->flag >> 1 here to transform
......@@ -170,14 +173,14 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
info->cur_row.trid= _ma_trid_from_key(&info->last_key);
/* Save position for a possible read next / previous */
info->int_keypos= info->keyread_buff+ (keypos-buff);
info->int_maxpos= info->keyread_buff+ (maxpos-buff);
info->int_keypos= info->keyread_buff + (keypos - page.buff);
info->int_maxpos= info->keyread_buff + (maxpos - page.buff);
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->page_changed=0;
/* Set marker that buffer was used (Marker for mi_search_next()) */
info->keyread_buff_used= (info->keyread_buff != buff);
info->keyread_buff_used= (info->keyread_buff != page.buff);
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
DBUG_RETURN(0);
......@@ -211,38 +214,39 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
@retval last_key Set to 1 if key is the last key in the page.
*/
int _ma_bin_search(const MARIA_KEY *key, uchar *page,
int _ma_bin_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page,
uint32 comp_flag, uchar **ret_pos,
uchar *buff __attribute__((unused)), my_bool *last_key)
{
int flag;
uint page_flag;
uint start, mid, end, save_end, totlength, nod_flag, used_length;
uint start, mid, end, save_end, totlength, nod_flag;
uint not_used[2];
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_SHARE *share= keyinfo->share;
uchar *page;
DBUG_ENTER("_ma_bin_search");
LINT_INIT(flag);
page_flag= _ma_get_keypage_flag(share, page);
page_flag= ma_page->flag;
if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
{
/* Keys have varying length, can't use binary search */
DBUG_RETURN(_ma_seq_search(key, page, comp_flag, ret_pos, buff, last_key));
DBUG_RETURN(_ma_seq_search(key, ma_page, comp_flag, ret_pos, buff,
last_key));
}
_ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
nod_flag);
nod_flag= ma_page->node;
totlength= keyinfo->keylength + nod_flag;
DBUG_ASSERT(used_length >= share->keypage_header + nod_flag + totlength);
DBUG_ASSERT(ma_page->size >= share->keypage_header + nod_flag + totlength);
start=0;
mid=1;
save_end= end= ((used_length - nod_flag - share->keypage_header) /
save_end= end= ((ma_page->size - nod_flag - share->keypage_header) /
totlength-1);
DBUG_PRINT("test",("page_length: %u end: %u", used_length, end));
page+= share->keypage_header + nod_flag;
DBUG_PRINT("test",("page_length: %u end: %u", ma_page->size, end));
page= ma_page->buff + share->keypage_header + nod_flag;
while (start != end)
{
......@@ -297,13 +301,14 @@ int _ma_bin_search(const MARIA_KEY *key, uchar *page,
@retval buff Copy of previous or identical unpacked key
*/
int _ma_seq_search(const MARIA_KEY *key, uchar *page,
int _ma_seq_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page,
uint32 comp_flag, uchar **ret_pos,
uchar *buff, my_bool *last_key)
{
int flag;
uint page_flag, nod_flag, length, used_length, not_used[2];
uint page_flag, nod_flag, length, not_used[2];
uchar t_buff[MARIA_MAX_KEY_BUFF], *end;
uchar *page;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_SHARE *share= keyinfo->share;
MARIA_KEY tmp_key;
......@@ -312,10 +317,10 @@ int _ma_seq_search(const MARIA_KEY *key, uchar *page,
LINT_INIT(flag);
LINT_INIT(length);
page_flag= _ma_get_keypage_flag(share, page);
_ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
nod_flag);
end= page + used_length;
page_flag= ma_page->flag;
nod_flag= ma_page->node;
page= ma_page->buff;
end= page + ma_page->size;
page+= share->keypage_header + nod_flag;
*ret_pos= (uchar*) page;
t_buff[0]=0; /* Avoid bugs */
......@@ -362,7 +367,7 @@ int _ma_seq_search(const MARIA_KEY *key, uchar *page,
Same interface as for _ma_seq_search()
*/
int _ma_prefix_search(const MARIA_KEY *key, uchar *page,
int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page,
uint32 nextflag, uchar **ret_pos, uchar *buff,
my_bool *last_key)
{
......@@ -372,11 +377,11 @@ int _ma_prefix_search(const MARIA_KEY *key, uchar *page,
flag is the value returned by ha_key_cmp and as treated as final
*/
int flag=0, my_flag=-1;
uint nod_flag, used_length, length, len, matched, cmplen, kseg_len;
uint nod_flag, length, len, matched, cmplen, kseg_len;
uint page_flag, prefix_len,suffix_len;
int key_len_skip, seg_len_pack, key_len_left;
uchar *end;
uchar *vseg, *saved_vseg, *saved_from;
uchar *end, *vseg, *saved_vseg, *saved_from;
uchar *page;
uchar tt_buff[MARIA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
uchar *saved_to;
const uchar *kseg;
......@@ -395,11 +400,11 @@ int _ma_prefix_search(const MARIA_KEY *key, uchar *page,
LINT_INIT(saved_vseg);
t_buff[0]=0; /* Avoid bugs */
page_flag= _ma_get_keypage_flag(share, page);
_ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
nod_flag);
page_flag= ma_page->flag;
nod_flag= ma_page->node;
page_flag&= KEYPAGE_FLAG_HAS_TRANSID; /* For faster test in loop */
end= page + used_length;
page= ma_page->buff;
end= page + ma_page->size;
page+= share->keypage_header + nod_flag;
*ret_pos= page;
kseg= key->data;
......@@ -1364,14 +1369,16 @@ uchar *_ma_skip_binary_pack_key(MARIA_KEY *key, uint page_flag,
@return pointer to next key
*/
uchar *_ma_get_key(MARIA_KEY *key, uchar *page, uchar *keypos)
uchar *_ma_get_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *keypos)
{
uint page_flag, nod_flag;
MARIA_KEYDEF *keyinfo= key->keyinfo;
uchar *page;
DBUG_ENTER("_ma_get_key");
page_flag= _ma_get_keypage_flag(keyinfo->share, page);
nod_flag= _ma_test_if_nod(keyinfo->share, page);
page= ma_page->buff;
page_flag= ma_page->flag;
nod_flag= ma_page->node;
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
......@@ -1410,14 +1417,15 @@ uchar *_ma_get_key(MARIA_KEY *key, uchar *page, uchar *keypos)
@retval 1 error
*/
static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos)
static my_bool _ma_get_prev_key(MARIA_KEY *key, MARIA_PAGE *ma_page,
uchar *keypos)
{
uint page_flag, nod_flag;
MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_prev_key");
page_flag= _ma_get_keypage_flag(keyinfo->share, page);
nod_flag= _ma_test_if_nod(keyinfo->share, page);
page_flag= ma_page->flag;
nod_flag= ma_page->node;
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
......@@ -1431,7 +1439,9 @@ static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos)
}
else
{
page+= keyinfo->share->keypage_header + nod_flag;
uchar *page;
page= ma_page->buff + keyinfo->share->keypage_header + nod_flag;
key->data[0]= 0; /* safety */
DBUG_ASSERT(page != keypos);
while (page < keypos)
......@@ -1458,17 +1468,19 @@ static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos)
@retval pointer to where key starts
*/
uchar *_ma_get_last_key(MARIA_KEY *key, uchar *page, uchar *endpos)
uchar *_ma_get_last_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *endpos)
{
uint page_flag,nod_flag;
uchar *lastpos;
uchar *lastpos, *page;
MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_last_key");
DBUG_PRINT("enter",("page: 0x%lx endpos: 0x%lx", (long) page,
DBUG_PRINT("enter",("page: 0x%lx endpos: 0x%lx", (long) ma_page->buff,
(long) endpos));
page_flag= _ma_get_keypage_flag(keyinfo->share, page);
nod_flag= _ma_test_if_nod(keyinfo->share, page);
page_flag= ma_page->flag;
nod_flag= ma_page->node;
page= ma_page->buff + keyinfo->share->keypage_header + nod_flag;
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
......@@ -1476,12 +1488,11 @@ uchar *_ma_get_last_key(MARIA_KEY *key, uchar *page, uchar *endpos)
key->ref_length= keyinfo->share->rec_reflength;
key->data_length= keyinfo->keylength - key->ref_length;
key->flag= 0;
if (lastpos > page)
if (lastpos >= page)
bmove(key->data, lastpos, keyinfo->keylength + nod_flag);
}
else
{
page+= keyinfo->share->keypage_header + nod_flag;
lastpos= page;
key->data[0]=0; /* safety */
while (page < endpos)
......@@ -1591,10 +1602,10 @@ int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key,
uint32 nextflag, my_off_t pos)
{
int error;
uint page_flag,nod_flag;
uchar lastkey[MARIA_MAX_KEY_BUFF];
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_KEY tmp_key;
MARIA_PAGE page;
DBUG_ENTER("_ma_search_next");
DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: 0x%lx page_changed %d keyread_buff_used: %d",
nextflag, (ulong) info->cur_row.lastpos,
......@@ -1619,25 +1630,27 @@ int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key,
if (info->keyread_buff_used)
{
if (!_ma_fetch_keypage(info, keyinfo, info->last_search_keypage,
if (_ma_fetch_keypage(&page, info, keyinfo, info->last_search_keypage,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->keyread_buff, 0, 0))
DFLT_INIT_HITS, info->keyread_buff, 0))
DBUG_RETURN(-1);
info->keyread_buff_used=0;
}
else
{
/* Last used buffer is in info->keyread_buff */
page_flag= _ma_get_keypage_flag(keyinfo->share, info->keyread_buff);
nod_flag= _ma_test_if_nod(keyinfo->share, info->keyread_buff);
/* Todo: Add info->keyread_page to keep track of this */
_ma_page_setup(&page, info, keyinfo, 0, info->keyread_buff);
}
tmp_key.data= lastkey;
info->last_key.keyinfo= tmp_key.keyinfo= keyinfo;
if (nextflag & SEARCH_BIGGER) /* Next key */
{
if (nod_flag)
if (page.node)
{
my_off_t tmp_pos= _ma_kpos(nod_flag,info->int_keypos);
my_off_t tmp_pos= _ma_kpos(page.node, info->int_keypos);
if ((error= _ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
tmp_pos)) <=0)
......@@ -1647,15 +1660,14 @@ int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key,
info->last_key.data != key->data)
memcpy(info->last_key.data, key->data,
key->data_length + key->ref_length);
if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag,
if (!(*keyinfo->get_key)(&info->last_key, page.flag, page.node,
&info->int_keypos))
DBUG_RETURN(-1);
}
else /* Previous key */
{
/* Find start of previous key */
info->int_keypos= _ma_get_last_key(&tmp_key, info->keyread_buff,
info->int_keypos);
info->int_keypos= _ma_get_last_key(&tmp_key, &page, info->int_keypos);
if (!info->int_keypos)
DBUG_RETURN(-1);
if (info->int_keypos == info->keyread_buff + info->s->keypage_header)
......@@ -1664,14 +1676,13 @@ int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key,
DBUG_RETURN(_ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
pos));
}
if (nod_flag &&
if (page.node &&
(error= _ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
_ma_kpos(nod_flag,info->int_keypos))) <= 0)
_ma_kpos(page.node,info->int_keypos))) <= 0)
DBUG_RETURN(error);
/* QQ: We should be able to optimize away the following call */
if (! _ma_get_last_key(&info->last_key, info->keyread_buff,
info->int_keypos))
if (! _ma_get_last_key(&info->last_key, &page, info->int_keypos))
DBUG_RETURN(-1);
}
info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
......@@ -1688,11 +1699,11 @@ int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key,
Found row is stored in info->cur_row.lastpos
*/
int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
register my_off_t pos)
int _ma_search_first(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t pos)
{
uint page_flag, nod_flag;
uchar *page;
uchar *first_pos;
MARIA_PAGE page;
MARIA_SHARE *share= info->s;
DBUG_ENTER("_ma_search_first");
......@@ -1705,28 +1716,26 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
do
{
if (!_ma_fetch_keypage(info, keyinfo, pos, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->keyread_buff, 0, 0))
if (_ma_fetch_keypage(&page, info, keyinfo, pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->keyread_buff, 0))
{
info->cur_row.lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1);
}
page_flag= _ma_get_keypage_flag(share, info->keyread_buff);
nod_flag= _ma_test_if_nod(share, info->keyread_buff);
page= info->keyread_buff + share->keypage_header + nod_flag;
} while ((pos= _ma_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
first_pos= page.buff + share->keypage_header + page.node;
} while ((pos= _ma_kpos(page.node, first_pos)) != HA_OFFSET_ERROR);
info->last_key.keyinfo= keyinfo;
if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag, &page))
if (!(*keyinfo->get_key)(&info->last_key, page.flag, page.node, &first_pos))
DBUG_RETURN(-1); /* Crashed */
info->int_keypos=page;
info->int_maxpos= (info->keyread_buff +
_ma_get_page_used(share, info->keyread_buff)-1);
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->int_keypos= first_pos;
info->int_maxpos= (page.buff + page.size -1);
info->int_nod_flag= page.node;
info->int_keytree_version= keyinfo->version;
info->last_search_keypage= info->last_keypage;
info->page_changed=info->keyread_buff_used=0;
info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
info->cur_row.trid= _ma_trid_from_key(&info->last_key);
......@@ -1743,11 +1752,11 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
Found row is stored in info->cur_row.lastpos
*/
int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
register my_off_t pos)
int _ma_search_last(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t pos)
{
uint page_flag, nod_flag;
uchar *buff,*end_of_page;
uchar *end_of_page;
MARIA_PAGE page;
DBUG_ENTER("_ma_search_last");
if (pos == HA_OFFSET_ERROR)
......@@ -1757,32 +1766,28 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_RETURN(-1);
}
buff=info->keyread_buff;
do
{
uint used_length;
if (!_ma_fetch_keypage(info, keyinfo, pos, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, buff, 0, 0))
if (_ma_fetch_keypage(&page, info, keyinfo, pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->keyread_buff, 0))
{
info->cur_row.lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1);
}
page_flag= _ma_get_keypage_flag(info->s, info->keyread_buff);
_ma_get_used_and_nod_with_flag(info->s, page_flag, buff, used_length,
nod_flag);
end_of_page= buff + used_length;
} while ((pos= _ma_kpos(nod_flag, end_of_page)) != HA_OFFSET_ERROR);
end_of_page= page.buff + page.size;
} while ((pos= _ma_kpos(page.node, end_of_page)) != HA_OFFSET_ERROR);
info->last_key.keyinfo= keyinfo;
if (!_ma_get_last_key(&info->last_key, buff, end_of_page))
if (!_ma_get_last_key(&info->last_key, &page, end_of_page))
DBUG_RETURN(-1);
info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
info->cur_row.trid= _ma_trid_from_key(&info->last_key);
info->int_keypos= info->int_maxpos= end_of_page;
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->int_nod_flag= page.node;
info->int_keytree_version= keyinfo->version;
info->last_search_keypage= info->last_keypage;
info->page_changed=info->keyread_buff_used=0;
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
......
......@@ -25,36 +25,32 @@
/* Functions declared in this file */
static int w_search(register MARIA_HA *info, uint32 comp_flag,
static int w_search(MARIA_HA *info, uint32 comp_flag,
MARIA_KEY *key, my_off_t page,
my_off_t father_page, uchar *father_buff,
MARIA_PINNED_PAGE *father_page_link, uchar *father_keypos,
MARIA_PAGE *father_page, uchar *father_keypos,
my_bool insert_last);
static int _ma_balance_page(MARIA_HA *info,MARIA_KEYDEF *keyinfo,
MARIA_KEY *key, uchar *curr_buff, my_off_t page,
my_off_t father_page, uchar *father_buff,
uchar *father_keypos,
MARIA_KEY_PARAM *s_temp);
static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEY *int_key,
uchar *page, uchar **after_key);
static int _ma_balance_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
MARIA_KEY *key, MARIA_PAGE *curr_page,
MARIA_PAGE *father_page,
uchar *father_key_pos, MARIA_KEY_PARAM *s_temp);
static uchar *_ma_find_last_pos(MARIA_KEY *int_key,
MARIA_PAGE *page, uchar **after_key);
static my_bool _ma_ck_write_tree(register MARIA_HA *info, MARIA_KEY *key);
static my_bool _ma_ck_write_btree(register MARIA_HA *info, MARIA_KEY *key);
static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
static my_bool _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
my_off_t *root, uint32 comp_flag);
static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, const uchar *buff,
uint org_length, uint new_length,
static my_bool _ma_log_split(MARIA_PAGE *page, uint org_length,
uint new_length,
const uchar *key_pos,
uint key_length, int move_length,
enum en_key_op prefix_or_suffix,
const uchar *data, uint data_length,
uint changed_length);
static my_bool _ma_log_del_prefix(MARIA_HA *info, my_off_t page,
const uchar *buff,
static my_bool _ma_log_del_prefix(MARIA_PAGE *page,
uint org_length, uint new_length,
const uchar *key_pos, uint key_length,
int move_length);
static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page,
const uchar *buff,
static my_bool _ma_log_key_middle(MARIA_PAGE *page,
uint new_length,
uint data_added_first,
uint data_changed_first,
......@@ -381,11 +377,11 @@ static my_bool _ma_ck_write_btree(MARIA_HA *info, MARIA_KEY *key)
/**
@brief Write a key to the b-tree
@retval -1 error
@retval 1 error
@retval 0 ok
*/
static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
static my_bool _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
my_off_t *root, uint32 comp_flag)
{
MARIA_SHARE *share= info->s;
......@@ -419,18 +415,18 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
}
_ma_unpin_all_pages_and_finalize_row(info, lsn);
DBUG_RETURN(error);
DBUG_RETURN(error != 0);
} /* _ma_ck_write_btree_with_log */
/**
@brief Write a key to the b-tree
@retval -1 error
@retval 1 error
@retval 0 ok
*/
int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEY *key, my_off_t *root,
my_bool _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEY *key, my_off_t *root,
uint32 comp_flag)
{
int error;
......@@ -438,68 +434,74 @@ int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEY *key, my_off_t *root,
/* key_length parameter is used only if comp_flag is SEARCH_FIND */
if (*root == HA_OFFSET_ERROR ||
(error= w_search(info, comp_flag, key, *root, (my_off_t) 0, (uchar*) 0,
(MARIA_PINNED_PAGE *) 0, (uchar*) 0, 1)) > 0)
(error= w_search(info, comp_flag, key, *root, (MARIA_PAGE *) 0,
(uchar*) 0, 1)) > 0)
error= _ma_enlarge_root(info, key, root);
DBUG_RETURN(error);
DBUG_RETURN(error != 0);
} /* _ma_ck_real_write_btree */
/**
@brief Make a new root with key as only pointer
@retval -1 error
@retval 1 error
@retval 0 ok
*/
int _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, my_off_t *root)
my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, my_off_t *root)
{
uint t_length, page_flag, nod_flag, page_length;
uint t_length, nod_flag;
MARIA_KEY_PARAM s_temp;
MARIA_SHARE *share= info->s;
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
MARIA_KEYDEF *keyinfo= key->keyinfo;
int res= 0;
MARIA_PAGE page;
my_bool res= 0;
DBUG_ENTER("_ma_enlarge_root");
page.info= info;
page.keyinfo= keyinfo;
page.buff= info->buff;
page.flag= 0;
nod_flag= (*root != HA_OFFSET_ERROR) ? share->base.key_reflength : 0;
/* Store pointer to prev page if nod */
_ma_kpointer(info, info->buff + share->keypage_header, *root);
_ma_kpointer(info, page.buff + share->keypage_header, *root);
t_length= (*keyinfo->pack_key)(key, nod_flag, (uchar*) 0,
(uchar*) 0, (uchar*) 0, &s_temp);
page_length= share->keypage_header + t_length + nod_flag;
page.size= share->keypage_header + t_length + nod_flag;
bzero(info->buff, share->keypage_header);
_ma_store_keynr(share, info->buff, keyinfo->key_nr);
_ma_store_page_used(share, info->buff, page_length);
page_flag= 0;
bzero(page.buff, share->keypage_header);
_ma_store_keynr(share, page.buff, keyinfo->key_nr);
if (nod_flag)
page_flag|= KEYPAGE_FLAG_ISNOD;
page.flag|= KEYPAGE_FLAG_ISNOD;
if (key->flag & (SEARCH_USER_KEY_HAS_TRANSID | SEARCH_PAGE_KEY_HAS_TRANSID))
page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
_ma_store_keypage_flag(share, info->buff, page_flag);
(*keyinfo->store_key)(keyinfo, info->buff + share->keypage_header +
page.flag|= KEYPAGE_FLAG_HAS_TRANSID;
(*keyinfo->store_key)(keyinfo, page.buff + share->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, PAGECACHE_PRIORITY_HIGH, &page_link)) ==
if ((page.pos= _ma_new(info, PAGECACHE_PRIORITY_HIGH, &page_link)) ==
HA_OFFSET_ERROR)
DBUG_RETURN(-1);
DBUG_RETURN(1);
*root= page.pos;
page_store_info(share, &page);
/*
Clear unitialized part of page to avoid valgrind/purify warnings
and to get a clean page that is easier to compress and compare with
pages generated with redo
*/
bzero(info->buff + page_length, share->block_size - page_length);
bzero(page.buff + page.size, share->block_size - page.size);
if (share->now_transactional &&
_ma_log_new(info, *root, info->buff, page_length, keyinfo->key_nr, 1))
res= -1;
if (_ma_write_keypage(info, keyinfo, *root, page_link->write_lock,
PAGECACHE_PRIORITY_HIGH, info->buff))
res= -1;
if (share->now_transactional && _ma_log_new(&page, 1))
res= 1;
if (_ma_write_keypage(&page, page_link->write_lock,
PAGECACHE_PRIORITY_HIGH))
res= 1;
DBUG_RETURN(res);
} /* _ma_enlarge_root */
......@@ -515,33 +517,30 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, my_off_t *root)
*/
static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
my_off_t page, my_off_t father_page, uchar *father_buff,
MARIA_PINNED_PAGE *father_page_link, uchar *father_keypos,
my_off_t page_pos,
MARIA_PAGE *father_page, uchar *father_keypos,
my_bool insert_last)
{
int error,flag;
uint page_flag, nod_flag;
uchar *temp_buff,*keypos;
uchar keybuff[MARIA_MAX_KEY_BUFF];
my_bool was_last_key;
my_off_t next_page, dup_key_pos;
MARIA_PINNED_PAGE *page_link;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_PAGE page;
DBUG_ENTER("w_search");
DBUG_PRINT("enter",("page: %ld", (long) page));
DBUG_PRINT("enter",("page: %ld", (long) page_pos));
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MARIA_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1);
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, temp_buff, 0, &page_link))
if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, temp_buff, 0))
goto err;
flag= (*keyinfo->bin_search)(key, temp_buff, comp_flag, &keypos,
flag= (*keyinfo->bin_search)(key, &page, comp_flag, &keypos,
keybuff, &was_last_key);
page_flag= _ma_get_keypage_flag(share, temp_buff);
nod_flag= _ma_test_if_nod(share, temp_buff);
if (flag == 0)
{
MARIA_KEY tmp_key;
......@@ -550,7 +549,7 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
tmp_key.keyinfo= keyinfo;
tmp_key.data= keybuff;
if ((*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &keypos))
if ((*keyinfo->get_key)(&tmp_key, page.flag, page.node, &keypos))
dup_key_pos= _ma_row_pos_from_key(&tmp_key);
else
dup_key_pos= HA_OFFSET_ERROR;
......@@ -566,7 +565,7 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
if (subkeys >= 0)
{
/* normal word, one-level tree structure */
flag=(*keyinfo->bin_search)(key, temp_buff, comp_flag,
flag=(*keyinfo->bin_search)(key, &page, comp_flag,
&keypos, keybuff, &was_last_key);
}
else
......@@ -577,7 +576,7 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
get_key_full_length_rdonly(off, key);
key+=off;
/* we'll modify key entry 'in vivo' */
keypos-= keyinfo->keylength + nod_flag;
keypos-= keyinfo->keylength + page.node;
error= _ma_ck_real_write_btree(info, key, &root, comp_flag);
_ma_dpointer(share, keypos+HA_FT_WLEN, root);
subkeys--; /* should there be underflow protection ? */
......@@ -585,12 +584,12 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
ft_intXstore(keypos, subkeys);
if (!error)
{
page_link->changed= 1;
error= _ma_write_keypage(info, keyinfo, page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, temp_buff);
page_mark_changed(info, &page);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
}
my_afree((uchar*) temp_buff);
my_afree(temp_buff);
DBUG_RETURN(error);
}
}
......@@ -598,34 +597,32 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
{
DBUG_PRINT("warning", ("Duplicate key"));
info->dup_key_pos= dup_key_pos;
my_afree((uchar*) temp_buff);
my_errno=HA_ERR_FOUND_DUPP_KEY;
DBUG_RETURN(-1);
goto err;
}
}
if (flag == MARIA_FOUND_WRONG_KEY)
DBUG_RETURN(-1);
goto err;
if (!was_last_key)
insert_last=0;
next_page= _ma_kpos(nod_flag,keypos);
next_page= _ma_kpos(page.node, keypos);
if (next_page == HA_OFFSET_ERROR ||
(error= w_search(info, comp_flag, key, next_page,
page, temp_buff, page_link, keypos, insert_last)) > 0)
{
error= _ma_insert(info, key, temp_buff, keypos, page, keybuff,
father_page, father_buff, father_page_link,
father_keypos, insert_last);
page_link->changed= 1;
if (_ma_write_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS,temp_buff))
&page, keypos, insert_last)) > 0)
{
error= _ma_insert(info, key, &page, keypos, keybuff,
father_page, father_keypos, insert_last);
page_mark_changed(info, &page);
if (_ma_write_keypage(&page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS))
goto err;
}
my_afree((uchar*) temp_buff);
my_afree(temp_buff);
DBUG_RETURN(error);
err:
my_afree((uchar*) temp_buff);
my_afree(temp_buff);
DBUG_PRINT("exit",("Error: %d",my_errno));
DBUG_RETURN (-1);
DBUG_RETURN(-1);
} /* w_search */
......@@ -637,13 +634,10 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
info Open table information.
keyinfo Key definition information.
key New key
anc_buff Key page (beginning).
anc_page Key page (beginning)
key_pos Position in key page where to insert.
anc_page Page number for anc_buff
key_buff Copy of previous key if keys where packed.
father_page position of parent key page in file.
father_buff parent key page for balancing.
father_page_link Link to father page for marking page changed
father_key_pos position in parent key page for balancing.
insert_last If to append at end of page.
......@@ -661,15 +655,14 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
2 If key contains key to upper level (from split space)
*/
int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
uchar *key_pos, my_off_t anc_page, uchar *key_buff,
my_off_t father_page, uchar *father_buff,
MARIA_PINNED_PAGE *father_page_link,
uchar *father_key_pos, my_bool insert_last)
int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
MARIA_PAGE *anc_page, uchar *key_pos, uchar *key_buff,
MARIA_PAGE *father_page, uchar *father_key_pos,
my_bool insert_last)
{
uint a_length, nod_flag, org_anc_length;
int t_length;
uchar *endpos, *prev_key;
uchar *endpos, *prev_key, *anc_buff;
MARIA_KEY_PARAM s_temp;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
......@@ -677,8 +670,10 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
DBUG_PRINT("enter",("key_pos: 0x%lx", (ulong) key_pos));
DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, key););
_ma_get_used_and_nod(share, anc_buff, a_length, nod_flag);
org_anc_length= a_length;
org_anc_length= a_length= anc_page->size;
nod_flag= anc_page->node;
anc_buff= anc_page->buff;
endpos= anc_buff+ a_length;
prev_key= (key_pos == anc_buff + share->keypage_header + nod_flag ?
(uchar*) 0 : key_buff);
......@@ -702,7 +697,6 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
{
if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
maria_print_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
......@@ -713,7 +707,6 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
{
if (-t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
maria_print_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
......@@ -723,8 +716,11 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
a_length+=t_length;
if (key->flag & (SEARCH_USER_KEY_HAS_TRANSID | SEARCH_PAGE_KEY_HAS_TRANSID))
_ma_mark_page_with_transid(share, anc_buff);
_ma_store_page_used(share, anc_buff, a_length);
{
_ma_mark_page_with_transid(share, anc_page);
}
anc_page->size= a_length;
page_store_size(share, anc_page);
/*
Check if the new key fits totally into the the page
......@@ -784,8 +780,8 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
insert_dynamic(info->ft1_to_ft2, b);
/* fixing the page's length - it contains only one key now */
_ma_store_page_used(share, anc_buff, share->keypage_header + blen +
ft2len + 2);
anc_page->size= share->keypage_header + blen + ft2len + 2;
page_store_size(share, anc_page);
}
/* the rest will be done when we're back from recursion */
}
......@@ -793,7 +789,7 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
else
{
if (share->now_transactional &&
_ma_log_add(info, anc_page, anc_buff, (uint) (endpos - anc_buff),
_ma_log_add(anc_page, org_anc_length,
key_pos, s_temp.changed_length, t_length, 0))
DBUG_RETURN(-1);
}
......@@ -809,17 +805,16 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
_ma_balance_page_ can't handle variable length keys.
*/
if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
father_buff && !insert_last && !info->quick_mode &&
father_page && !insert_last && !info->quick_mode &&
!info->s->base.born_transactional)
{
s_temp.key_pos= key_pos;
father_page_link->changed= 1;
DBUG_RETURN(_ma_balance_page(info, keyinfo, key, anc_buff, anc_page,
father_page, father_buff, father_key_pos,
page_mark_changed(info, father_page);
DBUG_RETURN(_ma_balance_page(info, keyinfo, key, anc_page,
father_page, father_key_pos,
&s_temp));
}
DBUG_RETURN(_ma_split_page(info, key, anc_page,
anc_buff, org_anc_length,
DBUG_RETURN(_ma_split_page(info, key, anc_page, org_anc_length,
key_pos, s_temp.changed_length, t_length,
key_buff, insert_last));
} /* _ma_insert */
......@@ -832,9 +827,8 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
info Maria handler
keyinfo Key handler
key Buffer for middle key
split_page Address on disk for split_buff
split_buff Page buffer for page that should be split
org_split_length Original length of split_buff before key was inserted
split_page Page that should be split
org_split_length Original length of split_page before key was inserted
inserted_key_pos Address in buffer where key was inserted
changed_length Number of bytes changed at 'inserted_key_pos'
move_length Number of bytes buffer was moved when key was inserted
......@@ -849,8 +843,7 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
@retval -1 error
*/
int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, my_off_t split_page,
uchar *split_buff,
int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, MARIA_PAGE *split_page,
uint org_split_length,
uchar *inserted_key_pos, uint changed_length,
int move_length,
......@@ -858,57 +851,60 @@ int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, my_off_t split_page,
{
uint length,a_length,key_ref_length,t_length,nod_flag,key_length;
uint page_length, split_length, page_flag;
uchar *key_pos,*pos, *after_key, *new_buff;
my_off_t new_pos;
uchar *key_pos,*pos, *after_key;
MARIA_KEY_PARAM s_temp;
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_KEY tmp_key;
MARIA_PAGE new_page;
int res;
DBUG_ENTER("_ma_split_page");
LINT_INIT(after_key);
DBUG_DUMP("buff", split_buff, _ma_get_page_used(share, split_buff));
DBUG_DUMP("buff", split_page->buff, split_page->size);
info->page_changed=1; /* Info->buff is used */
info->keyread_buff_used=1;
new_buff= info->buff;
page_flag= _ma_get_keypage_flag(share, split_buff);
nod_flag= _ma_test_if_nod(share, split_buff);
page_flag= split_page->flag;
nod_flag= split_page->node;
key_ref_length= share->keypage_header + nod_flag;
new_page.info= info;
new_page.buff= info->buff;
new_page.keyinfo= keyinfo;
tmp_key.data= key_buff;
tmp_key.keyinfo= keyinfo;
if (insert_last_key)
key_pos= _ma_find_last_pos(info, &tmp_key, split_buff, &after_key);
key_pos= _ma_find_last_pos(&tmp_key, split_page, &after_key);
else
key_pos= _ma_find_half_pos(info, &tmp_key, nod_flag, split_buff,
&after_key);
key_pos= _ma_find_half_pos(&tmp_key, split_page, &after_key);
if (!key_pos)
DBUG_RETURN(-1);
key_length= tmp_key.data_length + tmp_key.ref_length;
split_length= (uint) (key_pos - split_buff);
a_length= _ma_get_page_used(share, split_buff);
_ma_store_page_used(share, split_buff, split_length);
split_length= (uint) (key_pos - split_page->buff);
a_length= split_page->size;
split_page->size= split_length;
page_store_size(share, split_page);
key_pos=after_key;
if (nod_flag)
{
DBUG_PRINT("test",("Splitting nod"));
pos=key_pos-nod_flag;
memcpy((uchar*) new_buff + share->keypage_header, (uchar*) pos,
memcpy((uchar*) new_page.buff + share->keypage_header, (uchar*) pos,
(size_t) nod_flag);
}
/* Move middle item to key and pointer to new page */
if ((new_pos= _ma_new(info, PAGECACHE_PRIORITY_HIGH, &page_link)) ==
if ((new_page.pos= _ma_new(info, PAGECACHE_PRIORITY_HIGH, &page_link)) ==
HA_OFFSET_ERROR)
DBUG_RETURN(-1);
_ma_copy_key(key, &tmp_key);
_ma_kpointer(info, key->data + key_length, new_pos);
_ma_kpointer(info, key->data + key_length, new_page.pos);
/* Store new page */
if (!(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &key_pos))
......@@ -916,36 +912,42 @@ int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, my_off_t split_page,
t_length=(*keyinfo->pack_key)(&tmp_key, nod_flag, (uchar *) 0,
(uchar*) 0, (uchar*) 0, &s_temp);
length=(uint) ((split_buff + a_length) - key_pos);
memcpy((uchar*) new_buff+key_ref_length+t_length,(uchar*) key_pos,
length=(uint) ((split_page->buff + a_length) - key_pos);
memcpy((uchar*) new_page.buff+key_ref_length+t_length,(uchar*) key_pos,
(size_t) length);
(*keyinfo->store_key)(keyinfo,new_buff+key_ref_length,&s_temp);
(*keyinfo->store_key)(keyinfo,new_page.buff+key_ref_length,&s_temp);
page_length= length + t_length + key_ref_length;
bzero(new_buff, share->keypage_header);
bzero(new_page.buff, share->keypage_header);
/* Copy KEYFLAG_FLAG_ISNODE and KEYPAGE_FLAG_HAS_TRANSID from parent page */
_ma_store_keypage_flag(share, new_buff, page_flag);
_ma_store_page_used(share, new_buff, page_length);
new_page.flag= page_flag;
new_page.size= page_length;
page_store_info(share, &new_page);
/* Copy key number */
new_buff[share->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
KEYPAGE_FLAG_SIZE]=
split_buff[share->keypage_header - KEYPAGE_USED_SIZE -
new_page.buff[share->keypage_header - KEYPAGE_USED_SIZE -
KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]=
split_page->buff[share->keypage_header - KEYPAGE_USED_SIZE -
KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE];
res= 2; /* Middle key up */
if (share->now_transactional &&
_ma_log_new(info, new_pos, new_buff, page_length, keyinfo->key_nr, 0))
if (share->now_transactional && _ma_log_new(&new_page, 0))
res= -1;
bzero(new_buff + page_length, share->block_size - page_length);
if (_ma_write_keypage(info, keyinfo, new_pos, page_link->write_lock,
DFLT_INIT_HITS, new_buff))
/*
Clear unitialized part of page to avoid valgrind/purify warnings
and to get a clean page that is easier to compress and compare with
pages generated with redo
*/
bzero(new_page.buff + page_length, share->block_size - page_length);
if (_ma_write_keypage(&new_page, page_link->write_lock,
DFLT_INIT_HITS))
res= -1;
/* Save changes to split pages */
if (share->now_transactional &&
_ma_log_split(info, split_page, split_buff, org_split_length,
split_length,
_ma_log_split(split_page, org_split_length, split_length,
inserted_key_pos, changed_length, move_length,
KEY_OP_NONE, (uchar*) 0, 0, 0))
res= -1;
......@@ -964,19 +966,22 @@ int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, my_off_t split_page,
after_key will contain the position to where the next key starts
*/
uchar *_ma_find_half_pos(MARIA_HA *info, MARIA_KEY *key, uint nod_flag,
uchar *page, uchar **after_key)
uchar *_ma_find_half_pos(MARIA_KEY *key, MARIA_PAGE *ma_page,
uchar **after_key)
{
uint keys, length, key_ref_length, page_flag;
uchar *end,*lastpos;
uint keys, length, key_ref_length, page_flag, nod_flag;
uchar *page, *end, *lastpos;
MARIA_HA *info= ma_page->info;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_find_half_pos");
nod_flag= ma_page->node;
key_ref_length= share->keypage_header + nod_flag;
page_flag= _ma_get_keypage_flag(share, page);
length= _ma_get_page_used(share, page) - key_ref_length;
page+= key_ref_length; /* Point to first key */
page_flag= ma_page->flag;
length= ma_page->size - key_ref_length;
page= ma_page->buff+ 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)) && !(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
......@@ -1023,21 +1028,23 @@ uchar *_ma_find_half_pos(MARIA_HA *info, MARIA_KEY *key, uint nod_flag,
@retval int_key will contain the last key
*/
static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEY *int_key,
uchar *page, uchar **after_key)
static uchar *_ma_find_last_pos(MARIA_KEY *int_key, MARIA_PAGE *ma_page,
uchar **after_key)
{
uint keys, length, key_ref_length, page_flag;
uchar *end, *lastpos, *prevpos;
uchar *page, *end, *lastpos, *prevpos;
uchar key_buff[MARIA_MAX_KEY_BUFF];
MARIA_HA *info= ma_page->info;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo= int_key->keyinfo;
MARIA_KEY tmp_key;
DBUG_ENTER("_ma_find_last_pos");
key_ref_length= share->keypage_header;
page_flag= _ma_get_keypage_flag(share, page);
length= _ma_get_page_used(share, page) - key_ref_length;
page+=key_ref_length;
page_flag= ma_page->flag;
length= ma_page->size - key_ref_length;
page= ma_page->buff + key_ref_length;
if (!(keyinfo->flag &
(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
HA_BINARY_PACK_KEY)) && !(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
......@@ -1063,7 +1070,6 @@ static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEY *int_key,
if (!(length=(*keyinfo->get_key)(&tmp_key, page_flag, 0, &page)))
{
maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
......@@ -1077,7 +1083,6 @@ static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEY *int_key,
memcpy(int_key->data, key_buff, length); /* previous key */
if (!(length=(*keyinfo->get_key)(&tmp_key, page_flag, 0, &page)))
{
maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
......@@ -1105,62 +1110,61 @@ static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEY *int_key,
@retval -1 Error
*/
static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
MARIA_KEY *key, uchar *curr_buff,
my_off_t curr_page,
my_off_t father_page, uchar *father_buff,
static int _ma_balance_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
MARIA_KEY *key, MARIA_PAGE *curr_page,
MARIA_PAGE *father_page,
uchar *father_key_pos, MARIA_KEY_PARAM *s_temp)
{
MARIA_PINNED_PAGE *next_page_link;
MARIA_PINNED_PAGE tmp_page_link, *new_page_link= &tmp_page_link;
MARIA_SHARE *share= info->s;
my_bool right;
uint k_length,father_length,father_keylength,nod_flag,curr_keylength;
uint right_length,left_length,new_right_length,new_left_length,extra_length;
uint keys, tmp_length, extra_buff_length;
uchar *pos,*buff,*extra_buff, *parting_key;
my_off_t next_page,new_pos;
uchar *pos, *extra_buff, *parting_key;
uchar tmp_part_key[MARIA_MAX_KEY_BUFF];
MARIA_PAGE next_page, extra_page, *left_page, *right_page;
DBUG_ENTER("_ma_balance_page");
k_length=keyinfo->keylength;
father_length= _ma_get_page_used(share, father_buff);
k_length= keyinfo->keylength;
father_length= father_page->size;
father_keylength= k_length + share->base.key_reflength;
nod_flag= _ma_test_if_nod(share, curr_buff);
curr_keylength=k_length+nod_flag;
nod_flag= curr_page->node;
curr_keylength= k_length+nod_flag;
info->page_changed=1;
if ((father_key_pos != father_buff+father_length &&
if ((father_key_pos != father_page->buff+father_length &&
(info->state->records & 1)) ||
father_key_pos == father_buff+ share->keypage_header +
father_key_pos == father_page->buff+ share->keypage_header +
share->base.key_reflength)
{
right=1;
next_page= _ma_kpos(share->base.key_reflength,
next_page.pos= _ma_kpos(share->base.key_reflength,
father_key_pos+father_keylength);
buff=info->buff;
DBUG_PRINT("info", ("use right page: %lu", (ulong) next_page));
left_page= curr_page;
right_page= &next_page;
DBUG_PRINT("info", ("use right page: %lu", (ulong) next_page.pos));
}
else
{
right=0;
father_key_pos-=father_keylength;
next_page= _ma_kpos(share->base.key_reflength,father_key_pos);
/* Move curr_buff so that it's on the left */
buff= curr_buff;
curr_buff= info->buff;
DBUG_PRINT("info", ("use left page: %lu", (ulong) next_page));
next_page.pos= _ma_kpos(share->base.key_reflength,father_key_pos);
left_page= &next_page;
right_page= curr_page;
DBUG_PRINT("info", ("use left page: %lu", (ulong) next_page.pos));
} /* father_key_pos ptr to parting key */
if (!_ma_fetch_keypage(info,keyinfo, next_page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, info->buff, 0, &next_page_link))
if (_ma_fetch_keypage(&next_page, info, keyinfo, next_page.pos,
PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, info->buff, 0))
goto err;
next_page_link->changed= 1;
DBUG_DUMP("next", info->buff, _ma_get_page_used(share, info->buff));
page_mark_changed(info, &next_page);
DBUG_DUMP("next", next_page.buff, next_page.size);
/* Test if there is room to share keys */
left_length= _ma_get_page_used(share, curr_buff);
right_length= _ma_get_page_used(share, buff);
left_length= left_page->size;
right_length= right_page->size;
keys= ((left_length+right_length-share->keypage_header*2-nod_flag*2)/
curr_keylength);
......@@ -1171,8 +1175,10 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
new_left_length= share->keypage_header+nod_flag+(keys/2)*curr_keylength;
new_right_length=share->keypage_header+nod_flag+(((keys+1)/2)*
curr_keylength);
_ma_store_page_used(share, curr_buff, new_left_length);
_ma_store_page_used(share, buff, new_right_length);
left_page->size= new_left_length;
page_store_size(share, left_page);
right_page->size= new_right_length;
page_store_size(share, right_page);
DBUG_PRINT("info", ("left_length: %u -> %u right_length: %u -> %u",
left_length, new_left_length,
......@@ -1182,14 +1188,15 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint length;
DBUG_PRINT("info", ("move keys to end of buff"));
/* Move keys buff -> curr_buff */
pos=curr_buff+left_length;
/* Move keys right_page -> left_page */
pos= left_page->buff+left_length;
memcpy(pos,father_key_pos, (size_t) k_length);
memcpy(pos+k_length, buff + share->keypage_header,
memcpy(pos+k_length, right_page->buff + share->keypage_header,
(size_t) (length=new_left_length - left_length - k_length));
pos= buff + share->keypage_header + length;
pos= right_page->buff + share->keypage_header + length;
memcpy(father_key_pos, pos, (size_t) k_length);
bmove(buff + share->keypage_header, pos + k_length, new_right_length);
bmove(right_page->buff + share->keypage_header,
pos + k_length, new_right_length);
if (share->now_transactional)
{
......@@ -1197,17 +1204,17 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
{
/*
Log changes to page on left
The original page is on the left and stored in curr_buff
The original page is on the left and stored in left_page->buff
We have on the page the newly inserted key and data
from buff added last on the page
*/
if (_ma_log_split(info, curr_page, curr_buff,
if (_ma_log_split(curr_page,
left_length - s_temp->move_length,
new_left_length,
s_temp->key_pos, s_temp->changed_length,
s_temp->move_length,
KEY_OP_ADD_SUFFIX,
curr_buff + left_length,
curr_page->buff + left_length,
new_left_length - left_length,
new_left_length - left_length+ k_length))
goto err;
......@@ -1216,7 +1223,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
This contains the original data with some keys deleted from
start of page
*/
if (_ma_log_prefix(info, next_page, buff, 0,
if (_ma_log_prefix(&next_page, 0,
((int) new_right_length - (int) right_length)))
goto err;
}
......@@ -1227,7 +1234,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
Data is removed from start of page
The inserted key may be in buff or moved to curr_buff
*/
if (_ma_log_del_prefix(info, curr_page, buff,
if (_ma_log_del_prefix(curr_page,
right_length - s_temp->changed_length,
new_right_length,
s_temp->key_pos, s_temp->changed_length,
......@@ -1236,8 +1243,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/*
Log changes to page on left, which has new data added last
*/
if (_ma_log_suffix(info, next_page, curr_buff,
left_length, new_left_length))
if (_ma_log_suffix(&next_page, left_length, new_left_length))
goto err;
}
}
......@@ -1245,16 +1251,18 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
else
{
uint length;
DBUG_PRINT("info", ("move keys to start of buff"));
DBUG_PRINT("info", ("move keys to start of right_page"));
bmove_upp(buff + new_right_length, buff + right_length,
bmove_upp(right_page->buff + new_right_length,
right_page->buff + right_length,
right_length - share->keypage_header);
length= new_right_length -right_length - k_length;
memcpy(buff + share->keypage_header + length, father_key_pos,
memcpy(right_page->buff + share->keypage_header + length, father_key_pos,
(size_t) k_length);
pos=curr_buff+new_left_length;
pos= left_page->buff + new_left_length;
memcpy(father_key_pos, pos, (size_t) k_length);
memcpy(buff + share->keypage_header, pos+k_length, (size_t) length);
memcpy(right_page->buff + share->keypage_header, pos+k_length,
(size_t) length);
if (share->now_transactional)
{
......@@ -1265,7 +1273,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
The original page is on the left and stored in curr_buff
The page is shortened from end and the key may be on the page
*/
if (_ma_log_split(info, curr_page, curr_buff,
if (_ma_log_split(curr_page,
left_length - s_temp->move_length,
new_left_length,
s_temp->key_pos, s_temp->changed_length,
......@@ -1277,7 +1285,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
This contains the original data, with some data from cur_buff
added first
*/
if (_ma_log_prefix(info, next_page, buff,
if (_ma_log_prefix(&next_page,
(uint) (new_right_length - right_length),
(int) (new_right_length - right_length)))
goto err;
......@@ -1290,21 +1298,20 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
from buff added first on the page
*/
uint diff_length= new_right_length - right_length;
if (_ma_log_split(info, curr_page, buff,
if (_ma_log_split(curr_page,
left_length - s_temp->move_length,
new_right_length,
s_temp->key_pos + diff_length,
s_temp->changed_length,
s_temp->move_length,
KEY_OP_ADD_PREFIX,
buff + share->keypage_header,
curr_page->buff + share->keypage_header,
diff_length, diff_length + k_length))
goto err;
/*
Log changes to page on left, which is shortened from end
*/
if (_ma_log_suffix(info, next_page, curr_buff,
left_length, new_left_length))
if (_ma_log_suffix(&next_page, left_length, new_left_length))
goto err;
}
}
......@@ -1313,29 +1320,31 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/* Log changes to father (one level up) page */
if (share->now_transactional &&
_ma_log_change(info, father_page, father_buff, father_key_pos,
k_length))
_ma_log_change(father_page, father_key_pos, k_length))
goto err;
/*
next_page_link->changed is marked as true above and fathers
page_link->changed is marked as true in caller
*/
if (_ma_write_keypage(info, keyinfo, next_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, info->buff) ||
_ma_write_keypage(info, keyinfo, father_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS,
father_buff))
if (_ma_write_keypage(&next_page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS) ||
_ma_write_keypage(father_page,
PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS))
goto err;
DBUG_RETURN(0);
}
/* curr_buff[] and buff[] are full, lets split and make new nod */
/* left_page and right_page are full, lets split and make new nod */
extra_buff= info->buff+share->base.max_key_block_length;
new_left_length= new_right_length= (share->keypage_header + nod_flag +
(keys+1) / 3 * curr_keylength);
extra_page.info= info;
extra_page.keyinfo= keyinfo;
extra_page.buff= extra_buff;
extra_page.flag= 0;
/*
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
......@@ -1350,21 +1359,23 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
left_length, right_length,
new_left_length, new_right_length,
extra_length));
_ma_store_page_used(share, curr_buff, new_left_length);
_ma_store_page_used(share, buff, new_right_length);
left_page->size= new_left_length;
page_store_size(share, left_page);
right_page->size= new_right_length;
page_store_size(share, right_page);
bzero(extra_buff, share->keypage_header);
if (nod_flag)
_ma_store_keypage_flag(share, extra_buff, KEYPAGE_FLAG_ISNOD);
extra_page.flag= nod_flag ? KEYPAGE_FLAG_ISNOD : 0;
extra_page.size= extra_buff_length;
/* Copy key number */
extra_buff[share->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
KEYPAGE_FLAG_SIZE]=
buff[share->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
KEYPAGE_FLAG_SIZE];
_ma_store_page_used(share, extra_buff, extra_buff_length);
KEYPAGE_FLAG_SIZE]= keyinfo->key_nr;
page_store_info(share, &extra_page);
/* move first largest keys to new page */
pos=buff+right_length-extra_length;
pos= right_page->buff + right_length-extra_length;
memcpy(extra_buff + share->keypage_header, pos, extra_length);
/* Zero old data from buffer */
bzero(extra_buff + extra_buff_length,
......@@ -1373,43 +1384,52 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/* Save new parting key between buff and extra_buff */
memcpy(tmp_part_key, pos-k_length,k_length);
/* Make place for new keys */
bmove_upp(buff+ new_right_length, pos - k_length,
bmove_upp(right_page->buff + new_right_length, pos - k_length,
right_length - extra_length - k_length - share->keypage_header);
/* Copy keys from left page */
pos= curr_buff+new_left_length;
memcpy(buff + share->keypage_header, pos + k_length,
pos= left_page->buff + new_left_length;
memcpy(right_page->buff + share->keypage_header, pos + k_length,
(size_t) (tmp_length= left_length - new_left_length - k_length));
/* Copy old parting key */
parting_key= buff + share->keypage_header + tmp_length;
parting_key= right_page->buff + share->keypage_header + tmp_length;
memcpy(parting_key, father_key_pos, (size_t) k_length);
/* Move new parting keys up to caller */
memcpy((right ? key->data : father_key_pos),pos,(size_t) k_length);
memcpy((right ? father_key_pos : key->data),tmp_part_key, k_length);
if ((new_pos= _ma_new(info, DFLT_INIT_HITS, &new_page_link))
if ((extra_page.pos= _ma_new(info, DFLT_INIT_HITS, &new_page_link))
== HA_OFFSET_ERROR)
goto err;
_ma_kpointer(info,key->data+k_length,new_pos);
_ma_kpointer(info,key->data+k_length, extra_page.pos);
/* This is safe as long we are using not keys with transid */
key->data_length= k_length - info->s->rec_reflength;
key->ref_length= info->s->rec_reflength;
if (share->now_transactional)
{
if (right)
{
/*
Page order according to key values:
orignal_page (curr_buff), next_page (buff), extra_buff
orignal_page (curr_page = left_page), next_page (buff), extra_buff
cur_buff is shortened,
buff is getting new keys at start and shortened from end.
extra_buff is new page
Move page positions so that we store data in extra_page where
next_page was and next_page will be stored at the new position
*/
swap_variables(my_off_t, extra_page.pos, next_page.pos);
}
Note that extra_buff (largest key parts) will be stored at the
place of the original 'right' page (next_page) and right page (buff)
will be stored at new_pos.
if (share->now_transactional)
{
if (right)
{
/*
left_page is shortened,
right_page is getting new keys at start and shortened from end.
extra_page is new page
Note that extra_page (largest key parts) will be stored at the
place of the original 'right' page (next_page) and right page
will be stored at the new page position
This makes the log entries smaller as right_page contains all
data to generate the data extra_buff
......@@ -1418,7 +1438,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/*
Log changes to page on left (page shortened page at end)
*/
if (_ma_log_split(info, curr_page, curr_buff,
if (_ma_log_split(curr_page,
left_length - s_temp->move_length, new_left_length,
s_temp->key_pos, s_temp->changed_length,
s_temp->move_length,
......@@ -1428,7 +1448,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
Log changes to right page (stored at next page)
This contains the last 'extra_buff' from 'buff'
*/
if (_ma_log_prefix(info, next_page, extra_buff,
if (_ma_log_prefix(&extra_page,
0, (int) (extra_buff_length - right_length)))
goto err;
......@@ -1436,8 +1456,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
Log changes to middle page, which is stored at the new page
position
*/
if (_ma_log_new(info, new_pos, buff, new_right_length,
keyinfo->key_nr, 0))
if (_ma_log_new(&next_page, 0))
goto err;
}
else
......@@ -1448,7 +1467,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
added first and shortened at end
*/
int data_added_first= left_length - new_left_length;
if (_ma_log_key_middle(info, curr_page, buff,
if (_ma_log_key_middle(right_page,
new_right_length,
data_added_first,
data_added_first,
......@@ -1459,31 +1478,28 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
goto err;
/* Log changes to page on left, which is shortened from end */
if (_ma_log_suffix(info, next_page, curr_buff,
left_length, new_left_length))
if (_ma_log_suffix(left_page, left_length, new_left_length))
goto err;
/* Log change to rightmost (new) page */
if (_ma_log_new(info, new_pos, extra_buff,
extra_buff_length, keyinfo->key_nr, 0))
if (_ma_log_new(&extra_page, 0))
goto err;
}
/* Log changes to father (one level up) page */
if (share->now_transactional &&
_ma_log_change(info, father_page, father_buff, father_key_pos,
k_length))
_ma_log_change(father_page, father_key_pos, k_length))
goto err;
}
if (_ma_write_keypage(info, keyinfo, (right ? new_pos : next_page),
if (_ma_write_keypage(&next_page,
(right ? new_page_link->write_lock :
PAGECACHE_LOCK_LEFT_WRITELOCKED),
DFLT_INIT_HITS, info->buff) ||
_ma_write_keypage(info, keyinfo, (right ? next_page : new_pos),
DFLT_INIT_HITS) ||
_ma_write_keypage(&extra_page,
(!right ? new_page_link->write_lock :
PAGECACHE_LOCK_LEFT_WRITELOCKED),
DFLT_INIT_HITS, extra_buff))
DFLT_INIT_HITS))
goto err;
DBUG_RETURN(1); /* Middle key up */
......@@ -1739,21 +1755,23 @@ int _ma_write_undo_key_insert(MARIA_HA *info, const MARIA_KEY *key,
@retval 0 ok
*/
my_bool _ma_log_new(MARIA_HA *info, my_off_t page, const uchar *buff,
uint page_length, uint key_nr, my_bool root_page)
my_bool _ma_log_new(MARIA_PAGE *ma_page, my_bool root_page)
{
LSN lsn;
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE * 2 + KEY_NR_STORE_SIZE
+1];
uint page_length;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
MARIA_HA *info= ma_page->info;
MARIA_SHARE *share= info->s;
my_off_t page;
DBUG_ENTER("_ma_log_new");
DBUG_PRINT("enter", ("page: %lu", (ulong) page));
DBUG_PRINT("enter", ("page: %lu", (ulong) ma_page->pos));
DBUG_ASSERT(share->now_transactional);
/* Store address of new root page */
page/= share->block_size;
page= ma_page->pos / share->block_size;
page_store(log_data + FILEID_STORE_SIZE, page);
/* Store link to next unused page */
......@@ -1764,20 +1782,22 @@ my_bool _ma_log_new(MARIA_HA *info, my_off_t page, const uchar *buff,
share->key_del_current / share->block_size);
page_store(log_data + FILEID_STORE_SIZE + PAGE_STORE_SIZE, page);
key_nr_store(log_data + FILEID_STORE_SIZE + PAGE_STORE_SIZE*2, key_nr);
key_nr_store(log_data + FILEID_STORE_SIZE + PAGE_STORE_SIZE*2,
ma_page->keyinfo->key_nr);
log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE*2 + KEY_NR_STORE_SIZE]=
(uchar) root_page;
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
page_length-= LSN_STORE_SIZE;
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= buff + LSN_STORE_SIZE;
page_length= ma_page->size - LSN_STORE_SIZE;
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= ma_page->buff + LSN_STORE_SIZE;
log_array[TRANSLOG_INTERNAL_PARTS + 1].length= page_length;
if (translog_write_record(&lsn, LOGREC_REDO_INDEX_NEW_PAGE,
info->trn, info,
(translog_size_t) (sizeof(log_data) + page_length),
(translog_size_t)
(sizeof(log_data) + page_length),
TRANSLOG_INTERNAL_PARTS + 2, log_array,
log_data, NULL))
DBUG_RETURN(1);
......@@ -1790,20 +1810,23 @@ my_bool _ma_log_new(MARIA_HA *info, my_off_t page, const uchar *buff,
Log when some part of the key page changes
*/
my_bool _ma_log_change(MARIA_HA *info, my_off_t page, const uchar *buff,
my_bool _ma_log_change(MARIA_PAGE *ma_page,
const uchar *key_pos, uint length)
{
LSN lsn;
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 6 + 7], *log_pos;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
uint offset= (uint) (key_pos - buff), translog_parts, extra_length= 0;
uint offset= (uint) (key_pos - ma_page->buff), translog_parts;
uint extra_length= 0;
my_off_t page;
MARIA_HA *info= ma_page->info;
DBUG_ENTER("_ma_log_change");
DBUG_PRINT("enter", ("page: %lu length: %u", (ulong) page, length));
DBUG_PRINT("enter", ("page: %lu length: %u", (ulong) ma_page->pos, length));
DBUG_ASSERT(info->s->now_transactional);
/* Store address of new root page */
page/= info->s->block_size;
page= ma_page->pos / info->s->block_size;
page_store(log_data + FILEID_STORE_SIZE, page);
log_pos= log_data+ FILEID_STORE_SIZE + PAGE_STORE_SIZE;
log_pos[0]= KEY_OP_OFFSET;
......@@ -1819,9 +1842,10 @@ my_bool _ma_log_change(MARIA_HA *info, my_off_t page, const uchar *buff,
#ifdef EXTRA_DEBUG_KEY_CHANGES
{
int page_length= _ma_get_page_used(info->s, buff);
int page_length= ma_page->size;
ha_checksum crc;
crc= my_checksum(0, buff + LSN_STORE_SIZE, page_length - LSN_STORE_SIZE);
crc= my_checksum(0, ma_page->buff + LSN_STORE_SIZE,
page_length - LSN_STORE_SIZE);
log_pos+= 6;
log_pos[0]= KEY_OP_CHECK;
int2store(log_pos+1, page_length);
......@@ -1860,7 +1884,7 @@ my_bool _ma_log_change(MARIA_HA *info, my_off_t page, const uchar *buff,
*/
static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, const uchar *buff,
static my_bool _ma_log_split(MARIA_PAGE *ma_page,
uint org_length, uint new_length,
const uchar *key_pos, uint key_length,
int move_length, enum en_key_op prefix_or_suffix,
......@@ -1871,14 +1895,16 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, const uchar *buff,
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3+3+3+3+3+2];
uchar *log_pos;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
uint offset= (uint) (key_pos - buff);
uint offset= (uint) (key_pos - ma_page->buff);
uint translog_parts, extra_length;
MARIA_HA *info= ma_page->info;
my_off_t page;
DBUG_ENTER("_ma_log_split");
DBUG_PRINT("enter", ("page: %lu org_length: %u new_length: %u",
(ulong) page, org_length, new_length));
(ulong) ma_page->pos, org_length, new_length));
log_pos= log_data + FILEID_STORE_SIZE;
page/= info->s->block_size;
page= ma_page->pos / info->s->block_size;
page_store(log_pos, page);
log_pos+= PAGE_STORE_SIZE;
......@@ -1995,8 +2021,7 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, const uchar *buff,
@retval 1 error
*/
static my_bool _ma_log_del_prefix(MARIA_HA *info, my_off_t page,
const uchar *buff,
static my_bool _ma_log_del_prefix(MARIA_PAGE *ma_page,
uint org_length, uint new_length,
const uchar *key_pos, uint key_length,
int move_length)
......@@ -2004,17 +2029,19 @@ static my_bool _ma_log_del_prefix(MARIA_HA *info, my_off_t page,
LSN lsn;
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 12], *log_pos;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
uint offset= (uint) (key_pos - buff);
uint offset= (uint) (key_pos - ma_page->buff);
uint diff_length= org_length + move_length - new_length;
uint translog_parts, extra_length;
MARIA_HA *info= ma_page->info;
my_off_t page;
DBUG_ENTER("_ma_log_del_prefix");
DBUG_PRINT("enter", ("page: %lu org_length: %u new_length: %u",
(ulong) page, org_length, new_length));
(ulong) ma_page->pos, org_length, new_length));
DBUG_ASSERT((int) diff_length > 0);
log_pos= log_data + FILEID_STORE_SIZE;
page/= info->s->block_size;
page= ma_page->pos / info->s->block_size;
page_store(log_pos, page);
log_pos+= PAGE_STORE_SIZE;
......@@ -2084,8 +2111,7 @@ static my_bool _ma_log_del_prefix(MARIA_HA *info, my_off_t page,
data deleted last. Old changed key may be part of page
*/
static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page,
const uchar *buff,
static my_bool _ma_log_key_middle(MARIA_PAGE *ma_page,
uint new_length,
uint data_added_first,
uint data_changed_first,
......@@ -2099,12 +2125,14 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page,
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 4];
uint key_offset;
uint translog_parts, extra_length;
my_off_t page;
MARIA_HA *info= ma_page->info;
DBUG_ENTER("_ma_log_key_middle");
DBUG_PRINT("enter", ("page: %lu", (ulong) page));
DBUG_PRINT("enter", ("page: %lu", (ulong) ma_page->pos));
/* new place of key after changes */
key_pos+= data_added_first;
key_offset= (uint) (key_pos - buff);
key_offset= (uint) (key_pos - ma_page->buff);
if (key_offset < new_length)
{
/* key is on page; Calculate how much of the key is there */
......@@ -2122,7 +2150,7 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page,
data_deleted_last+= move_length;
}
page/= info->s->block_size;
page= ma_page->pos / info->s->block_size;
/* First log changes to page */
log_pos= log_data + FILEID_STORE_SIZE;
......@@ -2141,7 +2169,7 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page,
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos -
log_data);
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (buff +
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (ma_page->buff +
info->s->keypage_header);
log_array[TRANSLOG_INTERNAL_PARTS + 1].length= data_changed_first;
translog_parts= 2;
......@@ -2195,18 +2223,19 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page,
data deleted last
*/
static my_bool _ma_log_middle(MARIA_HA *info, my_off_t page,
const uchar *buff,
static my_bool _ma_log_middle(MARIA_PAGE *ma_page,
uint data_added_first, uint data_changed_first,
uint data_deleted_last)
{
LSN lsn;
LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3 + 5], *log_pos;
MARIA_HA *info= ma_page->info;
my_off_t page;
DBUG_ENTER("_ma_log_middle");
DBUG_PRINT("enter", ("page: %lu", (ulong) page));
page/= info->s->block_size;
page= ma_page->page / info->s->block_size;
log_pos= log_data + FILEID_STORE_SIZE;
page_store(log_pos, page);
......
......@@ -82,10 +82,9 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name);
static int maria_sort_records(HA_CHECK *param, register MARIA_HA *info,
char *name, uint sort_key,
my_bool write_info, my_bool update_index);
static int sort_record_index(MARIA_SORT_PARAM *sort_param, MARIA_HA *info,
MARIA_KEYDEF *keyinfo,
my_off_t page, uchar *buff,uint sortkey,
File new_file, my_bool update_index);
static int sort_record_index(MARIA_SORT_PARAM *sort_param, MARIA_PAGE *page,
uint sortkey, File new_file,
my_bool update_index);
static my_bool write_log_record(HA_CHECK *param);
HA_CHECK check_param;
......@@ -1663,6 +1662,7 @@ static int maria_sort_records(HA_CHECK *param,
char llbuff[22],llbuff2[22];
MARIA_SORT_INFO sort_info;
MARIA_SORT_PARAM sort_param;
MARIA_PAGE page;
DBUG_ENTER("sort_records");
bzero((char*)&sort_info,sizeof(sort_info));
......@@ -1781,9 +1781,9 @@ static int maria_sort_records(HA_CHECK *param,
if (sort_info.new_data_file_type != COMPRESSED_RECORD)
info->state->checksum=0;
if (sort_record_index(&sort_param,info,keyinfo,
share->state.key_root[sort_key],
temp_buff, sort_key,new_file,update_index) ||
_ma_page_setup(&page, info, keyinfo, share->state.key_root[sort_key],
temp_buff);
if (sort_record_index(&sort_param, &page, sort_key,new_file,update_index) ||
maria_write_data_suffix(&sort_info,1) ||
flush_io_cache(&info->rec_cache))
goto err;
......@@ -1839,11 +1839,11 @@ static int maria_sort_records(HA_CHECK *param,
/* Sort records recursive using one index */
static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info,
MARIA_KEYDEF *keyinfo,
my_off_t page, uchar *buff, uint sort_key,
static int sort_record_index(MARIA_SORT_PARAM *sort_param,
MARIA_PAGE *ma_page, uint sort_key,
File new_file,my_bool update_index)
{
MARIA_HA *info= ma_page->info;
MARIA_SHARE *share= info->s;
uint page_flag, nod_flag,used_length;
uchar *temp_buff,*keypos,*endpos;
......@@ -1853,41 +1853,44 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info,
MARIA_SORT_INFO *sort_info= sort_param->sort_info;
HA_CHECK *param=sort_info->param;
MARIA_KEY tmp_key;
MARIA_PAGE new_page;
const MARIA_KEYDEF *keyinfo= ma_page->keyinfo;
DBUG_ENTER("sort_record_index");
page_flag= _ma_get_keypage_flag(share, buff);
nod_flag= _ma_test_if_nod(share, buff);
page_flag= ma_page->flag;
nod_flag= ma_page->node;
temp_buff=0;
tmp_key.keyinfo= keyinfo;
tmp_key.keyinfo= (MARIA_KEYDEF*) keyinfo;
tmp_key.data= lastkey;
if (nod_flag)
{
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length)))
if (!(temp_buff= (uchar*) my_alloca(tmp_key.keyinfo->block_length)))
{
_ma_check_print_error(param,"Not Enough memory");
DBUG_RETURN(-1);
}
}
used_length= _ma_get_page_used(share, buff);
keypos= buff + share->keypage_header + nod_flag;
endpos= buff + used_length;
used_length= ma_page->size;
keypos= ma_page->buff + share->keypage_header + nod_flag;
endpos= ma_page->buff + used_length;
for ( ;; )
{
_sanity(__FILE__,__LINE__);
if (nod_flag)
{
next_page= _ma_kpos(nod_flag, keypos);
if (my_pread(share->kfile.file, (uchar*)temp_buff,
(uint) keyinfo->block_length, next_page,
if (my_pread(share->kfile.file, temp_buff,
(uint) tmp_key.keyinfo->block_length, next_page,
MYF(MY_NABP+MY_WME)))
{
_ma_check_print_error(param,"Can't read keys from filepos: %s",
llstr(next_page,llbuff));
goto err;
}
if (sort_record_index(sort_param, info,keyinfo,next_page,temp_buff,
sort_key,
_ma_page_setup(&new_page, info, ma_page->keyinfo, next_page, temp_buff);
if (sort_record_index(sort_param, &new_page, sort_key,
new_file, update_index))
goto err;
}
......@@ -1917,9 +1920,9 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info,
goto err;
}
/* Clear end of block to get better compression if the table is backuped */
bzero((uchar*) buff+used_length,keyinfo->block_length-used_length);
if (my_pwrite(share->kfile.file, (uchar*)buff, (uint)keyinfo->block_length,
page,param->myf_rw))
bzero(ma_page->buff + used_length, keyinfo->block_length - used_length);
if (my_pwrite(share->kfile.file, ma_page->buff, (uint)keyinfo->block_length,
ma_page->pos, param->myf_rw))
{
_ma_check_print_error(param,"%d when updating keyblock",my_errno);
goto err;
......
......@@ -607,28 +607,20 @@ struct st_maria_handler
((uint) mi_uint2korr((x) + (share)->keypage_header - KEYPAGE_USED_SIZE))
#define _ma_store_page_used(share,x,y) \
mi_int2store((x) + (share)->keypage_header - KEYPAGE_USED_SIZE, (y))
#define _ma_get_keypage_flag(share,x) x[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]
#define _ma_test_if_nod(share,x) \
((_ma_get_keypage_flag(share,x) & KEYPAGE_FLAG_ISNOD) ? (share)->base.key_reflength : 0)
#define _ma_get_used_and_nod(share,buff,length,nod) \
{ \
(nod)= _ma_test_if_nod((share),(buff)); \
(length)= _ma_get_page_used((share),(buff)); \
}
#define _ma_get_used_and_nod_with_flag(share,flag,buff,length,nod) \
{ \
(nod)= (((flag) & KEYPAGE_FLAG_ISNOD) ? (share)->base.key_reflength : 0); \
(length)= _ma_get_page_used((share),(buff)); \
}
#define _ma_store_keynr(share, x, nr) x[(share)->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE]= (nr)
#define _ma_get_keynr(share, x) ((uchar) x[(share)->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE])
#define _ma_store_transid(buff, transid) \
transid_store((buff) + LSN_STORE_SIZE, (transid))
#define _ma_korr_transid(buff) \
transid_korr((buff) + LSN_STORE_SIZE)
#define _ma_get_keypage_flag(share,x) x[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]
#define _ma_store_keypage_flag(share,x,flag) x[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]= (flag)
#define _ma_mark_page_with_transid(share, x) x[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]|= KEYPAGE_FLAG_HAS_TRANSID
#define _ma_mark_page_with_transid(share, page) \
(page)->flag|= KEYPAGE_FLAG_HAS_TRANSID; \
(page)->buff[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]= (page)->flag;
/*
......@@ -783,6 +775,21 @@ typedef struct st_pinned_page
} MARIA_PINNED_PAGE;
/* Keeps all information about a page and related to a page */
typedef struct st_maria_page
{
MARIA_HA *info;
const MARIA_KEYDEF *keyinfo;
uchar *buff; /* Data for page */
my_off_t pos; /* Disk address to page */
uint size; /* Size of data on page */
uint node; /* 0 or share->base.key_reflength */
uint flag; /* Page flag */
uint link_offset;
} MARIA_PAGE;
/* Prototypes for intern functions */
extern int _ma_read_dynamic_record(MARIA_HA *, uchar *, MARIA_RECORD_POS);
extern int _ma_read_rnd_dynamic_record(MARIA_HA *, uchar *, MARIA_RECORD_POS,
......@@ -804,22 +811,22 @@ extern my_bool _ma_update_static_record(MARIA_HA *, MARIA_RECORD_POS,
extern my_bool _ma_delete_static_record(MARIA_HA *info, const uchar *record);
extern my_bool _ma_cmp_static_record(MARIA_HA *info, const uchar *record);
extern my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key);
extern int _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key,
extern my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key,
MARIA_RECORD_POS *root);
extern int _ma_insert(MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
uchar *key_pos, my_off_t anc_page, uchar *key_buff,
my_off_t father_page, uchar *father_buff,
MARIA_PINNED_PAGE *father_page_link,
uchar *father_key_pos, my_bool insert_last);
extern int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEY *key,
int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
MARIA_PAGE *anc_page, uchar *key_pos, uchar *key_buff,
MARIA_PAGE *father_page, uchar *father_key_pos,
my_bool insert_last);
extern my_bool _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEY *key,
MARIA_RECORD_POS *root, uint32 comp_flag);
extern int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, my_off_t split_page,
uchar *split_buff, uint org_split_length,
extern int _ma_split_page(MARIA_HA *info, MARIA_KEY *key,
MARIA_PAGE *split_page,
uint org_split_length,
uchar *inserted_key_pos, uint changed_length,
int move_length,
uchar *key_buff, my_bool insert_last_key);
extern uchar *_ma_find_half_pos(MARIA_HA *info, MARIA_KEY *key, uint nod_flag,
uchar *page, uchar ** after_key);
extern uchar *_ma_find_half_pos(MARIA_KEY *key, MARIA_PAGE *page,
uchar ** after_key);
extern int _ma_calc_static_key_length(const MARIA_KEY *key, uint nod_flag,
uchar *key_pos, uchar *org_key,
uchar *key_buff,
......@@ -847,8 +854,8 @@ extern void _ma_store_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos,
extern void _ma_store_bin_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos,
MARIA_KEY_PARAM *s_temp);
extern int _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key);
extern int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
extern my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key);
extern my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
my_off_t *root);
extern int _ma_readinfo(MARIA_HA *info, int lock_flag, int check_keybuffer);
extern int _ma_writeinfo(MARIA_HA *info, uint options);
......@@ -861,13 +868,13 @@ extern int _ma_decrement_open_count(MARIA_HA *info);
extern int _ma_check_index(MARIA_HA *info, int inx);
extern int _ma_search(MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
my_off_t pos);
extern int _ma_bin_search( const MARIA_KEY *key, uchar *page,
extern int _ma_bin_search(const MARIA_KEY *key, const MARIA_PAGE *page,
uint32 comp_flag, uchar **ret_pos, uchar *buff,
my_bool *was_last_key);
extern int _ma_seq_search(const MARIA_KEY *key, uchar *page,
extern int _ma_seq_search(const MARIA_KEY *key, const MARIA_PAGE *page,
uint comp_flag, uchar ** ret_pos, uchar *buff,
my_bool *was_last_key);
extern int _ma_prefix_search(const MARIA_KEY *key, uchar *page,
extern int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *page,
uint32 comp_flag, uchar ** ret_pos, uchar *buff,
my_bool *was_last_key);
extern my_off_t _ma_kpos(uint nod_flag, const uchar *after_key);
......@@ -889,14 +896,12 @@ extern uint _ma_get_binary_pack_key(MARIA_KEY *key, uint page_flag,
uint nod_flag, uchar **page_pos);
uchar *_ma_skip_binary_pack_key(MARIA_KEY *key, uint page_flag,
uint nod_flag, uchar *page);
extern uchar *_ma_get_last_key(MARIA_KEY *key, uchar *keypos, uchar *endpos);
extern uchar *_ma_get_key(MARIA_KEY *key, uchar *page, uchar *keypos);
extern uchar *_ma_get_last_key(MARIA_KEY *key, MARIA_PAGE *page,
uchar *endpos);
extern uchar *_ma_get_key(MARIA_KEY *key, MARIA_PAGE *page, uchar *keypos);
extern uint _ma_keylength(MARIA_KEYDEF *keyinfo, const uchar *key);
extern uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, const uchar *key,
HA_KEYSEG *end);
extern uchar *_qq_move_key(MARIA_KEYDEF *keyinfo, uchar *to,
const uchar *from);
extern int _ma_search_next(MARIA_HA *info, MARIA_KEY *key,
uint32 nextflag, my_off_t pos);
extern int _ma_search_first(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
......@@ -909,21 +914,20 @@ extern my_off_t _ma_transparent_recpos(MARIA_SHARE *share, my_off_t pos);
extern my_off_t _ma_transaction_keypos_to_recpos(MARIA_SHARE *, my_off_t pos);
extern my_off_t _ma_transaction_recpos_to_keypos(MARIA_SHARE *, my_off_t pos);
extern uchar *_ma_fetch_keypage(MARIA_HA *info,
extern void _ma_page_setup(MARIA_PAGE *page, MARIA_HA *info,
const MARIA_KEYDEF *keyinfo, my_off_t pos,
uchar *buff);
extern my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info,
const MARIA_KEYDEF *keyinfo,
my_off_t page, enum pagecache_page_lock lock,
int level, uchar *buff, int return_buffer,
MARIA_PINNED_PAGE **page_link);
extern int _ma_write_keypage(MARIA_HA *info,
const MARIA_KEYDEF *keyinfo,
my_off_t page, enum pagecache_page_lock lock,
int level, uchar *buff);
my_off_t pos, enum pagecache_page_lock lock,
int level, uchar *buff,
my_bool return_buffer);
extern my_bool _ma_write_keypage(MARIA_PAGE *page,
enum pagecache_page_lock lock, int level);
extern int _ma_dispose(MARIA_HA *info, my_off_t pos, my_bool page_not_read);
extern my_off_t _ma_new(register MARIA_HA *info, int level,
MARIA_PINNED_PAGE **page_link);
extern my_bool _ma_compact_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t page_pos, uchar *page,
TrID min_read_from);
extern my_bool _ma_compact_keypage(MARIA_PAGE *page, TrID min_read_from);
extern uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid);
extern ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from);
#define transid_packed_length(data) \
......@@ -931,6 +935,15 @@ extern ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from);
(uint) (257 - (uchar) (data)[0]))
#define key_has_transid(key) (*(key) & 1)
#define page_mark_changed(info, page) \
dynamic_element(&(info)->pinned_pages, (page)->link_offset, \
MARIA_PINNED_PAGE*)->changed= 1;
#define page_store_size(share, page) \
_ma_store_page_used((share), (page)->buff, (page)->size);
#define page_store_info(share, page) \
_ma_store_keypage_flag((share), (page)->buff, (page)->flag); \
_ma_store_page_used((share), (page)->buff, (page)->size);
extern MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,
uchar *key, const uchar *record,
MARIA_RECORD_POS filepos, ulonglong trid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment