Changes in BPlusTree::_SplitNode():
* Added check for invalid keyIndex parameter. * Removed superfluous break condition in the second loop. * Increment "out" in the second loop only when we have processed a key that will end up in the node. Thus, after the loop, the variable will contain the numbers of keys to be copied/moved, not that number + 1. Adjusted later use of "out" accordingly, save in one place where it was used incorrectly, which resulted in one key length and value to many to be copied, thus occasionally causing a page fault (bug #1363). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22195 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
759833c921
commit
8a10c0b5a7
|
@ -1001,6 +1001,12 @@ BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
|
|||
uint8 *outKeys = other->Keys();
|
||||
int32 keyIndex = *_keyIndex; // can become less than zero!
|
||||
|
||||
if (keyIndex > node->NumKeys()) {
|
||||
FATAL(("key index out of bounds: %d, num keys: %d\n", keyIndex,
|
||||
node->NumKeys()));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// how many keys will fit in one (half) page?
|
||||
// that loop will find the answer to this question and
|
||||
// change the key lengths indices for their new home
|
||||
|
@ -1140,6 +1146,7 @@ BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
|
|||
bytesBefore = in > skip
|
||||
? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0;
|
||||
bytes = *_keyLength;
|
||||
out++;
|
||||
} else {
|
||||
if (in < node->NumKeys()) {
|
||||
inKeyLengths[in] = HOST_ENDIAN_TO_BFS_INT16(
|
||||
|
@ -1152,22 +1159,14 @@ BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
|
|||
bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in])
|
||||
- bytesBefore - bytes;
|
||||
}
|
||||
out++;
|
||||
}
|
||||
in++;
|
||||
}
|
||||
|
||||
out++;
|
||||
|
||||
// break out when all keys are done
|
||||
if (in > node->NumKeys() && keyIndex < in)
|
||||
break;
|
||||
}
|
||||
|
||||
// adjust the byte counts (since we were a bit lazy in the loop)
|
||||
if (keyIndex >= in && keyIndex - skip < out) {
|
||||
bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in])
|
||||
- bytesBefore - total;
|
||||
} else if (keyIndex < skip)
|
||||
if (keyIndex < skip)
|
||||
bytesBefore = node->AllKeyLength() - total;
|
||||
|
||||
if (bytesBefore < 0 || bytesAfter < 0) {
|
||||
|
@ -1180,7 +1179,7 @@ BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
|
|||
// right link, and overflow link can stay the same
|
||||
node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore
|
||||
+ bytesAfter);
|
||||
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out - 1);
|
||||
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out);
|
||||
|
||||
// array positions have changed
|
||||
outKeyLengths = node->KeyLengths();
|
||||
|
@ -1189,7 +1188,7 @@ BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
|
|||
// move the keys in the old node: the order is important here,
|
||||
// because we don't want to overwrite any contents
|
||||
|
||||
keys = keyIndex <= skip ? out - 1 : keyIndex - skip;
|
||||
keys = keyIndex <= skip ? out : keyIndex - skip;
|
||||
keyIndex -= skip;
|
||||
in = out - keyIndex - 1;
|
||||
// Note: keyIndex and in will contain invalid values when the new key
|
||||
|
|
Loading…
Reference in New Issue