diff options
Diffstat (limited to 'storage/maria/ma_write.c')
-rw-r--r-- | storage/maria/ma_write.c | 333 |
1 files changed, 82 insertions, 251 deletions
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 0f980bbb1cc..5348e4c6ac2 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -47,9 +47,6 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t *root, uint comp_flag); static my_bool _ma_log_new(MARIA_HA *info, my_off_t page, uchar *buff, uint page_length, uint key_nr, my_bool root_page); -static my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff, - uchar *end_buff, uchar *key_pos, - uint changed_length, int move_length); static my_bool _ma_log_change(MARIA_HA *info, my_off_t page, uchar *buff, uchar *key_pos, uint length); static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, @@ -58,7 +55,7 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, uint key_length, int move_length, enum en_key_op prefix_or_suffix, uchar *data, uint data_length, - uint change_length); + uint changed_length); static my_bool _ma_log_del_prefix(MARIA_HA *info, my_off_t page, uchar *buff, uint org_length, uint new_length, uchar *key_pos, uint key_length, @@ -70,12 +67,6 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page, uchar *buff, uint data_deleted_last, uchar *key_pos, uint key_length, int move_length); -static my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, - uchar *buff, uint changed_length, - int move_length); -static my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, - uchar *buff, uint org_length, - uint new_length); /* @brief Default handler for returing position to new row @@ -388,10 +379,17 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, LSN lsn= LSN_IMPOSSIBLE; int error; my_off_t new_root= *root; + uchar key_buff[HA_MAX_KEY_BUFF]; #ifdef NOT_YET DBUG_ENTER("_ma_ck_write_btree_with_log"); #endif + if (info->s->now_transactional) + { + /* Save original value as the key may change */ + memcpy(key_buff, key, key_length + info->s->rec_reflength); + } + error= _ma_ck_real_write_btree(info, keyinfo, key, key_length, &new_root, comp_flag); if (!error && info->s->now_transactional) @@ -404,9 +402,10 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, lsn_store(log_data, info->trn->undo_lsn); key_nr_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, keyinfo->key_nr); + key_length+= info->s->rec_reflength; log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) key; + log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) key_buff; log_array[TRANSLOG_INTERNAL_PARTS + 1].length= key_length; msg.root= root; @@ -460,23 +459,6 @@ int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } /* _ma_ck_real_write_btree */ -/* - @brief write hook for undo key insert -*/ - -my_bool write_hook_for_undo_key(enum translog_record_type type, - TRN *trn, MARIA_HA *tbl_info, - LSN *lsn, void *hook_arg) -{ - struct st_msg_to_write_hook_for_undo_key *msg= - (struct st_msg_to_write_hook_for_undo_key *) hook_arg; - - *msg->root= msg->value; - _ma_fast_unlock_key_del(tbl_info); - return write_hook_for_undo(type, trn, tbl_info, lsn, 0); -} - - /** @brief Make a new root with key as only pointer @@ -675,6 +657,9 @@ err: Insert new key at right of key_pos. Note that caller must save anc_buff + This function writes log records for all changed pages + (Including anc_buff and father page) + RETURN < 0 Error. 0 OK @@ -689,7 +674,7 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, my_bool insert_last) { uint a_length, nod_flag, org_anc_length; - int t_length, res; + int t_length; uchar *endpos, *prev_key; MARIA_KEY_PARAM s_temp; DBUG_ENTER("_ma_insert"); @@ -804,8 +789,8 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else { if (info->s->now_transactional && - _ma_log_add(info, anc_page, anc_buff, endpos, key_pos, - s_temp.changed_length, t_length)) + _ma_log_add(info, anc_page, anc_buff, (uint) (endpos - anc_buff), + key_pos, s_temp.changed_length, t_length, 0)) DBUG_RETURN(-1); } DBUG_RETURN(0); /* There is room on page */ @@ -817,44 +802,51 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, father_buff && !insert_last) { s_temp.key_pos= key_pos; - s_temp.move_length= t_length; father_page_link->changed= 1; DBUG_RETURN(_ma_balance_page(info, keyinfo, key, anc_buff, anc_page, father_page, father_buff, father_key_pos, &s_temp)); } - - res= _ma_split_page(info,keyinfo,key,anc_buff,key_buff, insert_last); - if (res < 0) - DBUG_RETURN(res); /* Error */ - - if (info->s->now_transactional) - { - if (_ma_log_split(info, anc_page, anc_buff, org_anc_length, - _ma_get_page_used(info, anc_buff), - key_pos, - s_temp.changed_length, - t_length, KEY_OP_NONE, (uchar*) 0, 0, 0)) - res= -1; - } - DBUG_RETURN(res); + DBUG_RETURN(_ma_split_page(info, keyinfo, key, anc_page, + anc_buff, org_anc_length, + key_pos, s_temp.changed_length, t_length, + key_buff, insert_last)); } /* _ma_insert */ /** @brief split a full page in two and assign emerging item to key - RETURN - @retval 0 ok + @fn _ma_split_page() + 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 + 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 + key_buff Key buffer to use for temporary storage of key + insert_last_key If we are insert key on rightmost key page + + @note + split_buff is not stored on disk (caller has to do this) + + @return + @retval 2 ok (Middle key up from _ma_insert()) @retval -1 error */ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uchar *buff, uchar *key_buff, - my_bool insert_last_key) + uchar *key, my_off_t split_page, uchar *split_buff, + uint org_split_length, + uchar *inserted_key_pos, uint changed_length, + int move_length, + uchar *key_buff, my_bool insert_last_key) { uint length,a_length,key_ref_length,t_length,nod_flag,key_length; - uint page_length; + uint page_length, split_length; uchar *key_pos,*pos, *after_key, *new_buff; my_off_t new_pos; MARIA_KEY_PARAM s_temp; @@ -863,25 +855,26 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_ENTER("maria_split_page"); LINT_INIT(after_key); - DBUG_DUMP("buff", buff, _ma_get_page_used(info, buff)); + DBUG_DUMP("buff", split_buff, _ma_get_page_used(info, split_buff)); info->page_changed=1; /* Info->buff is used */ info->keyread_buff_used=1; new_buff= info->buff; - nod_flag=_ma_test_if_nod(info, buff); + nod_flag=_ma_test_if_nod(info, split_buff); key_ref_length= info->s->keypage_header + nod_flag; if (insert_last_key) - key_pos= _ma_find_last_pos(info, keyinfo, buff, key_buff, &key_length, + key_pos= _ma_find_last_pos(info, keyinfo, split_buff, + key_buff, &key_length, &after_key); else - key_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, key_buff, + key_pos= _ma_find_half_pos(info, nod_flag, keyinfo, split_buff, key_buff, &key_length, &after_key); if (!key_pos) DBUG_RETURN(-1); - length=(uint) (key_pos-buff); - a_length= _ma_get_page_used(info, buff); - _ma_store_page_used(info, buff, length, nod_flag); + split_length= (uint) (key_pos - split_buff); + a_length= _ma_get_page_used(info, split_buff); + _ma_store_page_used(info, split_buff, split_length, nod_flag); key_pos=after_key; if (nod_flag) @@ -898,14 +891,14 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_RETURN(-1); _ma_kpointer(info, _ma_move_key(keyinfo,key,key_buff),new_pos); - /* Store new page */ + /* Store new page */ if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff)) DBUG_RETURN(-1); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0, (uchar*) 0, (uchar*) 0, key_buff, &s_temp); - length=(uint) ((buff+a_length)-key_pos); + length=(uint) ((split_buff + a_length) - key_pos); memcpy((uchar*) new_buff+key_ref_length+t_length,(uchar*) key_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,new_buff+key_ref_length,&s_temp); @@ -916,8 +909,8 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* Copy key number */ new_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]= - buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - - KEYPAGE_FLAG_SIZE]; + split_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - + KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]; res= 2; /* Middle key up */ if (info->s->now_transactional && @@ -928,6 +921,15 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (_ma_write_keypage(info, keyinfo, new_pos, page_link->write_lock, DFLT_INIT_HITS, new_buff)) res= -1; + + /* Save changes to split pages */ + if (info->s->now_transactional && + _ma_log_split(info, split_page, split_buff, org_split_length, + split_length, + inserted_key_pos, changed_length, move_length, + KEY_OP_NONE, (uchar*) 0, 0, 0)) + res= -1; + DBUG_DUMP("key",(uchar*) key, _ma_keylength(keyinfo,key)); DBUG_RETURN(res); } /* _ma_split_page */ @@ -1046,10 +1048,11 @@ static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo, @notes Father_buff will always be changed + Caller must handle saving of curr_buff @return - @retval 0 Balance was done - @retval 1 Middle key up + @retval 0 Balance was done (father buff is saved) + @retval 1 Middle key up (father buff is not saved) @retval -1 Error */ @@ -1360,7 +1363,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, - left_length, new_left_length, + left_length - s_temp->move_length, new_left_length, s_temp->key_pos, s_temp->changed_length, s_temp->move_length, KEY_OP_NONE, (uchar*) 0, 0, 0)) @@ -1370,7 +1373,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, This contains the last 'extra_buff' from 'buff' */ if (_ma_log_prefix(info, next_page, extra_buff, - 0, (int) (extra_length - right_length))) + 0, (int) (extra_buff_length - right_length))) goto err; /* @@ -1654,68 +1657,6 @@ static my_bool _ma_log_new(MARIA_HA *info, my_off_t page, uchar *buff, /** @brief - Log that a key was added to the page -*/ - -static my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff, - uchar *end_buff, uchar *key_pos, - uint changed_length, int move_length) -{ - LSN lsn; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3 + 3 + 3], *log_pos; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; - DBUG_ENTER("_ma_log_add"); - DBUG_PRINT("enter", ("page: %lu", (ulong) page)); - - DBUG_ASSERT(info->s->now_transactional); - - /* - Write REDO entry that contains the logical operations we need - to do the page - */ - log_pos= log_data + FILEID_STORE_SIZE; - page/= info->s->block_size; - page_store(log_pos, page); - log_pos+= PAGE_STORE_SIZE; - - if (key_pos == end_buff) - log_pos[0]= KEY_OP_ADD_SUFFIX; - else - { - uint offset= (uint) (key_pos - buff); - log_pos[0]= KEY_OP_OFFSET; - int2store(log_pos+1, offset); - log_pos+= 3; - if (move_length) - { - log_pos[0]= KEY_OP_SHIFT; - int2store(log_pos+1, move_length); - log_pos+= 3; - } - log_pos[0]= KEY_OP_CHANGE; - } - int2store(log_pos+1, changed_length); - log_pos+= 3; - - 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= key_pos; - log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; - - if (translog_write_record(&lsn, LOGREC_REDO_INDEX, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + - 0].length + changed_length, - TRANSLOG_INTERNAL_PARTS + 2, log_array, - log_data, NULL)) - DBUG_RETURN(-1); - DBUG_RETURN(0); -} - - -/** - @brief Log when some part of the key page changes */ @@ -1755,12 +1696,14 @@ static my_bool _ma_log_change(MARIA_HA *info, my_off_t page, uchar *buff, /** - @brief - Write log entry for page that has got a key added to the page under - one and only one of the following senarios: - - Page is shortened from end - - Data is added to end of page - - Data added at front of page + @brief Write log entry for page splitting + + @note + Write log entry for page that has got a key added to the page under + one and only one of the following senarios: + - Page is shortened from end + - Data is added to end of page + - Data added at front of page @param prefix_or_suffix KEY_OP_NONE Ignored KEY_OP_ADD_PREFIX Add data to start of page @@ -1773,7 +1716,7 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, uchar *key_pos, uint key_length, int move_length, enum en_key_op prefix_or_suffix, uchar *data, uint data_length, - uint change_length) + uint changed_length) { LSN lsn; uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3+3+3+3+3+2]; @@ -1790,7 +1733,7 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, page_store(log_pos, page); log_pos+= PAGE_STORE_SIZE; - if (new_length <= offset) + if (new_length <= offset || !key_pos) { /* Page was split before inserted key. Write redo entry where @@ -1859,9 +1802,9 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, log_pos+= 3; if (prefix_or_suffix == KEY_OP_ADD_PREFIX) { - int2store(log_pos+1, change_length); + int2store(log_pos+1, changed_length); log_pos+= 2; - data_length= change_length; + data_length= changed_length; } log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].str= (char*) data; log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].length= data_length; @@ -2089,118 +2032,6 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page, uchar *buff, } -/** - @brief - Write log entry for page that has got data added or deleted at start of page -*/ - -static my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, - uchar *buff, uint changed_length, - int move_length) -{ - uint translog_parts; - LSN lsn; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7], *log_pos; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; - DBUG_ENTER("_ma_log_prefix"); - DBUG_PRINT("enter", ("page: %lu change_length: %u move_length: %d", - (ulong) page, changed_length, move_length)); - - page/= info->s->block_size; - log_pos= log_data + FILEID_STORE_SIZE; - page_store(log_pos, page); - log_pos+= PAGE_STORE_SIZE; - - if (move_length < 0) - { - /* Delete prefix */ - DBUG_ASSERT(changed_length == 0); - log_pos[0]= KEY_OP_DEL_PREFIX; - int2store(log_pos+1, -move_length); - log_pos+= 3; - translog_parts= 1; - } - else - { - /* Add prefix */ - DBUG_ASSERT(changed_length >0 && (int) changed_length >= move_length); - log_pos[0]= KEY_OP_ADD_PREFIX; - int2store(log_pos+1, move_length); - int2store(log_pos+3, changed_length); - log_pos+= 5; - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= ((char*) buff + - info->s->keypage_header); - log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; - translog_parts= 2; - } - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - - log_data); - - DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + - 0].length + changed_length, - TRANSLOG_INTERNAL_PARTS + translog_parts, - log_array, log_data, NULL)); -} - - -/** - @brief - Write log entry for page that has got data added or deleted at end of page -*/ - -static my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, - uchar *buff, uint org_length, - uint new_length) -{ - LSN lsn; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10], *log_pos; - int diff; - uint translog_parts, extra_length; - DBUG_ENTER("_ma_log_suffix"); - DBUG_PRINT("enter", ("page: %lu org_length: %u new_length: %u", - (ulong) page, org_length, new_length)); - - page/= info->s->block_size; - - log_pos= log_data + FILEID_STORE_SIZE; - page_store(log_pos, page); - log_pos+= PAGE_STORE_SIZE; - - if ((diff= (int) (new_length - org_length)) < 0) - { - log_pos[0]= KEY_OP_DEL_SUFFIX; - int2store(log_pos+1, -diff); - log_pos+= 3; - translog_parts= 1; - extra_length= 0; - } - else - { - log_pos[0]= KEY_OP_ADD_SUFFIX; - int2store(log_pos+1, diff); - log_pos+= 3; - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) buff + org_length; - log_array[TRANSLOG_INTERNAL_PARTS + 1].length= (uint) diff; - translog_parts= 2; - extra_length= (uint) diff; - } - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - - log_data); - - DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + - 0].length + extra_length, - TRANSLOG_INTERNAL_PARTS + translog_parts, - log_array, log_data, NULL)); -} - - #ifdef NOT_NEEDED /** |