xfs: make Directory Iterator class an abstract class

Directory Iterator class represents one instance which could be Short, Extent, Leaf, Node or B+Tree, a good case for making it an abstract class

Change-Id: I925255caf4c4f8bc01a975740ef2ebf0bb2e1b49
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5764
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
Mashijams 2022-10-25 18:33:19 +05:30 committed by waddlesplash
parent 6610656e8f
commit 62a64d0a43
8 changed files with 85 additions and 170 deletions

View File

@ -6,6 +6,7 @@
#define _BPLUS_TREE_H_
#include "Directory.h"
#include "Extent.h"
#include "Inode.h"
#include "LeafDirectory.h"
@ -102,7 +103,7 @@ struct PathNode {
/*
* This class should handle B+Tree based directories
*/
class TreeDirectory {
class TreeDirectory : public DirectoryIterator {
public:
TreeDirectory(Inode* inode);
~TreeDirectory();

View File

@ -4,147 +4,84 @@
*/
#include "BPlusTree.h"
#include "Directory.h"
DirectoryIterator::DirectoryIterator(Inode* inode)
:
fInode(inode),
fShortDir(NULL),
fExtentDir(NULL),
fLeafDir(NULL),
fNodeDir(NULL),
fTreeDir(NULL)
{
}
#include "Extent.h"
#include "LeafDirectory.h"
#include "Node.h"
#include "ShortDirectory.h"
DirectoryIterator::~DirectoryIterator()
{
delete fShortDir;
delete fLeafDir;
delete fExtentDir;
delete fNodeDir;
delete fTreeDir;
}
status_t
DirectoryIterator::Init()
DirectoryIterator*
DirectoryIterator::Init(Inode* inode)
{
if (fInode->Format() == XFS_DINODE_FMT_LOCAL)
{
if (inode->Format() == XFS_DINODE_FMT_LOCAL) {
TRACE("Iterator:Init: LOCAL");
fShortDir = new(std::nothrow) ShortDirectory(fInode);
if (fShortDir == NULL)
return B_NO_MEMORY;
return B_OK;
ShortDirectory* shortDir = new(std::nothrow) ShortDirectory(inode);
return shortDir;
}
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
if (inode->Format() == XFS_DINODE_FMT_EXTENTS) {
TRACE("Iterator:Init: EXTENTS");
fExtentDir = new(std::nothrow) Extent(fInode);
if (fExtentDir == NULL)
return B_NO_MEMORY;
if (fExtentDir->IsBlockType())
return fExtentDir->Init();
status_t status;
delete fExtentDir;
fExtentDir = NULL;
// Check if it is extent based directory
Extent* extentDir = new(std::nothrow) Extent(inode);
if (extentDir == NULL)
return NULL;
fLeafDir = new(std::nothrow) LeafDirectory(fInode);
if (fLeafDir == NULL)
return B_NO_MEMORY;
if (fLeafDir->IsLeafType())
return fLeafDir->Init();
delete fLeafDir;
fLeafDir = NULL;
if (extentDir->IsBlockType()) {
status = extentDir->Init();
if (status == B_OK)
return extentDir;
}
fNodeDir = new(std::nothrow) NodeDirectory(fInode);
if (fNodeDir == NULL)
return B_NO_MEMORY;
if (fNodeDir->IsNodeType())
return fNodeDir->Init();
delete fNodeDir;
fNodeDir = NULL;
delete extentDir;
// Check if it is leaf based directory
LeafDirectory* leafDir = new(std::nothrow) LeafDirectory(inode);
if (leafDir == NULL)
return NULL;
if (leafDir->IsLeafType()) {
status = leafDir->Init();
if (status == B_OK)
return leafDir;
}
delete leafDir;
// Check if it is node based directory
NodeDirectory* nodeDir = new(std::nothrow) NodeDirectory(inode);
if (nodeDir == NULL)
return NULL;
if (nodeDir->IsNodeType()) {
status = nodeDir->Init();
if (status == B_OK)
return nodeDir;
}
delete nodeDir;
}
/* Return B_OK so even if the shortform directory has an extent directory
* we can atleast still list the shortform directory
*/
if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
if (inode->Format() == XFS_DINODE_FMT_BTREE) {
TRACE("Iterator:Init(): B+TREE");
fTreeDir = new(std::nothrow) TreeDirectory(fInode);
if (fTreeDir == NULL)
return B_NO_MEMORY;
return fTreeDir->InitCheck();
TreeDirectory* treeDir = new(std::nothrow) TreeDirectory(inode);
if (treeDir == NULL)
return NULL;
status_t status = treeDir->InitCheck();
if (status == B_OK)
return treeDir;
}
return B_BAD_VALUE;
}
status_t
DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino)
{
status_t status;
if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
TRACE("Iterator:GetNext: LOCAL");
status = fShortDir->GetNext(name, length, ino);
return status;
}
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
TRACE("Iterator:GetNext: EXTENTS");
if (fExtentDir != NULL)
status = fExtentDir->GetNext(name, length, ino);
else if (fLeafDir != NULL)
status = fLeafDir->GetNext(name, length, ino);
else
status = fNodeDir->GetNext(name, length, ino);
return status;
}
if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
TRACE("Iterator:GetNext: B+TREE");
if (fTreeDir != NULL)
return status = fTreeDir->GetNext(name, length, ino);
return B_NOT_SUPPORTED;
}
// Only reaches here if Inode is a device or is corrupt.
return B_BAD_VALUE;
}
status_t
DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino)
{
status_t status;
if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
TRACE("Iterator:Lookup: LOCAL\n");
status = fShortDir->Lookup(name, length, ino);
return status;
}
//TODO: Reading from extent based dirs
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
TRACE("Iterator:Lookup: EXTENTS\n");
if (fExtentDir != NULL)
status = fExtentDir->Lookup(name, length, ino);
else if (fLeafDir != NULL)
status = fLeafDir->Lookup(name, length, ino);
else
status = fNodeDir->Lookup(name, length, ino);
return status;
}
//TODO: Reading from B+Tree based dirs
if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
TRACE("Iterator:Lookup: B+TREE\n");
if (fTreeDir != NULL)
return fTreeDir->Lookup(name, length, ino);
return B_NOT_SUPPORTED;
}
return B_BAD_VALUE;
}
// Invalid format return NULL
return NULL;
}

