BTRFS: Reimplement TreeIterator, add some error checks and remove redundancies.
Add BTree::Path as a attribute so enhance performance, so that everytime we iterate through items it wont search all the root to leaf again. The Iterator is initialized without rewinding to make more flexible. Signed-off-by: Augustin Cavalier <[email protected]>
This commit is contained in:
@@ -22,9 +22,10 @@ AttributeIterator::AttributeIterator(Inode* inode)
|
||||
fInode(inode),
|
||||
fIterator(NULL)
|
||||
{
|
||||
struct btrfs_key key;
|
||||
btrfs_key key;
|
||||
key.SetType(BTRFS_KEY_TYPE_XATTR_ITEM);
|
||||
key.SetObjectID(inode->ID());
|
||||
key.SetOffset(BTREE_BEGIN);
|
||||
fIterator = new(std::nothrow) TreeIterator(inode->GetVolume()->FSTree(),
|
||||
key);
|
||||
}
|
||||
@@ -33,6 +34,7 @@ AttributeIterator::AttributeIterator(Inode* inode)
|
||||
AttributeIterator::~AttributeIterator()
|
||||
{
|
||||
delete fIterator;
|
||||
fIterator = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +48,9 @@ AttributeIterator::InitCheck()
|
||||
status_t
|
||||
AttributeIterator::GetNext(char* name, size_t* _nameLength)
|
||||
{
|
||||
btrfs_key key;
|
||||
btrfs_dir_entry* entries;
|
||||
uint32 entries_length;
|
||||
status_t status = fIterator->GetPreviousEntry(key, (void**)&entries,
|
||||
status_t status = fIterator->GetPreviousEntry((void**)&entries,
|
||||
&entries_length);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
@@ -519,13 +519,16 @@ BTree::_RemoveIterator(TreeIterator* iterator)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
TreeIterator::TreeIterator(BTree* tree, btrfs_key& key)
|
||||
TreeIterator::TreeIterator(BTree* tree, const btrfs_key& key)
|
||||
:
|
||||
fTree(tree),
|
||||
fCurrentKey(key)
|
||||
fKey(key),
|
||||
fIteratorStatus(B_NO_INIT)
|
||||
{
|
||||
Rewind();
|
||||
tree->_AddIterator(this);
|
||||
fPath = new(std::nothrow) BTree::Path(tree);
|
||||
if (fPath == NULL)
|
||||
fIteratorStatus = B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
@@ -533,26 +536,72 @@ TreeIterator::~TreeIterator()
|
||||
{
|
||||
if (fTree)
|
||||
fTree->_RemoveIterator(this);
|
||||
|
||||
delete fPath;
|
||||
fPath = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TreeIterator::Rewind(bool inverse)
|
||||
{
|
||||
if (inverse)
|
||||
fKey.SetOffset(BTREE_END);
|
||||
else
|
||||
fKey.SetOffset(BTREE_BEGIN);
|
||||
fIteratorStatus = B_NO_INIT;
|
||||
}
|
||||
|
||||
|
||||
/*! Iterates through the tree in the specified direction.
|
||||
*/
|
||||
status_t
|
||||
TreeIterator::Traverse(btree_traversing direction, btrfs_key& key,
|
||||
void** value, uint32* size)
|
||||
TreeIterator::_Traverse(btree_traversing direction)
|
||||
{
|
||||
if (fTree == NULL)
|
||||
return B_INTERRUPTED;
|
||||
|
||||
fCurrentKey.SetOffset(fCurrentKey.Offset() + direction);
|
||||
BTree::Path path(fTree);
|
||||
status_t status = fTree->_Find(&path, fCurrentKey, value, size, direction);
|
||||
if (status != B_OK) {
|
||||
TRACE("TreeIterator::Traverse() Find failed\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
status_t status = fTree->Traverse(direction, fPath, fKey);
|
||||
if (status < B_OK) {
|
||||
ERROR("TreeIterator::Traverse() Find failed\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
return (fIteratorStatus = B_OK);
|
||||
}
|
||||
|
||||
|
||||
// Like GetEntry in BTree::Path but here we check the type and moving.
|
||||
status_t
|
||||
TreeIterator::_GetEntry(btree_traversing type, void** _value, uint32* _size,
|
||||
uint32* _offset)
|
||||
{
|
||||
status_t status;
|
||||
if (fIteratorStatus == B_NO_INIT) {
|
||||
status = _Traverse(type);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
type = BTREE_EXACT;
|
||||
}
|
||||
|
||||
if (fIteratorStatus != B_OK)
|
||||
return fIteratorStatus;
|
||||
|
||||
int move = fPath->Move(0, type);
|
||||
if (move > 0)
|
||||
status = fTree->NextLeaf(fPath);
|
||||
else if (move < 0)
|
||||
status = fTree->PreviousLeaf(fPath);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
btrfs_key found;
|
||||
status = fPath->GetCurrentEntry(&found, _value, _size, _offset);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
fKey.SetObjectID(found.ObjectID());
|
||||
fKey.SetOffset(found.Offset());
|
||||
if (fKey.Type() != found.Type() && fKey.Type() != BTRFS_KEY_TYPE_ANY)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -560,11 +609,13 @@ TreeIterator::Traverse(btree_traversing direction, btrfs_key& key,
|
||||
/*! just sets the current key in the iterator.
|
||||
*/
|
||||
status_t
|
||||
TreeIterator::Find(btrfs_key& key)
|
||||
TreeIterator::Find(const btrfs_key& key)
|
||||
{
|
||||
if (fTree == NULL)
|
||||
return B_INTERRUPTED;
|
||||
fCurrentKey = key;
|
||||
if (fIteratorStatus == B_INTERRUPTED)
|
||||
return fIteratorStatus;
|
||||
|
||||
fKey = key;
|
||||
fIteratorStatus = B_NO_INIT;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -573,4 +624,5 @@ void
|
||||
TreeIterator::Stop()
|
||||
{
|
||||
fTree = NULL;
|
||||
fIteratorStatus = B_INTERRUPTED;
|
||||
}
|
||||
|
||||
@@ -176,31 +176,37 @@ public:
|
||||
|
||||
class TreeIterator : public SinglyLinkedListLinkImpl<TreeIterator> {
|
||||
public:
|
||||
TreeIterator(BTree* tree, btrfs_key& key);
|
||||
TreeIterator(BTree* tree, const btrfs_key& key);
|
||||
~TreeIterator();
|
||||
|
||||
status_t Traverse(btree_traversing direction,
|
||||
btrfs_key& key, void** value,
|
||||
uint32* size = NULL);
|
||||
status_t Find(btrfs_key& key);
|
||||
void Rewind(bool inverse = false);
|
||||
status_t Find(const btrfs_key& key);
|
||||
status_t GetNextEntry(void** _value,
|
||||
uint32* _size = NULL,
|
||||
uint32* _offset = NULL);
|
||||
status_t GetPreviousEntry(void** _value,
|
||||
uint32* _size = NULL,
|
||||
uint32* _offset = NULL);
|
||||
|
||||
status_t Rewind();
|
||||
status_t GetNextEntry(btrfs_key& key, void** value,
|
||||
uint32* size = NULL);
|
||||
status_t GetPreviousEntry(btrfs_key& key, void** value,
|
||||
uint32* size = NULL);
|
||||
|
||||
BTree* Tree() const { return fTree; }
|
||||
BTree* Tree() const { return fTree; }
|
||||
btrfs_key Key() const { return fKey; }
|
||||
|
||||
private:
|
||||
friend class BTree;
|
||||
|
||||
status_t _Traverse(btree_traversing direction);
|
||||
status_t _Find(btree_traversing type, btrfs_key& key,
|
||||
void** _value);
|
||||
status_t _GetEntry(btree_traversing type, void** _value,
|
||||
uint32* _size, uint32* _offset);
|
||||
// called by BTree
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
BTree* fTree;
|
||||
btrfs_key fCurrentKey;
|
||||
BTree::Path* fPath;
|
||||
btrfs_key fKey;
|
||||
status_t fIteratorStatus;
|
||||
};
|
||||
|
||||
|
||||
@@ -219,25 +225,16 @@ BTree::Path::GetCurrentEntry(btrfs_key* _key, void** _value, uint32* _size,
|
||||
|
||||
|
||||
inline status_t
|
||||
TreeIterator::Rewind()
|
||||
TreeIterator::GetNextEntry(void** _value, uint32* _size, uint32* _offset)
|
||||
{
|
||||
fCurrentKey.SetOffset(BTREE_BEGIN);
|
||||
return B_OK;
|
||||
return _GetEntry(BTREE_FORWARD, _value, _size, _offset);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
TreeIterator::GetNextEntry(btrfs_key& key, void** value, uint32* size)
|
||||
TreeIterator::GetPreviousEntry(void** _value, uint32* _size, uint32* _offset)
|
||||
{
|
||||
return Traverse(BTREE_FORWARD, key, value, size);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
TreeIterator::GetPreviousEntry(btrfs_key& key, void** value,
|
||||
uint32* size)
|
||||
{
|
||||
return Traverse(BTREE_BACKWARD, key, value, size);
|
||||
return _GetEntry(BTREE_BACKWARD, _value, _size, _offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ DirectoryIterator::DirectoryIterator(Inode* inode)
|
||||
btrfs_key key;
|
||||
key.SetType(BTRFS_KEY_TYPE_DIR_INDEX);
|
||||
key.SetObjectID(inode->ID());
|
||||
key.SetOffset(BTREE_BEGIN);
|
||||
fIterator = new(std::nothrow) TreeIterator(inode->GetVolume()->FSTree(),
|
||||
key);
|
||||
}
|
||||
@@ -33,8 +34,8 @@ DirectoryIterator::DirectoryIterator(Inode* inode)
|
||||
|
||||
DirectoryIterator::~DirectoryIterator()
|
||||
{
|
||||
if (fIterator != NULL)
|
||||
delete fIterator;
|
||||
delete fIterator;
|
||||
fIterator = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,11 +70,9 @@ DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
|
||||
return fInode->FindParent(_id);
|
||||
}
|
||||
|
||||
btrfs_key key;
|
||||
btrfs_dir_entry* entries;
|
||||
uint32 entries_length;
|
||||
status_t status = fIterator->GetNextEntry(key, (void**)&entries,
|
||||
&entries_length);
|
||||
status_t status = fIterator->GetNextEntry((void**)&entries, &entries_length);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user