bins_del.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/hfs/bins_del.c
  3.  *
  4.  * Copyright (C) 1995-1997  Paul H. Hargrove
  5.  * This file may be distributed under the terms of the GNU General Public License.
  6.  *
  7.  * This file contains the code common to inserting and deleting records
  8.  * in a B-tree.
  9.  *
  10.  * "XXX" in a comment is a note to myself to consider changing something.
  11.  *
  12.  * In function preconditions the term "valid" applied to a pointer to
  13.  * a structure means that the pointer is non-NULL and the structure it
  14.  * points to has all fields initialized to consistent values.
  15.  */
  16. #include "hfs_btree.h"
  17. /*================ File-local functions ================*/
  18. /*
  19.  * hfs_bnode_update_key()
  20.  *
  21.  * Description:
  22.  *   Updates the key for a bnode in its parent.
  23.  *   The key change is propagated up the tree as necessary.
  24.  * Input Variable(s):
  25.  *   struct hfs_brec *brec: the search path to update keys in
  26.  *   struct hfs_belem *belem: the search path element with the changed key
  27.  *   struct hfs_bnode *bnode: the bnode with the changed key
  28.  *   int offset: the "distance" from 'belem->bn' to 'bnode':
  29.  *    0 if the change is in 'belem->bn',
  30.  *    1 if the change is in its right sibling, etc.
  31.  * Output Variable(s):
  32.  *   NONE
  33.  * Returns:
  34.  *   void
  35.  * Preconditions:
  36.  *   'brec' points to a valid (struct hfs_brec)
  37.  *   'belem' points to a valid (struct hfs_belem) in 'brec'.
  38.  *   'bnode' points to a valid (struct hfs_bnode) which is non-empty
  39.  *    and is 'belem->bn' or one of its siblings.
  40.  *   'offset' is as described above.
  41.  * Postconditions:
  42.  *   The key change is propagated up the tree as necessary.
  43.  */
  44. void hfs_bnode_update_key(struct hfs_brec *brec, struct hfs_belem *belem,
  45.   struct hfs_bnode *bnode, int offset)
  46. {
  47. int record = (--belem)->record + offset;
  48. void *key = bnode_datastart(bnode) + 1;
  49. int keysize = brec->tree->bthKeyLen;
  50. struct hfs_belem *limit;
  51.    memcpy(1+bnode_key(belem->bnr.bn, record), key, keysize);
  52. /* don't trash the header */
  53. if (brec->top > &brec->elem[1]) {
  54. limit = brec->top;
  55. } else {
  56. limit = &brec->elem[1];
  57. }
  58. while ((belem > limit) && (record == 1)) {
  59. record = (--belem)->record;
  60. memcpy(1+belem_key(belem), key, keysize);
  61. }
  62. }
  63. /*
  64.  * hfs_bnode_shift_right()
  65.  *
  66.  * Description:
  67.  *   Shifts some records from a node to its right neighbor.
  68.  * Input Variable(s):
  69.  *   struct hfs_bnode* left: the node to shift records from
  70.  *   struct hfs_bnode* right: the node to shift records to
  71.  *   hfs_u16 first: the number of the first record in 'left' to move to 'right'
  72.  * Output Variable(s):
  73.  *   NONE
  74.  * Returns:
  75.  *   void
  76.  * Preconditions:
  77.  *   'left' and 'right' point to valid (struct hfs_bnode)s.
  78.  *   'left' contains at least 'first' records.
  79.  *   'right' has enough free space to hold the records to be moved from 'left'
  80.  * Postconditions:
  81.  *   The record numbered 'first' and all records after it in 'left' are
  82.  *   placed at the beginning of 'right'.
  83.  *   The key corresponding to 'right' in its parent is NOT updated.
  84.  */
  85. void hfs_bnode_shift_right(struct hfs_bnode *left, struct hfs_bnode *right,
  86.    int first)
  87. {
  88. int i, adjust, nrecs;
  89. unsigned size;
  90. hfs_u16 *to, *from;
  91. if ((first <= 0) || (first > left->ndNRecs)) {
  92. hfs_warn("bad argument to shift_right: first=%d, nrecs=%dn",
  93.        first, left->ndNRecs);
  94. return;
  95. }
  96. /* initialize variables */
  97. nrecs = left->ndNRecs + 1 - first;
  98. size = bnode_end(left) - bnode_offset(left, first);
  99. /* move (possibly empty) contents of right node forward */
  100. memmove(bnode_datastart(right) + size,
  101. bnode_datastart(right), 
  102. bnode_end(right) - sizeof(struct NodeDescriptor));
  103. /* copy in new records */
  104. memcpy(bnode_datastart(right), bnode_key(left,first), size);
  105. /* fix up offsets in right node */
  106. i = right->ndNRecs + 1;
  107. from = RECTBL(right, i);
  108. to = from - nrecs;
  109. while (i--) {
  110. hfs_put_hs(hfs_get_hs(from++) + size, to++);
  111. }
  112. adjust = sizeof(struct NodeDescriptor) - bnode_offset(left, first);
  113. i = nrecs-1;
  114. from = RECTBL(left, first+i);
  115. while (i--) {
  116. hfs_put_hs(hfs_get_hs(from++) + adjust, to++);
  117. }
  118. /* fix record counts */
  119. left->ndNRecs -= nrecs;
  120. right->ndNRecs += nrecs;
  121. }
  122. /*
  123.  * hfs_bnode_shift_left()
  124.  *
  125.  * Description:
  126.  *   Shifts some records from a node to its left neighbor.
  127.  * Input Variable(s):
  128.  *   struct hfs_bnode* left: the node to shift records to
  129.  *   struct hfs_bnode* right: the node to shift records from
  130.  *   hfs_u16 last: the number of the last record in 'right' to move to 'left'
  131.  * Output Variable(s):
  132.  *   NONE
  133.  * Returns:
  134.  *   void
  135.  * Preconditions:
  136.  *   'left' and 'right' point to valid (struct hfs_bnode)s.
  137.  *   'right' contains at least 'last' records.
  138.  *   'left' has enough free space to hold the records to be moved from 'right'
  139.  * Postconditions:
  140.  *   The record numbered 'last' and all records before it in 'right' are
  141.  *   placed at the end of 'left'.
  142.  *   The key corresponding to 'right' in its parent is NOT updated.
  143.  */
  144. void hfs_bnode_shift_left(struct hfs_bnode *left, struct hfs_bnode *right,
  145.   int last)
  146. {
  147. int i, adjust, nrecs;
  148. unsigned size;
  149. hfs_u16 *to, *from;
  150. if ((last <= 0) || (last > right->ndNRecs)) {
  151. hfs_warn("bad argument to shift_left: last=%d, nrecs=%dn",
  152.        last, right->ndNRecs);
  153. return;
  154. }
  155. /* initialize variables */
  156. size = bnode_offset(right, last + 1) - sizeof(struct NodeDescriptor);
  157. /* copy records to left node */
  158. memcpy(bnode_dataend(left), bnode_datastart(right), size);
  159. /* move (possibly empty) remainder of right node backward */
  160. memmove(bnode_datastart(right), bnode_datastart(right) + size, 
  161. bnode_end(right) - bnode_offset(right, last + 1));
  162. /* fix up offsets */
  163. nrecs = left->ndNRecs;
  164. i = last;
  165. from = RECTBL(right, 2);
  166. to = RECTBL(left, nrecs + 2);
  167. adjust = bnode_offset(left, nrecs + 1) - sizeof(struct NodeDescriptor);
  168. while (i--) {
  169. hfs_put_hs(hfs_get_hs(from--) + adjust, to--);
  170. }
  171. i = right->ndNRecs + 1 - last;
  172. ++from;
  173. to = RECTBL(right, 1);
  174. while (i--) {
  175. hfs_put_hs(hfs_get_hs(from--) - size, to--);
  176. }
  177. /* fix record counts */
  178. left->ndNRecs += last;
  179. right->ndNRecs -= last;
  180. }
  181. /*
  182.  * hfs_bnode_in_brec()
  183.  *
  184.  * Description:
  185.  *   Determines whethet a given bnode is part of a given brec.
  186.  *   This is used to avoid deadlock in the case of a corrupted b-tree.
  187.  * Input Variable(s):
  188.  *   hfs_u32 node: the number of the node to check for.
  189.  *   struct hfs_brec* brec: the brec to check in.
  190.  * Output Variable(s):
  191.  *   NONE
  192.  * Returns:
  193.  *   int: 1 it found, 0 if not
  194.  * Preconditions:
  195.  *   'brec' points to a valid struct hfs_brec.
  196.  * Postconditions:
  197.  *   'brec' is unchanged.
  198.  */
  199. int hfs_bnode_in_brec(hfs_u32 node, const struct hfs_brec *brec)
  200. {
  201. const struct hfs_belem *belem = brec->bottom;
  202. while (belem && (belem >= brec->top)) {
  203. if (belem->bnr.bn && (belem->bnr.bn->node == node)) {
  204. return 1;
  205. }
  206. --belem;
  207. }
  208. return 0;
  209. }