* Coding style cleanups, no functional changes.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26728 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-08-02 14:06:38 +00:00
parent 51daeb7147
commit 02c8f6c89d
13 changed files with 1333 additions and 1259 deletions
@@ -10,7 +10,8 @@
// TODO: clean this up, find a better separation between Inode and this class // TODO: clean this up, find a better separation between Inode and this class
// TODO: even after Create(), the attribute cannot be stat() for until the first write // TODO: even after Create(), the attribute cannot be stat() for until the
// first write
extern void fill_stat_buffer(Inode* inode, struct stat& stat); extern void fill_stat_buffer(Inode* inode, struct stat& stat);
@@ -203,8 +204,8 @@ Attribute::Read(attr_cookie *cookie, off_t pos, uint8 *buffer, size_t *_length)
status_t status_t
Attribute::Write(Transaction &transaction, attr_cookie *cookie, Attribute::Write(Transaction& transaction, attr_cookie* cookie, off_t pos,
off_t pos, const uint8 *buffer, size_t *_length) const uint8* buffer, size_t* _length)
{ {
if (!cookie->create && fSmall == NULL && fAttribute == NULL) if (!cookie->create && fSmall == NULL && fAttribute == NULL)
return B_NO_INIT; return B_NO_INIT;
@@ -1,6 +1,5 @@
/* Attribute - connection between pure inode and kernel_interface attributes /*
* * Copyright 2004-2008, Axel Dörfler, [email protected].
* Copyright 2004, Axel Dörfler, [email protected].
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
#ifndef ATTRIBUTE_H #ifndef ATTRIBUTE_H
@@ -30,15 +29,18 @@ class Attribute {
status_t Get(const char* name); status_t Get(const char* name);
void Put(); void Put();
status_t Create(const char *name, type_code type, int openMode, status_t Create(const char* name, type_code type,
int openMode, attr_cookie** _cookie);
status_t Open(const char* name, int openMode,
attr_cookie** _cookie); attr_cookie** _cookie);
status_t Open(const char *name, int openMode, attr_cookie **_cookie);
status_t Stat(struct stat& stat); status_t Stat(struct stat& stat);
status_t Read(attr_cookie *cookie, off_t pos, uint8 *buffer, size_t *_length); status_t Read(attr_cookie* cookie, off_t pos, uint8* buffer,
size_t* _length);
status_t Write(Transaction& transaction, attr_cookie* cookie, status_t Write(Transaction& transaction, attr_cookie* cookie,
off_t pos, const uint8 *buffer, size_t *_length); off_t pos, const uint8* buffer,
size_t* _length);
private: private:
status_t _Truncate(); status_t _Truncate();
@@ -50,4 +52,4 @@ class Attribute {
const char* fName; const char* fName;
}; };
#endif /* ATTRIBUTE_H */ #endif // ATTRIBUTE_H
+142 -97
View File
@@ -82,7 +82,8 @@ CachedNode::Unset()
return; return;
if (fNode != NULL) { if (fNode != NULL) {
block_cache_put(fTree->fStream->GetVolume()->BlockCache(), fBlockNumber); block_cache_put(fTree->fStream->GetVolume()->BlockCache(),
fBlockNumber);
fNode = NULL; fNode = NULL;
} }
} }
@@ -225,9 +226,10 @@ CachedNode::InternalSetTo(Transaction *transaction, off_t offset)
} }
if (block) { if (block) {
// the node is somewhere in that block... (confusing offset calculation) // The node is somewhere in that block...
fNode = (bplustree_node *)(block + offset - // (confusing offset calculation)
(fileOffset + (blockOffset << volume->BlockShift()))); fNode = (bplustree_node*)(block + offset
- (fileOffset + (blockOffset << volume->BlockShift())));
} else } else
REPORT_ERROR(B_IO_ERROR); REPORT_ERROR(B_IO_ERROR);
} }
@@ -246,7 +248,8 @@ CachedNode::Free(Transaction &transaction, off_t offset)
// function is called, perhaps it should be done when the directory // function is called, perhaps it should be done when the directory
// inode is closed or based on some calculation or whatever... // inode is closed or based on some calculation or whatever...
bplustree_header *header = fTree->fCachedHeader.MakeWritableHeader(transaction); bplustree_header* header
= fTree->fCachedHeader.MakeWritableHeader(transaction);
if (header == NULL) if (header == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -419,7 +422,8 @@ BPlusTree::SetTo(Transaction &transaction, Inode *stream, int32 nodeSize)
header->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1); header->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
header->data_type = HOST_ENDIAN_TO_BFS_INT32(ModeToKeyType(stream->Mode())); header->data_type = HOST_ENDIAN_TO_BFS_INT32(ModeToKeyType(stream->Mode()));
header->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(nodeSize); header->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(nodeSize);
header->free_node_pointer = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL); header->free_node_pointer
= HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(nodeSize * 2); header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(nodeSize * 2);
// initialize b+tree root node // initialize b+tree root node
@@ -684,8 +688,7 @@ BPlusTree::_FindKey(const bplustree_node *node, const uint8 *key,
} }
/*! /*! Prepares the stack to contain all nodes that were passed while
Prepares the stack to contain all nodes that were passed while
following the key, from the root node to the leaf node that could following the key, from the root node to the leaf node that could
or should contain that key. or should contain that key.
*/ */
@@ -733,8 +736,7 @@ BPlusTree::_SeekDown(Stack<node_and_key> &stack, const uint8 *key,
} }
/*! /*! This will find a free duplicate fragment in the given bplustree_node.
This will find a free duplicate fragment in the given bplustree_node.
The CachedNode will be set to the writable fragment on success. The CachedNode will be set to the writable fragment on success.
*/ */
status_t status_t
@@ -792,8 +794,10 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
// If it's a duplicate fragment, try to insert it into that, or if it // If it's a duplicate fragment, try to insert it into that, or if it
// doesn't fit anymore, create a new duplicate node // doesn't fit anymore, create a new duplicate node
if (bplustree_node::LinkType(oldValue) == BPLUSTREE_DUPLICATE_FRAGMENT) { if (bplustree_node::LinkType(oldValue)
bplustree_node *duplicate = cachedDuplicate.SetToWritable(transaction, == BPLUSTREE_DUPLICATE_FRAGMENT) {
bplustree_node* duplicate
= cachedDuplicate.SetToWritable(transaction,
bplustree_node::FragmentOffset(oldValue), false); bplustree_node::FragmentOffset(oldValue), false);
if (duplicate == NULL) if (duplicate == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -802,19 +806,20 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
bplustree_node::FragmentIndex(oldValue)); bplustree_node::FragmentIndex(oldValue));
if (array->count > NUM_FRAGMENT_VALUES if (array->count > NUM_FRAGMENT_VALUES
|| array->count < 1) { || array->count < 1) {
FATAL(("insertDuplicate: Invalid array[%d] size in fragment %Ld == %Ld!\n", FATAL(("insertDuplicate: Invalid array[%d] size in fragment "
"%Ld == %Ld!\n",
(int)bplustree_node::FragmentIndex(oldValue), (int)bplustree_node::FragmentIndex(oldValue),
bplustree_node::FragmentOffset(oldValue), bplustree_node::FragmentOffset(oldValue), array->count));
array->count));
return B_BAD_DATA; return B_BAD_DATA;
} }
if (array->count < NUM_FRAGMENT_VALUES) { if (array->count < NUM_FRAGMENT_VALUES) {
array->Insert(value); array->Insert(value);
} else { } else {
// test if the fragment will be empty if we remove this key's values // Test if the fragment will be empty if we remove this key's
// values
if (duplicate->FragmentsUsed(fNodeSize) < 2) { if (duplicate->FragmentsUsed(fNodeSize) < 2) {
// the node will be empty without our values, so let us // The node will be empty without our values, so let us
// reuse it as a duplicate node // reuse it as a duplicate node
offset = bplustree_node::FragmentOffset(oldValue); offset = bplustree_node::FragmentOffset(oldValue);
@@ -826,10 +831,11 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
array->Insert(value); array->Insert(value);
} else { } else {
// create a new duplicate node // Create a new duplicate node
cachedDuplicate.UnsetUnchanged(transaction); cachedDuplicate.UnsetUnchanged(transaction);
// the old duplicate has not been touched, so we can reuse it // The old duplicate has not been touched, so we can
// reuse it
bplustree_node* newDuplicate; bplustree_node* newDuplicate;
status = cachedDuplicate.Allocate(transaction, status = cachedDuplicate.Allocate(transaction,
@@ -837,8 +843,8 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
if (status < B_OK) if (status < B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
// copy the array from the fragment node to the duplicate node // Copy the array from the fragment node to the duplicate
// and free the old entry (by zero'ing all values) // node and free the old entry (by zero'ing all values)
newDuplicate->overflow_link = HOST_ENDIAN_TO_BFS_INT64( newDuplicate->overflow_link = HOST_ENDIAN_TO_BFS_INT64(
array->count); array->count);
memcpy(&newDuplicate->all_key_count, &array->values[0], memcpy(&newDuplicate->all_key_count, &array->values[0],
@@ -849,11 +855,12 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
array->Insert(value); array->Insert(value);
} }
// update the main pointer to link to a duplicate node // Update the main pointer to link to a duplicate node
if (cached.MakeWritable(transaction) == NULL) if (cached.MakeWritable(transaction) == NULL)
return B_IO_ERROR; return B_IO_ERROR;
values[index] = HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( values[index]
= HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink(
BPLUSTREE_DUPLICATE_NODE, offset)); BPLUSTREE_DUPLICATE_NODE, offset));
} }
@@ -874,14 +881,15 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (array->count > NUM_DUPLICATE_VALUES || array->count < 0) { if (array->count > NUM_DUPLICATE_VALUES || array->count < 0) {
FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n", FATAL(("removeDuplicate: Invalid array size in duplicate %Ld "
duplicateOffset, array->count)); "== %Ld!\n", duplicateOffset, array->count));
return B_BAD_DATA; return B_BAD_DATA;
} }
} while (array->count >= NUM_DUPLICATE_VALUES } while (array->count >= NUM_DUPLICATE_VALUES
&& (oldValue = duplicate->RightLink()) != BPLUSTREE_NULL); && (oldValue = duplicate->RightLink()) != BPLUSTREE_NULL);
bplustree_node *writableDuplicate = cachedDuplicate.MakeWritable(transaction); bplustree_node* writableDuplicate
= cachedDuplicate.MakeWritable(transaction);
if (writableDuplicate == NULL) if (writableDuplicate == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -892,7 +900,8 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
// no space left - add a new duplicate node // no space left - add a new duplicate node
bplustree_node* newDuplicate; bplustree_node* newDuplicate;
status = cachedDuplicate.Allocate(transaction, &newDuplicate, &offset); status = cachedDuplicate.Allocate(transaction, &newDuplicate,
&offset);
if (status < B_OK) if (status < B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
@@ -984,10 +993,9 @@ BPlusTree::_InsertKey(bplustree_node *node, uint16 index, uint8 *key,
} }
/*! /*! Splits the \a node into two halves - the other half will be put into
Splits the \a node into two halves - the other half will be put into \a other. \a other. It also takes care to create a new overflow link if the node
It also takes care to create a new overflow link if the node to split is an to split is an index node.
index node.
*/ */
status_t status_t
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset, BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
@@ -1082,7 +1090,8 @@ BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
keys = out - keyIndex - 1; keys = out - keyIndex - 1;
for (int32 i = 0;i < keys;i++) { for (int32 i = 0;i < keys;i++) {
outKeyLengths[keyIndex + i + 1] = HOST_ENDIAN_TO_BFS_INT16( outKeyLengths[keyIndex + i + 1] = HOST_ENDIAN_TO_BFS_INT16(
BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[keyIndex + i]) + bytes); BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[keyIndex + i])
+ bytes);
} }
memcpy(outKeyValues + keyIndex + 1, inKeyValues + keyIndex, memcpy(outKeyValues + keyIndex + 1, inKeyValues + keyIndex,
keys * sizeof(off_t)); keys * sizeof(off_t));
@@ -1421,8 +1430,9 @@ BPlusTree::_RemoveDuplicate(Transaction &transaction,
if (array->count > NUM_FRAGMENT_VALUES if (array->count > NUM_FRAGMENT_VALUES
|| array->count < 1) { || array->count < 1) {
FATAL(("removeDuplicate: Invalid array[%d] size in fragment %Ld == %Ld!\n", FATAL(("removeDuplicate: Invalid array[%d] size in fragment %Ld "
(int)bplustree_node::FragmentIndex(oldValue), duplicateOffset, array->count)); "== %Ld!\n", (int)bplustree_node::FragmentIndex(oldValue),
duplicateOffset, array->count));
return B_BAD_DATA; return B_BAD_DATA;
} }
if (!array->Remove(value)) { if (!array->Remove(value)) {
@@ -1442,7 +1452,8 @@ BPlusTree::_RemoveDuplicate(Transaction &transaction,
// Remove the whole fragment node, if this was the only array, // Remove the whole fragment node, if this was the only array,
// otherwise free just the array // otherwise free just the array
if (duplicate->FragmentsUsed(fNodeSize) == 1) { if (duplicate->FragmentsUsed(fNodeSize) == 1) {
status_t status = cachedDuplicate.Free(transaction, duplicateOffset); status_t status = cachedDuplicate.Free(transaction,
duplicateOffset);
if (status < B_OK) if (status < B_OK)
return status; return status;
} else } else
@@ -1466,8 +1477,8 @@ BPlusTree::_RemoveDuplicate(Transaction &transaction,
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (array->count > NUM_DUPLICATE_VALUES if (array->count > NUM_DUPLICATE_VALUES
|| array->count < 0) { || array->count < 0) {
FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n", FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == "
duplicateOffset, array->count)); "%Ld!\n", duplicateOffset, array->count));
return B_BAD_DATA; return B_BAD_DATA;
} }
@@ -1478,7 +1489,8 @@ BPlusTree::_RemoveDuplicate(Transaction &transaction,
RETURN_ERROR(B_ENTRY_NOT_FOUND); RETURN_ERROR(B_ENTRY_NOT_FOUND);
cachedDuplicate.UnsetUnchanged(transaction); cachedDuplicate.UnsetUnchanged(transaction);
duplicate = cachedDuplicate.SetToWritable(transaction, duplicateOffset, false); duplicate = cachedDuplicate.SetToWritable(transaction, duplicateOffset,
false);
} }
if (duplicate == NULL) if (duplicate == NULL)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
@@ -1502,41 +1514,48 @@ BPlusTree::_RemoveDuplicate(Transaction &transaction,
return B_IO_ERROR; return B_IO_ERROR;
if (array->count == 1) { if (array->count == 1) {
// this is the last node, and there is only one value left; // This is the last node, and there is only one value left;
// replace the duplicate link with that value, it's no duplicate // replace the duplicate link with that value, it's no
// anymore // duplicate anymore
values[index] = array->values[0]; values[index] = array->values[0];
} else { } else {
// move the duplicate link to the next node // Move the duplicate link to the next node
values[index] = HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( values[index] = HOST_ENDIAN_TO_BFS_INT64(
bplustree_node::MakeLink(
BPLUSTREE_DUPLICATE_NODE, right)); BPLUSTREE_DUPLICATE_NODE, right));
} }
} }
status_t status; status_t status = cachedDuplicate.Free(transaction,
if ((status = cachedDuplicate.Free(transaction, duplicateOffset)) < B_OK) duplicateOffset);
if (status < B_OK)
return status; return status;
if (left != BPLUSTREE_NULL if (left != BPLUSTREE_NULL
&& (duplicate = cachedDuplicate.SetToWritable(transaction, left, false)) != NULL) { && (duplicate = cachedDuplicate.SetToWritable(transaction, left,
false)) != NULL) {
duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(right); duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(right);
// If the next node is the last node, we need to free that node // If the next node is the last node, we need to free that node
// and convert the duplicate entry back into a normal entry // and convert the duplicate entry back into a normal entry
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (right == BPLUSTREE_NULL && duplicate->LeftLink() == BPLUSTREE_NULL if (right == BPLUSTREE_NULL
&& duplicate->LeftLink() == BPLUSTREE_NULL
&& array->count <= NUM_FRAGMENT_VALUES) { && array->count <= NUM_FRAGMENT_VALUES) {
duplicateOffset = left; duplicateOffset = left;
continue; continue;
} }
} }
if (right != BPLUSTREE_NULL if (right != BPLUSTREE_NULL
&& (duplicate = cachedDuplicate.SetToWritable(transaction, right, false)) != NULL) { && (duplicate = cachedDuplicate.SetToWritable(transaction,
right, false)) != NULL) {
duplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(left); duplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(left);
// Again, we may need to turn the duplicate entry back into a normal entry // Again, we may need to turn the duplicate entry back into a
// normal entry
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (left == BPLUSTREE_NULL && duplicate->RightLink() == BPLUSTREE_NULL if (left == BPLUSTREE_NULL
&& duplicate->RightLink() == BPLUSTREE_NULL
&& array->count <= NUM_FRAGMENT_VALUES) { && array->count <= NUM_FRAGMENT_VALUES) {
duplicateOffset = right; duplicateOffset = right;
continue; continue;
@@ -1556,13 +1575,15 @@ BPlusTree::_RemoveDuplicate(Transaction &transaction,
&offset, &fragment, &fragmentIndex) == B_OK) { &offset, &fragment, &fragmentIndex) == B_OK) {
// move to other node // move to other node
duplicate_array* target = fragment->FragmentAt(fragmentIndex); duplicate_array* target = fragment->FragmentAt(fragmentIndex);
memcpy(target, array, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); memcpy(target, array,
(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
cachedDuplicate.Free(transaction, duplicateOffset); cachedDuplicate.Free(transaction, duplicateOffset);
duplicateOffset = offset; duplicateOffset = offset;
} else { } else {
// convert node // convert node
memmove(duplicate, array, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); memmove(duplicate, array,
(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
memset((off_t*)duplicate + NUM_FRAGMENT_VALUES + 1, 0, memset((off_t*)duplicate + NUM_FRAGMENT_VALUES + 1, 0,
fNodeSize - (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); fNodeSize - (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
} }
@@ -1605,7 +1626,8 @@ BPlusTree::_RemoveKey(bplustree_node *node, uint16 index)
if (key + length + sizeof(off_t) + sizeof(uint16) > (uint8*)node + fNodeSize if (key + length + sizeof(off_t) + sizeof(uint16) > (uint8*)node + fNodeSize
|| length > BPLUSTREE_MAX_KEY_LENGTH) { || length > BPLUSTREE_MAX_KEY_LENGTH) {
FATAL(("Key length to long: %s, %u (inode at %d,%u)\n", key, length, FATAL(("Key length to long: %s, %u (inode at %d,%u)\n", key, length,
(int)fStream->BlockRun().allocation_group, fStream->BlockRun().start)); (int)fStream->BlockRun().allocation_group,
fStream->BlockRun().start));
fStream->GetVolume()->Panic(); fStream->GetVolume()->Panic();
return; return;
} }
@@ -1614,7 +1636,8 @@ BPlusTree::_RemoveKey(bplustree_node *node, uint16 index)
uint8* keys = node->Keys(); uint8* keys = node->Keys();
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() - 1); node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() - 1);
node->all_key_length = HOST_ENDIAN_TO_BFS_INT64(node->AllKeyLength() - length); node->all_key_length = HOST_ENDIAN_TO_BFS_INT64(
node->AllKeyLength() - length);
off_t* newValues = node->Values(); off_t* newValues = node->Values();
uint16* newKeyLengths = node->KeyLengths(); uint16* newKeyLengths = node->KeyLengths();
@@ -1633,8 +1656,10 @@ BPlusTree::_RemoveKey(bplustree_node *node, uint16 index)
// move values // move values
if (index > 0) if (index > 0)
memmove(newValues, values, index * sizeof(off_t)); memmove(newValues, values, index * sizeof(off_t));
if (node->NumKeys() > index) if (node->NumKeys() > index) {
memmove(newValues + index, values + index + 1, (node->NumKeys() - index) * sizeof(off_t)); memmove(newValues + index, values + index + 1,
(node->NumKeys() - index) * sizeof(off_t));
}
} }
@@ -1689,7 +1714,8 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
return _RemoveDuplicate(transaction, node, cached, return _RemoveDuplicate(transaction, node, cached,
nodeAndKey.keyIndex, value); nodeAndKey.keyIndex, value);
} else { } else {
FATAL(("dupliate node found where no duplicates are allowed!\n")); FATAL(("dupliate node found where no duplicates are "
"allowed!\n"));
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
} }
} }
@@ -1703,15 +1729,18 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
// to a leaf node by dropping the overflow link, or, // to a leaf node by dropping the overflow link, or,
// if it's already a leaf node, just empty it // if it's already a leaf node, just empty it
if (nodeAndKey.nodeOffset == fHeader->RootNode() if (nodeAndKey.nodeOffset == fHeader->RootNode()
&& (node->NumKeys() == 0 || (node->NumKeys() == 1 && node->IsLeaf()))) { && (node->NumKeys() == 0
writableNode->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL); || (node->NumKeys() == 1 && node->IsLeaf()))) {
writableNode->overflow_link
= HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
writableNode->all_key_count = 0; writableNode->all_key_count = 0;
writableNode->all_key_length = 0; writableNode->all_key_length = 0;
// if we've made a leaf node out of the root node, we need // if we've made a leaf node out of the root node, we need
// to reset the maximum number of levels in the header // to reset the maximum number of levels in the header
if (fHeader->MaxNumberOfLevels() != 1) { if (fHeader->MaxNumberOfLevels() != 1) {
bplustree_header *header = fCachedHeader.MakeWritableHeader(transaction); bplustree_header* header
= fCachedHeader.MakeWritableHeader(transaction);
if (header == NULL) if (header == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -1738,8 +1767,10 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
if (other != NULL) if (other != NULL)
other->right_link = writableNode->right_link; other->right_link = writableNode->right_link;
if ((other = otherCached.SetToWritable(transaction, node->RightLink())) != NULL) if ((other = otherCached.SetToWritable(transaction, node->RightLink()))
!= NULL) {
other->left_link = writableNode->left_link; other->left_link = writableNode->left_link;
}
cached.Free(transaction, nodeAndKey.nodeOffset); cached.Free(transaction, nodeAndKey.nodeOffset);
} }
@@ -1757,8 +1788,8 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
You need to have the inode write locked. You need to have the inode write locked.
*/ */
status_t status_t
BPlusTree::Replace(Transaction &transaction, const uint8 *key, BPlusTree::Replace(Transaction& transaction, const uint8* key, uint16 keyLength,
uint16 keyLength, off_t value) off_t value)
{ {
if (keyLength < BPLUSTREE_MIN_KEY_LENGTH if (keyLength < BPLUSTREE_MIN_KEY_LENGTH
|| keyLength > BPLUSTREE_MAX_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH
@@ -1777,14 +1808,16 @@ BPlusTree::Replace(Transaction &transaction, const uint8 *key,
while ((node = cached.SetTo(nodeOffset)) != NULL) { while ((node = cached.SetTo(nodeOffset)) != NULL) {
uint16 keyIndex = 0; uint16 keyIndex = 0;
off_t nextOffset; off_t nextOffset;
status_t status = _FindKey(node, key, keyLength, &keyIndex, &nextOffset); status_t status = _FindKey(node, key, keyLength, &keyIndex,
&nextOffset);
if (node->OverflowLink() == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
if (status == B_OK) { if (status == B_OK) {
bplustree_node* writableNode = cached.MakeWritable(transaction); bplustree_node* writableNode = cached.MakeWritable(transaction);
if (writableNode != NULL) if (writableNode != NULL) {
writableNode->Values()[keyIndex] = HOST_ENDIAN_TO_BFS_INT64(value); writableNode->Values()[keyIndex]
else = HOST_ENDIAN_TO_BFS_INT64(value);
} else
status = B_IO_ERROR; status = B_IO_ERROR;
} }
@@ -1798,16 +1831,15 @@ BPlusTree::Replace(Transaction &transaction, const uint8 *key,
} }
/*! Searches the key in the tree, and stores the offset found in /*! Searches the key in the tree, and stores the offset found in _value,
_value, if successful. if successful.
It's very similar to BPlusTree::SeekDown(), but doesn't fill It's very similar to BPlusTree::SeekDown(), but doesn't fill a stack
a stack while it descends the tree. while it descends the tree.
Returns B_OK when the key could be found, B_ENTRY_NOT_FOUND Returns B_OK when the key could be found, B_ENTRY_NOT_FOUND if not.
if not. It can also return other errors to indicate that It can also return other errors to indicate that something went wrong.
something went wrong. Note that this doesn't work with duplicates - it will just return
Note that this doesn't work with duplicates - it will just B_BAD_TYPE if you call this function on a tree where duplicates are
return B_BAD_TYPE if you call this function on a tree where allowed.
duplicates are allowed.
You need to have the inode read or write locked. You need to have the inode read or write locked.
*/ */
status_t status_t
@@ -1834,7 +1866,8 @@ BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
while ((node = cached.SetTo(nodeOffset)) != NULL) { while ((node = cached.SetTo(nodeOffset)) != NULL) {
uint16 keyIndex = 0; uint16 keyIndex = 0;
off_t nextOffset; off_t nextOffset;
status_t status = _FindKey(node, key, keyLength, &keyIndex, &nextOffset); status_t status = _FindKey(node, key, keyLength, &keyIndex,
&nextOffset);
#ifdef DEBUG #ifdef DEBUG
levels++; levels++;
@@ -1924,8 +1957,7 @@ TreeIterator::Goto(int8 to)
} }
/*! /*! Iterates through the tree in the specified direction.
Iterates through the tree in the specified direction.
When it iterates through duplicates, the "key" is only updated for the When it iterates through duplicates, the "key" is only updated for the
first entry - if you need to know when this happens, use the "duplicate" first entry - if you need to know when this happens, use the "duplicate"
parameter which is 0 for no duplicate, 1 for the first, and 2 for all parameter which is 0 for no duplicate, 1 for the first, and 2 for all
@@ -1960,27 +1992,31 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
const bplustree_node* node; const bplustree_node* node;
if (fDuplicateNode != BPLUSTREE_NULL) { if (fDuplicateNode != BPLUSTREE_NULL) {
// regardless of traverse direction the duplicates are always presented in // regardless of traverse direction the duplicates are always presented
// the same order; since they are all considered as equal, this shouldn't // in the same order; since they are all considered as equal, this
// cause any problems // shouldn't cause any problems
if (!fIsFragment || fDuplicate < fNumDuplicates) if (!fIsFragment || fDuplicate < fNumDuplicates) {
node = cached.SetTo(bplustree_node::FragmentOffset(fDuplicateNode), false); node = cached.SetTo(bplustree_node::FragmentOffset(fDuplicateNode),
else false);
} else
node = NULL; node = NULL;
if (node != NULL) { if (node != NULL) {
if (!fIsFragment && fDuplicate >= fNumDuplicates) { if (!fIsFragment && fDuplicate >= fNumDuplicates) {
// if the node is out of duplicates, we go directly to the next one // If the node is out of duplicates, we go directly to the next
// one
fDuplicateNode = node->RightLink(); fDuplicateNode = node->RightLink();
if (fDuplicateNode != BPLUSTREE_NULL if (fDuplicateNode != BPLUSTREE_NULL
&& (node = cached.SetTo(fDuplicateNode, false)) != NULL) { && (node = cached.SetTo(fDuplicateNode, false)) != NULL) {
fNumDuplicates = node->CountDuplicates(fDuplicateNode, false); fNumDuplicates = node->CountDuplicates(fDuplicateNode,
false);
fDuplicate = 0; fDuplicate = 0;
} }
} }
if (fDuplicate < fNumDuplicates) { if (fDuplicate < fNumDuplicates) {
*value = node->DuplicateAt(fDuplicateNode, fIsFragment, fDuplicate++); *value = node->DuplicateAt(fDuplicateNode, fIsFragment,
fDuplicate++);
if (duplicate) if (duplicate)
*duplicate = 2; *duplicate = 2;
return B_OK; return B_OK;
@@ -2027,7 +2063,8 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
uint16 length; uint16 length;
uint8* keyStart = node->KeyAt(fCurrentKey, &length); uint8* keyStart = node->KeyAt(fCurrentKey, &length);
if (keyStart + length + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fTree->fNodeSize if (keyStart + length + sizeof(off_t) + sizeof(uint16)
> (uint8*)node + fTree->fNodeSize
|| length > BPLUSTREE_MAX_KEY_LENGTH) { || length > BPLUSTREE_MAX_KEY_LENGTH) {
fTree->fStream->GetVolume()->Panic(); fTree->fStream->GetVolume()->Panic();
RETURN_ERROR(B_BAD_DATA); RETURN_ERROR(B_BAD_DATA);
@@ -2048,10 +2085,12 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
// duplicate fragments? // duplicate fragments?
uint8 type = bplustree_node::LinkType(offset); uint8 type = bplustree_node::LinkType(offset);
if (type == BPLUSTREE_DUPLICATE_FRAGMENT || type == BPLUSTREE_DUPLICATE_NODE) { if (type == BPLUSTREE_DUPLICATE_FRAGMENT
|| type == BPLUSTREE_DUPLICATE_NODE) {
fDuplicateNode = offset; fDuplicateNode = offset;
node = cached.SetTo(bplustree_node::FragmentOffset(fDuplicateNode), false); node = cached.SetTo(bplustree_node::FragmentOffset(fDuplicateNode),
false);
if (node == NULL) if (node == NULL)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
@@ -2064,7 +2103,8 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
if (duplicate) if (duplicate)
*duplicate = 1; *duplicate = 1;
} else { } else {
// shouldn't happen, but we're dealing here with potentially corrupt disks... // Shouldn't happen, but we're dealing here with potentially
// corrupt disks...
fDuplicateNode = BPLUSTREE_NULL; fDuplicateNode = BPLUSTREE_NULL;
offset = 0; offset = 0;
} }
@@ -2084,7 +2124,8 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
{ {
if (fTree == NULL) if (fTree == NULL)
return B_INTERRUPTED; return B_INTERRUPTED;
if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH if (keyLength < BPLUSTREE_MIN_KEY_LENGTH
|| keyLength > BPLUSTREE_MAX_KEY_LENGTH
|| key == NULL) || key == NULL)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
@@ -2163,7 +2204,9 @@ TreeIterator::Dump()
__out("\tfTree = %p\n", fTree); __out("\tfTree = %p\n", fTree);
__out("\tfCurrentNodeOffset = %Ld\n", fCurrentNodeOffset); __out("\tfCurrentNodeOffset = %Ld\n", fCurrentNodeOffset);
__out("\tfCurrentKey = %ld\n", fCurrentKey); __out("\tfCurrentKey = %ld\n", fCurrentKey);
__out("\tfDuplicateNode = %Ld (%Ld, 0x%Lx)\n", bplustree_node::FragmentOffset(fDuplicateNode), fDuplicateNode, fDuplicateNode); __out("\tfDuplicateNode = %Ld (%Ld, 0x%Lx)\n",
bplustree_node::FragmentOffset(fDuplicateNode), fDuplicateNode,
fDuplicateNode);
__out("\tfDuplicate = %u\n", fDuplicate); __out("\tfDuplicate = %u\n", fDuplicate);
__out("\tfNumDuplicates = %u\n", fNumDuplicates); __out("\tfNumDuplicates = %u\n", fNumDuplicates);
__out("\tfIsFragment = %s\n", fIsFragment ? "true" : "false"); __out("\tfIsFragment = %s\n", fIsFragment ? "true" : "false");
@@ -2177,7 +2220,8 @@ TreeIterator::Dump()
void void
bplustree_node::Initialize() bplustree_node::Initialize()
{ {
left_link = right_link = overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL); left_link = right_link = overflow_link
= HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
all_key_count = 0; all_key_count = 0;
all_key_length = 0; all_key_length = 0;
} }
@@ -2257,7 +2301,8 @@ bplustree_node::CheckIntegrity(uint32 nodeSize) const
for (int32 i = 0; i < NumKeys(); i++) { for (int32 i = 0; i < NumKeys(); i++) {
uint16 length; uint16 length;
uint8* key = KeyAt(i, &length); uint8* key = KeyAt(i, &length);
if (key + length + sizeof(off_t) + sizeof(uint16) > (uint8 *)this + nodeSize if (key + length + sizeof(off_t) + sizeof(uint16)
> (uint8*)this + nodeSize
|| length > BPLUSTREE_MAX_KEY_LENGTH) { || length > BPLUSTREE_MAX_KEY_LENGTH) {
dprintf("node %p, key %ld\n", this, i); dprintf("node %p, key %ld\n", this, i);
DEBUGGER(("invalid node: keys corrupted")); DEBUGGER(("invalid node: keys corrupted"));
@@ -29,21 +29,28 @@ class BlockAllocator {
void Uninitialize(); void Uninitialize();
status_t AllocateForInode(Transaction &transaction, const block_run *parent, status_t AllocateForInode(Transaction& transaction,
mode_t type, block_run &run); const block_run* parent, mode_t type,
status_t Allocate(Transaction &transaction, Inode *inode, off_t numBlocks, block_run& run);
block_run &run, uint16 minimum = 1); status_t Allocate(Transaction& transaction, Inode* inode,
off_t numBlocks, block_run& run,
uint16 minimum = 1);
status_t Free(Transaction& transaction, block_run run); status_t Free(Transaction& transaction, block_run run);
status_t AllocateBlocks(Transaction &transaction, int32 group, uint16 start, status_t AllocateBlocks(Transaction& transaction,
uint16 numBlocks, uint16 minimum, block_run &run); int32 group, uint16 start, uint16 numBlocks,
uint16 minimum, block_run& run);
status_t StartChecking(check_control* control); status_t StartChecking(check_control* control);
status_t StopChecking(check_control* control); status_t StopChecking(check_control* control);
status_t CheckNextNode(check_control* control); status_t CheckNextNode(check_control* control);
status_t CheckBlockRun(block_run run, const char *type = NULL, check_control *control = NULL, bool allocated = true); status_t CheckBlockRun(block_run run,
status_t CheckInode(Inode *inode, check_control *control = NULL); const char* type = NULL,
check_control* control = NULL,
bool allocated = true);
status_t CheckInode(Inode* inode,
check_control* control = NULL);
size_t BitmapSize() const; size_t BitmapSize() const;
@@ -56,7 +63,7 @@ class BlockAllocator {
bool _CheckBitmapIsUsedAt(off_t block) const; bool _CheckBitmapIsUsedAt(off_t block) const;
void _SetCheckBitmapAt(off_t block); void _SetCheckBitmapAt(off_t block);
static status_t _Initialize(BlockAllocator *); static status_t _Initialize(BlockAllocator* self);
Volume* fVolume; Volume* fVolume;
mutex fLock; mutex fLock;
@@ -72,4 +79,4 @@ class BlockAllocator {
int dump_block_allocator(int argc, char** argv); int dump_block_allocator(int argc, char** argv);
#endif #endif
#endif /* BLOCK_ALLOCATOR_H */ #endif // BLOCK_ALLOCATOR_H
@@ -51,8 +51,7 @@ Index::Unset()
} }
/*! /*! Sets the index to specified one. Returns an error if the index could
Sets the index to specified one. Returns an error if the index could
not be found or initialized. not be found or initialized.
Note, Index::Update() may be called on the object even if this method Note, Index::Update() may be called on the object even if this method
failed previously. In this case, it will only update live queries for failed previously. In this case, it will only update live queries for
+24 -15
View File
@@ -1,6 +1,5 @@
/* Index - index access functions /*
* * Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2001-2004, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
#ifndef INDEX_H #ifndef INDEX_H
@@ -9,6 +8,7 @@
#include "system_dependencies.h" #include "system_dependencies.h"
class Transaction; class Transaction;
class Volume; class Volume;
class Inode; class Inode;
@@ -26,27 +26,36 @@ class Index {
uint32 Type(); uint32 Type();
size_t KeySize(); size_t KeySize();
status_t Create(Transaction &transaction, const char *name, uint32 type); status_t Create(Transaction& transaction, const char* name,
uint32 type);
status_t Update(Transaction &transaction, const char *name, int32 type, const uint8 *oldKey, status_t Update(Transaction& transaction, const char* name,
uint16 oldLength, const uint8 *newKey, uint16 newLength, Inode *inode); int32 type, const uint8* oldKey,
uint16 oldLength, const uint8* newKey,
uint16 newLength, Inode* inode);
status_t InsertName(Transaction &transaction, const char *name, Inode *inode); status_t InsertName(Transaction& transaction,
status_t RemoveName(Transaction &transaction, const char *name, Inode *inode); const char* name, Inode* inode);
status_t UpdateName(Transaction &transaction, const char *oldName, const char *newName, status_t RemoveName(Transaction& transaction,
const char* name, Inode* inode);
status_t UpdateName(Transaction& transaction,
const char* oldName, const char* newName,
Inode* inode); Inode* inode);
status_t InsertSize(Transaction& transaction, Inode* inode); status_t InsertSize(Transaction& transaction, Inode* inode);
status_t RemoveSize(Transaction& transaction, Inode* inode); status_t RemoveSize(Transaction& transaction, Inode* inode);
status_t UpdateSize(Transaction& transaction, Inode* inode); status_t UpdateSize(Transaction& transaction, Inode* inode);
status_t InsertLastModified(Transaction &transaction, Inode *inode); status_t InsertLastModified(Transaction& transaction,
status_t RemoveLastModified(Transaction &transaction, Inode *inode); Inode* inode);
status_t UpdateLastModified(Transaction &transaction, Inode *inode, off_t modified = -1); status_t RemoveLastModified(Transaction& transaction,
Inode* inode);
status_t UpdateLastModified(Transaction& transaction,
Inode* inode, off_t modified = -1);
private: private:
Index(const Index &); Index(const Index& other);
Index &operator=(const Index &); Index& operator=(const Index& other);
// no implementation // no implementation
Volume* fVolume; Volume* fVolume;
@@ -54,4 +63,4 @@ class Index {
const char* fName; const char* fName;
}; };
#endif /* INDEX_H */ #endif // INDEX_H
@@ -52,7 +52,6 @@ class Create : public AbstractTraceEntry {
int32 fMode; int32 fMode;
int fOpenMode; int fOpenMode;
uint32 fType; uint32 fType;
}; };
class Remove : public AbstractTraceEntry { class Remove : public AbstractTraceEntry {
@@ -138,13 +137,15 @@ class InodeAllocator {
InodeAllocator(Transaction& transaction); InodeAllocator(Transaction& transaction);
~InodeAllocator(); ~InodeAllocator();
status_t New(block_run *parentRun, mode_t mode, block_run &run, status_t New(block_run* parentRun, mode_t mode,
fs_vnode_ops *vnodeOps, Inode **_inode); block_run& run, fs_vnode_ops* vnodeOps,
Inode** _inode);
status_t CreateTree(); status_t CreateTree();
status_t Keep(fs_vnode_ops* vnodeOps, uint32 publishFlags); status_t Keep(fs_vnode_ops* vnodeOps, uint32 publishFlags);
private: private:
static void _TransactionListener(int32 id, int32 event, void *_inode); static void _TransactionListener(int32 id, int32 event,
void* _inode);
Transaction* fTransaction; Transaction* fTransaction;
block_run fRun; block_run fRun;
@@ -455,7 +456,7 @@ Inode::CheckPermissions(int accessMode) const
gid_t group = getegid(); gid_t group = getegid();
// you never have write access to a read-only volume // you never have write access to a read-only volume
if (accessMode & W_OK && fVolume->IsReadOnly()) if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly())
return B_READ_ONLY_DEVICE; return B_READ_ONLY_DEVICE;
// root users always have full access (but they can't execute files without // root users always have full access (but they can't execute files without
@@ -511,7 +512,8 @@ Inode::_MakeSpaceForSmallData(Transaction &transaction, bfs_inode *node,
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock); ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
while (bytes > 0) { while (bytes > 0) {
small_data *item = node->SmallDataStart(), *max = NULL; small_data* item = node->SmallDataStart();
small_data* max = NULL;
int32 index = 0, maxIndex = 0; int32 index = 0, maxIndex = 0;
for (; !item->IsLast(node); item = item->Next(), index++) { for (; !item->IsLast(node); item = item->Next(), index++) {
// should not remove those // should not remove those
@@ -43,7 +43,8 @@ class RunArrays {
int32 CountArrays() const { return fArrays.CountItems(); } int32 CountArrays() const { return fArrays.CountItems(); }
uint32 CountBlocks() const { return fBlockCount; } uint32 CountBlocks() const { return fBlockCount; }
uint32 LogEntryLength() const { return CountBlocks() + CountArrays(); } uint32 LogEntryLength() const
{ return CountBlocks() + CountArrays(); }
int32 MaxArrayLength(); int32 MaxArrayLength();
@@ -60,7 +61,8 @@ class RunArrays {
class LogEntry : public DoublyLinkedListLinkImpl<LogEntry> { class LogEntry : public DoublyLinkedListLinkImpl<LogEntry> {
public: public:
LogEntry(Journal *journal, uint32 logStart, uint32 length); LogEntry(Journal* journal, uint32 logStart,
uint32 length);
~LogEntry(); ~LogEntry();
uint32 Start() const { return fStart; } uint32 Start() const { return fStart; }
+9 -19
View File
@@ -8,10 +8,6 @@
#include "system_dependencies.h" #include "system_dependencies.h"
#ifndef _IMPEXP_KERNEL
# define _IMPEXP_KERNEL
#endif
#include "Volume.h" #include "Volume.h"
#include "Utility.h" #include "Utility.h"
@@ -23,17 +19,9 @@ typedef DoublyLinkedList<LogEntry> LogEntryList;
typedef SinglyLinkedList<Inode> InodeList; typedef SinglyLinkedList<Inode> InodeList;
// Locking policy in BFS: if you need both, the volume lock and the
// journal lock, you must lock the volume first - or else you will
// end up in a deadlock.
// That is, if you start a transaction, and will need to lock the
// volume while the transaction is in progress (for the unsafe
// get_vnode() call, for example), you must lock the volume before
// starting the transaction.
class Journal { class Journal {
public: public:
Journal(Volume *); Journal(Volume* volume);
~Journal(); ~Journal();
status_t InitCheck(); status_t InitCheck();
@@ -64,15 +52,17 @@ class Journal {
status_t _ReplayRunArray(int32* start); status_t _ReplayRunArray(int32* start);
status_t _TransactionDone(bool success); status_t _TransactionDone(bool success);
static void _TransactionWritten(int32 transactionID, int32 event, static void _TransactionWritten(int32 transactionID,
void *_logEntry); int32 event, void* _logEntry);
static void _TransactionIdle(int32 transactionID, int32 event, static void _TransactionIdle(int32 transactionID, int32 event,
void* _journal); void* _journal);
Volume* fVolume; Volume* fVolume;
recursive_lock fLock; recursive_lock fLock;
Transaction* fOwner; Transaction* fOwner;
uint32 fLogSize, fMaxTransactionSize, fUsed; uint32 fLogSize;
uint32 fMaxTransactionSize;
uint32 fUsed;
int32 fUnwrittenTransactions; int32 fUnwrittenTransactions;
mutex fEntriesLock; mutex fEntriesLock;
LogEntryList fEntries; LogEntryList fEntries;
@@ -177,8 +167,8 @@ class Transaction {
void AddInode(Inode* inode); void AddInode(Inode* inode);
private: private:
Transaction(const Transaction &); Transaction(const Transaction& other);
Transaction &operator=(const Transaction &); Transaction& operator=(const Transaction& other);
// no implementation // no implementation
void _UnlockInodes(); void _UnlockInodes();
@@ -191,4 +181,4 @@ class Transaction {
int dump_journal(int argc, char** argv); int dump_journal(int argc, char** argv);
#endif #endif
#endif /* JOURNAL_H */ #endif // JOURNAL_H
@@ -61,7 +61,8 @@ sorted_array::Remove(off_t value)
return false; return false;
count--; count--;
memmove(&values[index], &values[index + 1], (count - index) * sizeof(off_t)); memmove(&values[index], &values[index + 1],
(count - index) * sizeof(off_t));
return true; return true;
} }
@@ -13,7 +13,6 @@
// TODO: this is not endian safe!!! // TODO: this is not endian safe!!!
struct sorted_array { struct sorted_array {
public:
off_t count; off_t count;
off_t values[0]; off_t values[0];
+39 -20
View File
@@ -53,23 +53,34 @@ class Volume {
fs_volume* FSVolume() const { return fVolume; } fs_volume* FSVolume() const { return fVolume; }
const char* Name() const { return fSuperBlock.name; } const char* Name() const { return fSuperBlock.name; }
off_t NumBlocks() const { return fSuperBlock.NumBlocks(); } off_t NumBlocks() const
off_t UsedBlocks() const { return fSuperBlock.UsedBlocks(); } { return fSuperBlock.NumBlocks(); }
off_t FreeBlocks() const { return NumBlocks() - UsedBlocks(); } off_t UsedBlocks() const
{ return fSuperBlock.UsedBlocks(); }
off_t FreeBlocks() const
{ return NumBlocks() - UsedBlocks(); }
uint32 BlockSize() const { return fBlockSize; } uint32 BlockSize() const { return fBlockSize; }
uint32 BlockShift() const { return fBlockShift; } uint32 BlockShift() const { return fBlockShift; }
uint32 InodeSize() const { return fSuperBlock.InodeSize(); } uint32 InodeSize() const
uint32 AllocationGroups() const { return fSuperBlock.AllocationGroups(); } { return fSuperBlock.InodeSize(); }
uint32 AllocationGroupShift() const { return fAllocationGroupShift; } uint32 AllocationGroups() const
{ return fSuperBlock.AllocationGroups(); }
uint32 AllocationGroupShift() const
{ return fAllocationGroupShift; }
disk_super_block& SuperBlock() { return fSuperBlock; } disk_super_block& SuperBlock() { return fSuperBlock; }
off_t ToOffset(block_run run) const { return ToBlock(run) << BlockShift(); } off_t ToOffset(block_run run) const
off_t ToBlock(block_run run) const { return ((((off_t)run.AllocationGroup()) << AllocationGroupShift()) | (off_t)run.Start()); } { return ToBlock(run) << BlockShift(); }
off_t ToBlock(block_run run) const
{ return ((((off_t)run.AllocationGroup())
<< AllocationGroupShift())
| (off_t)run.Start()); }
block_run ToBlockRun(off_t block) const; block_run ToBlockRun(off_t block) const;
status_t ValidateBlockRun(block_run run); status_t ValidateBlockRun(block_run run);
off_t ToVnode(block_run run) const { return ToBlock(run); } off_t ToVnode(block_run run) const
{ return ToBlock(run); }
off_t ToVnode(off_t block) const { return block; } off_t ToVnode(off_t block) const { return block; }
off_t VnodeToBlock(ino_t id) const { return (off_t)id; } off_t VnodeToBlock(ino_t id) const { return (off_t)id; }
@@ -77,12 +88,15 @@ class Volume {
// block bitmap // block bitmap
BlockAllocator& Allocator(); BlockAllocator& Allocator();
status_t AllocateForInode(Transaction &transaction, const Inode *parent, status_t AllocateForInode(Transaction& transaction,
mode_t type, block_run &run); const Inode* parent, mode_t type,
status_t AllocateForInode(Transaction &transaction, const block_run *parent, block_run& run);
mode_t type, block_run &run); status_t AllocateForInode(Transaction& transaction,
const block_run* parent, mode_t type,
block_run& run);
status_t Allocate(Transaction& transaction, Inode* inode, status_t Allocate(Transaction& transaction, Inode* inode,
off_t numBlocks, block_run &run, uint16 minimum = 1); off_t numBlocks, block_run& run,
uint16 minimum = 1);
status_t Free(Transaction& transaction, block_run run); status_t Free(Transaction& transaction, block_run run);
// cache access // cache access
@@ -90,7 +104,8 @@ class Volume {
status_t FlushDevice(); status_t FlushDevice();
// queries // queries
void UpdateLiveQueries(Inode *inode, const char *attribute, int32 type, void UpdateLiveQueries(Inode* inode,
const char* attribute, int32 type,
const uint8* oldKey, size_t oldLength, const uint8* oldKey, size_t oldLength,
const uint8* newKey, size_t newLength); const uint8* newKey, size_t newLength);
bool CheckForLiveQuery(const char* attribute); bool CheckForLiveQuery(const char* attribute);
@@ -120,7 +135,8 @@ class Volume {
BlockAllocator fBlockAllocator; BlockAllocator fBlockAllocator;
mutex fLock; mutex fLock;
Journal* fJournal; Journal* fJournal;
vint32 fLogStart, fLogEnd; vint32 fLogStart;
vint32 fLogEnd;
Inode* fRootNode; Inode* fRootNode;
Inode* fIndicesNode; Inode* fIndicesNode;
@@ -161,16 +177,19 @@ Volume::Allocator()
inline status_t inline status_t
Volume::AllocateForInode(Transaction &transaction, const block_run *parent, mode_t type, block_run &run) Volume::AllocateForInode(Transaction& transaction, const block_run* parent,
mode_t type, block_run& run)
{ {
return fBlockAllocator.AllocateForInode(transaction, parent, type, run); return fBlockAllocator.AllocateForInode(transaction, parent, type, run);
} }
inline status_t inline status_t
Volume::Allocate(Transaction &transaction, Inode *inode, off_t numBlocks, block_run &run, uint16 minimum) Volume::Allocate(Transaction& transaction, Inode* inode, off_t numBlocks,
block_run& run, uint16 minimum)
{ {
return fBlockAllocator.Allocate(transaction, inode, numBlocks, run, minimum); return fBlockAllocator.Allocate(transaction, inode, numBlocks, run,
minimum);
} }
@@ -201,4 +220,4 @@ Volume::GetUniqueID()
return atomic_add(&fUniqueID, 1); return atomic_add(&fUniqueID, 1);
} }
#endif /* VOLUME_H */ #endif // VOLUME_H
@@ -1354,9 +1354,7 @@ bfs_read_link(fs_volume *_volume, fs_vnode *_node, char *buffer,
if (linkLen < *_bufferSize) if (linkLen < *_bufferSize)
*_bufferSize = linkLen; *_bufferSize = linkLen;
memcpy(buffer, inode->Node().short_symlink, *_bufferSize); return user_memcpy(buffer, inode->Node().short_symlink, *_bufferSize);
return B_OK;
} }