- 论坛徽章:
- 0
|
- /*
- * @ih, item header of inserted item, this is on little endian
- * @body, body of inserted item or bytes to paste
- * @flag, i - insert, d - delete, c - cut, p - paste, see comment to do_balance
- * @insert_key, in our processing of one level,
- * we sometimes determine what must be inserted into the next higher level.
- * This insertion consists of a key or two keys and
- * their corresponding pointers.
- * @insert_ptr, inserted node-ptrs for the next level
- */
- static void balance_leaf_shift_left(struct tree_balance *tb,
- struct item_head *ih,
- const char *body,
- int flag,
- struct item_head *insert_key,
- struct buffer_head **insert_ptr)
- {
- struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
- /* index of the affected item */
- int item_pos = PATH_LAST_POSITION(tb->tb_path);
-
- struct buffer_info bi;
- int ret_val;
- int pos_in_item;
- int zeros_num;
-
- if (!(tb->lnum[0] > 0)) /* left shift not needed */
- return;
-
- zeros_num = 0;
- if (flag == M_INSERT && body == 0)
- zeros_num = ih_item_len(ih);
- pos_in_item = tb->tb_path->pos_in_item;
- /* for indirect item pos_in_item is measured in unformatted node
- * pointers. Recalculate to bytes
- */
- if (flag != M_INSERT &&
- is_indirect_le_ih(B_N_PITEM_HEAD(tbS0, item_pos)))
- pos_in_item *= UNFM_P_SIZE;
- /*
- * lets compare the affted item with lnum[h] computed in fix_node.
- *
- * left shift, defed by Hans, as to
- * move lnum[h] items starting at I-0 in S to L
- */
- if (!(item_pos < tb->lnum[0])) {
- /* new item doesn't fall into L[0] */
- leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
- return;
- }
- n = B_NR_ITEMS(tb->L[0]);
- if (flag == M_INSERT) {
- if (item_pos == tb->lnum[0] -1 && tb->lbytes != -1) {
- /* part of new item falls into L[0] */
- int new_item_len;
- int version;
-
- /* shift lnum[0]-1 items entirely */
- ret_val = leaf_shift_left(tb, tb->lnum[0] -1, -1);
-
- /* Calculate item length to insert to S[0] */
- new_item_len = ih_item_len(ih) - tb->lbytes;
-
- /* Calculate and check item length to insert to L[0] */
- put_ih_item_len(ih, tb->lbytes /*ih_item_len(ih) - new_item_len*/);
- RFALSE(tb->lbytes <= 0,
- "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d",
- ih_item_len(ih));
- /* Insert new item into L[0] */
- bi.tb = tb;
- bi.bi_bh = tb->L[0];
- bi.bi_parent = tb->FL[0];
- bi.bi_position = get_left_neighbor_position(tb, 0);
-
- leaf_insert_into_buf(&bi, n + item_pos - ret_val,
- ih, body,
- zeros_num > ih_item_len(ih) ?
- ih_item_len(ih) : zeros_num);
-
- version = ih_version(ih);
- /* Calculate key component,
- * item length and body to insert into S[0]
- */
- set_le_ih_k_offset(ih,
- le_ih_k_offset(ih) +
- (tb->lbytes << (is_indirect_le_ih(ih) ?
- tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0)));
- put_ih_item_len(ih, new_item_len);
-
- if (tb->lbytes > zeros_num) {
- body += (tb->lbytes - zeros_num);
- zeros_num = 0;
- } else
- zeros_num -= tb->lbytes;
- RFALSE(ih_item_len(ih) <= 0,
- "PAP-12085: there is nothing to insert into S[0]: ih_item_len=%d",
- ih_item_len(ih));
- } else {
- /* new item in whole falls into L[0] */
-
- /* Shift lnum[0]-1 items to L[0] */
- ret_val = leaf_shift_left(tb, tb->lnum[0] -1, tb->lbytes);
-
- /* Insert new item into L[0] */
- bi.tb = tb;
- bi.bi_bh = tb->L[0];
- bi.bi_parent = tb->FL[0];
- bi.bi_position = get_left_neighbor_position(tb, 0);
-
- leaf_insert_into_buf(&bi, n + item_pos - ret_val,
- ih, body, zeros_num);
- tb->insert_size[0] = 0;
- zeros_num = 0;
- }
- }
- else if (flag == M_PASTE) {
- if (!(item_pos == tb->lnum[0] -1 && tb->lbytes != -1)) {
- /* appended item will be in L[0] in whole */
- struct item_head *pasted;
- if (!item_pos &&
- op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) {
- /* if we paste into first item of S[0], and
- * it is left mergable,
- * then increment pos_in_item by the size of
- * the last item in L[0]
- */
- pasted = B_N_PITEM_HEAD(tb->L[0], n -1);
-
- if (is_direntry_le_ih(pasted))
- pos_in_item += ih_entry_count(pasted);
- else
- pos_in_item += ih_item_len(pasted);
- }
- /* Shift lnum[0] in whole */
- ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
-
- /* Append to body of item in L[0] */
- bi.tb = tb;
- bi.bi_bh = tb->L[0];
- bi.bi_parent = tb->FL[0];
- bi.bi_position = get_left_neighbor_position(tb, 0);
-
- leaf_paste_in_buffer(&bi, n + item_pos - ret_val,
- pos_in_item, tb->insert_size[0],
- body, zeros_num);
-
- /* if appended item is directory, paste entry */
- pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val);
- if (is_direntry_le_ih(pasted))
- leaf_paste_entries(bi.bi_bh, n + item_pos - ret_val,
- pos_in_item, 1,
- (struct reiserfs_de_head *)body,
- body + DEH_SIZE,
- tb->insert_size[0]);
- /* if appended item is indirect item,
- * put unformatted node into un list
- */
- if (is_indirect_le_ih(pasted))
- set_ih_free_space(pasted, 0);
-
- tb->insert_size[0] = 0;
- zeros_num = 0;
- return;
- }
- /* we must shift the part of the appended item */
- if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) {
- /* case of directory item */
- RFALSE(zeros_num,
- "PAP-12090: invalid parameter in case of a directory");
-
- if (tb->lbytes > pos_in_item) {
- /* new directory entry falls into L[0] */
- struct item_head *pasted;
- int l_pos_in_item = pos_in_item;
-
- /* Shift lnum[0] items in whole.
- * Shift lbytes - 1 entries from given directory item
- */
- ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes -1);
- if (ret_val && !item_pos) {
- pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) -1);
- l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes -1);
- }
- /* Append given directory entry to directory item */
- bi.tb = tb;
- bi.bi_bh = tb->L[0];
- bi.bi_parent = tb->FL[0];
- bi.bi_position = get_left_neighbor_position(tb, 0);
-
- leaf_paste_in_buffer(&bi, n + item_pos - ret_val,
- l_pos_in_item,
- tb->insert_size[0],
- body, zeros_num);
-
- /* previous string prepared space for pasting new entry,
- * following string pastes this entry */
- /* when we have merge directory item,
- * pos_in_item has been changed too */
- /* paste new directory entry. 1 is entry number */
- leaf_paste_entries(bi.bi_bh, n + item_pos - ret_val,
- l_pos_in_item, 1,
- (struct reiserfs_de_head *) body,
- body + DEH_SIZE,
- tb->insert_size[0]);
- tb->insert_size[0] = 0;
- } else {
- /* new directory item doesn't fall into L[0] */
- /* Shift lnum[0]-1 items in whole.
- * Shift lbytes directory entries from directory item number lnum[0] */
- leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
- }
-
- /* Calculate new position to append in item body */
- pos_in_item -= tb->lbytes;
-
- } else { /* regular object */
- RFALSE(tb->lbytes <= 0,
- "PAP-12095: there is nothing to shift to L[0]. lbytes=%d",
- tb->lbytes);
-
- RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),
- "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d",
- ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)), pos_in_item);
-
- if (tb->lbytes >= pos_in_item) {
- /* appended item will be in L[0] in whole */
- /* this bytes number must be appended to
- * the last item of L[h] */
- int l_n = tb->lbytes - pos_in_item;
-
- /* Calculate new insert_size[0] */
- tb->insert_size[0] -= l_n;
- RFALSE(tb->insert_size[0] <= 0,
- "PAP-12105: there is nothing to paste into L[0]. insert_size=%d",
- tb->insert_size[0]);
-
- ret_val = leaf_shift_left(tb, tb->lnum[0],
- ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)));
- /* Append to body of item in L[0] */
- bi.tb = tb;
- bi.bi_bh = tb->L[0];
- bi.bi_parent = tb->FL[0];
- bi.bi_position = get_left_neighbor_position(tb, 0);
-
- leaf_paste_in_buffer(&bi, n + item_pos - ret_val,
- ih_item_len(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)),
- l_n, body, zeros_num > l_n ? l_n : zeros_num);
-
- /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */
- {
- int version;
- int temp_l = l_n;
-
- RFALSE(ih_item_len(B_N_PITEM_HEAD(tbS0, 0)),
- "PAP-12106: item length must be 0");
- RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0),
- B_N_PKEY(tb->L[0], n + item_pos - ret_val)),
- "PAP-12107: items must be of the same file");
-
- if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)))
- temp_l = l_n << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT);
-
- /* update key of first item in S0 */
- version = ih_version(B_N_PITEM_HEAD(tbS0, 0));
- set_le_key_k_offset(version, B_N_PKEY(tbS0, 0),
- le_key_k_offset(version, B_N_PKEY(tbS0, 0)) + temp_l);
- /* update left delimiting key */
- set_le_key_k_offset(version,
- B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]),
- le_key_k_offset(version,
- B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l);
- }
- /* Calculate new body, position in item and insert_size[0] */
- if (l_n > zeros_num) {
- body += (l_n - zeros_num);
- zeros_num = 0;
- } else
- zeros_num -= l_n;
- pos_in_item = 0;
-
- RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0),
- B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1))
- || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)
- || !op_is_left_mergeable(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), tbS0->b_size),
- "PAP-12120: item must be merge-able with left neighboring item");
-
- } else { /* only part of the appended item will be in L[0] */
- /* Calculate position in item for append in S[0] */
- pos_in_item -= tb->lbytes;
- RFALSE(pos_in_item <= 0,
- "PAP-12125: no place for paste. pos_in_item=%d",
- pos_in_item);
-
- /* Shift lnum[0] items in whole.
- * Shift lbytes byte from item number lnum[0] */
- leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
- }
- }
- } else {
- reiserfs_panic(tb->tb_sb,
- "PAP-12130: balance_leaf: lnum > 0: unexpectable mode: %s(%d)",
- (flag == M_DELETE) ? "DELETE" :
- ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
- }
- }
复制代码 |
|