If allocating a new node fails, the bplustree_header::maximum_size field is now
reseted to its old value. BPlusTree::SetTo() is now less strict about maximum_size vs. inode size differences; it will now print a warning and set the maximum_size to the inode size, even though the tree might be corrupted (reading should always be as compatible and forgiving as possible). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13946 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -250,8 +250,11 @@ CachedNode::Free(Transaction &transaction, off_t offset)
|
|||||||
// the tree and file size by one node
|
// the tree and file size by one node
|
||||||
off_t lastOffset = header->MaximumSize() - fTree->fNodeSize;
|
off_t lastOffset = header->MaximumSize() - fTree->fNodeSize;
|
||||||
if (offset == lastOffset) {
|
if (offset == lastOffset) {
|
||||||
|
status_t status = fTree->fStream->SetFileSize(transaction, lastOffset);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(lastOffset);
|
header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(lastOffset);
|
||||||
return fTree->fStream->SetFileSize(transaction, lastOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the node to the free nodes list
|
// add the node to the free nodes list
|
||||||
@@ -308,6 +311,9 @@ CachedNode::Allocate(Transaction &transaction, bplustree_node **_node, off_t *_o
|
|||||||
*_node = fNode;
|
*_node = fNode;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// revert header size to old value
|
||||||
|
header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(header->MaximumSize() - fTree->fNodeSize);
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,11 +431,14 @@ BPlusTree::SetTo(Inode *stream)
|
|||||||
fHeader = fCachedHeader.SetToHeader();
|
fHeader = fCachedHeader.SetToHeader();
|
||||||
if (fHeader == NULL)
|
if (fHeader == NULL)
|
||||||
RETURN_ERROR(fStatus = B_NO_INIT);
|
RETURN_ERROR(fStatus = B_NO_INIT);
|
||||||
|
|
||||||
// is header valid?
|
// is header valid?
|
||||||
|
|
||||||
|
if (fHeader->MaximumSize() != stream->Size()) {
|
||||||
|
FATAL(("B+tree header size doesn't fit file size!\n"));
|
||||||
|
fHeader->maximum_size = HOST_ENDIAN_TO_BFS_INT64(stream->Size());
|
||||||
|
}
|
||||||
if (fHeader->Magic() != BPLUSTREE_MAGIC
|
if (fHeader->Magic() != BPLUSTREE_MAGIC
|
||||||
|| fHeader->MaximumSize() != stream->Size()
|
|
||||||
|| (fHeader->RootNode() % fHeader->NodeSize()) != 0
|
|| (fHeader->RootNode() % fHeader->NodeSize()) != 0
|
||||||
|| !fHeader->IsValidLink(fHeader->RootNode())
|
|| !fHeader->IsValidLink(fHeader->RootNode())
|
||||||
|| !fHeader->IsValidLink(fHeader->FreeNode()))
|
|| !fHeader->IsValidLink(fHeader->FreeNode()))
|
||||||
@@ -442,7 +451,7 @@ BPlusTree::SetTo(Inode *stream)
|
|||||||
S_ULONG_LONG_INDEX, S_FLOAT_INDEX, S_DOUBLE_INDEX};
|
S_ULONG_LONG_INDEX, S_FLOAT_INDEX, S_DOUBLE_INDEX};
|
||||||
uint32 mode = stream->Mode() & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX | S_LONG_LONG_INDEX
|
uint32 mode = stream->Mode() & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX | S_LONG_LONG_INDEX
|
||||||
| S_ULONG_LONG_INDEX | S_FLOAT_INDEX | S_DOUBLE_INDEX);
|
| S_ULONG_LONG_INDEX | S_FLOAT_INDEX | S_DOUBLE_INDEX);
|
||||||
|
|
||||||
if (fHeader->DataType() > BPLUSTREE_DOUBLE_TYPE
|
if (fHeader->DataType() > BPLUSTREE_DOUBLE_TYPE
|
||||||
|| (stream->Mode() & S_INDEX_DIR) && toMode[fHeader->DataType()] != mode
|
|| (stream->Mode() & S_INDEX_DIR) && toMode[fHeader->DataType()] != mode
|
||||||
|| !stream->IsContainer()) {
|
|| !stream->IsContainer()) {
|
||||||
@@ -1239,8 +1248,8 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
|
|||||||
if (SplitNode(node, nodeAndKey.nodeOffset, other, otherOffset,
|
if (SplitNode(node, nodeAndKey.nodeOffset, other, otherOffset,
|
||||||
&nodeAndKey.keyIndex, keyBuffer, &keyLength, &value) < B_OK) {
|
&nodeAndKey.keyIndex, keyBuffer, &keyLength, &value) < B_OK) {
|
||||||
// free root node & other node here
|
// free root node & other node here
|
||||||
cachedNewRoot.Free(transaction, newRoot);
|
|
||||||
cachedOther.Free(transaction, otherOffset);
|
cachedOther.Free(transaction, otherOffset);
|
||||||
|
cachedNewRoot.Free(transaction, newRoot);
|
||||||
|
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user