View File

@ -6,12 +6,7 @@
#define _DIRECTORY_H_
#include "BPlusTree.h"
#include "Extent.h"
#include "Inode.h"
#include "LeafDirectory.h"
#include "Node.h"
#include "ShortDirectory.h"
/*
@ -20,26 +15,15 @@
*/
class DirectoryIterator {
public:
DirectoryIterator(Inode* inode);
~DirectoryIterator();
status_t Init();
bool IsLocalDir() { return fInode->IsLocal(); }
status_t GetNext(char* name, size_t* length,
xfs_ino_t* ino);
status_t Lookup(const char* name, size_t length,
xfs_ino_t* id);
virtual ~DirectoryIterator() = 0;
private:
Inode* fInode;
ShortDirectory* fShortDir;
// Short form Directory type
Extent* fExtentDir;
// Extent form Directory type
// TODO: Rename all to block type
LeafDirectory* fLeafDir;
// Extent based leaf directory
NodeDirectory* fNodeDir;
TreeDirectory* fTreeDir;
virtual status_t GetNext(char* name, size_t* length,
xfs_ino_t* ino) = 0;
virtual status_t Lookup(const char* name, size_t length,
xfs_ino_t* id) = 0;
static DirectoryIterator* Init(Inode* inode);
};

View File

@ -7,6 +7,7 @@
#define _EXTENT_H_
#include "Directory.h"
#include "Inode.h"
#include "system_dependencies.h"
@ -152,8 +153,7 @@ struct ExtentBlockTail {
};
class Extent
{
class Extent : public DirectoryIterator {
public:
Extent(Inode* inode);
~Extent();

View File

@ -7,6 +7,7 @@
#define _LEAFDIRECTORY_H_
#include "Directory.h"
#include "Extent.h"
#include "Inode.h"
#include "system_dependencies.h"
@ -99,7 +100,7 @@ struct ExtentLeafTail {
};
class LeafDirectory {
class LeafDirectory : public DirectoryIterator {
public:
LeafDirectory(Inode* inode);
~LeafDirectory();

View File

@ -6,6 +6,7 @@
#define _NODE_H_
#include "Directory.h"
#include "Extent.h"
#include "LeafDirectory.h"
@ -87,7 +88,7 @@ struct NodeEntry {
};
class NodeDirectory {
class NodeDirectory : public DirectoryIterator {
public:
NodeDirectory(Inode* inode);
~NodeDirectory();

View File

@ -6,6 +6,7 @@
#define __SHORT_DIR_H__
#include "Directory.h"
#include "Inode.h"
@ -50,8 +51,7 @@ struct ShortFormEntry {
} __attribute__((packed));
class ShortDirectory
{
class ShortDirectory : public DirectoryIterator {
public:
ShortDirectory(Inode* inode);
~ShortDirectory();

View File

@ -205,16 +205,9 @@ xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
if (status < B_OK)
return status;
DirectoryIterator* iterator =
new(std::nothrow) DirectoryIterator(directory);
DirectoryIterator* iterator = DirectoryIterator::Init(directory);
if (iterator == NULL)
return B_NO_MEMORY;
status = iterator->Init();
if (status != B_OK) {
delete iterator;
return status;
}
return B_BAD_VALUE;
status = iterator->Lookup(name, strlen(name), (xfs_ino_t*)_vnodeID);
if (status != B_OK) {
@ -407,12 +400,10 @@ xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie)
if (!inode->IsDirectory())
return B_NOT_A_DIRECTORY;
DirectoryIterator* iterator = new(std::nothrow) DirectoryIterator(inode);
if (iterator == NULL) {
delete iterator;
return B_NO_MEMORY;
}
status = iterator->Init();
DirectoryIterator* iterator = DirectoryIterator::Init(inode);
if (iterator == NULL)
return B_BAD_VALUE;
*_cookie = iterator;
return status;
}