ramfs: Replace the NodeChildTable with a DirectoryEntryTable.
Now that Attributes don't use a table, we can replace the generic system with a specific DirectoryEntryTable, upgrading to BOpenHashTable in the process.
This commit is contained in:
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef DIRECTORY_ENTRY_TABLE_H
|
||||||
|
#define DIRECTORY_ENTRY_TABLE_H
|
||||||
|
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include "AllocationInfo.h"
|
||||||
|
#include "DebugSupport.h"
|
||||||
|
#include "Misc.h"
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
// DirectoryEntryHash
|
||||||
|
struct DirectoryEntryHash {
|
||||||
|
struct Key {
|
||||||
|
ino_t id;
|
||||||
|
const char* name;
|
||||||
|
|
||||||
|
Key(ino_t i, const char* n) : id(i), name(n) {}
|
||||||
|
};
|
||||||
|
typedef Key KeyType;
|
||||||
|
typedef Entry ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(KeyType key) const
|
||||||
|
{
|
||||||
|
return node_child_hash(key.id, key.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(ValueType* value) const
|
||||||
|
{
|
||||||
|
return HashKey(Key(value->GetParent()->GetID(), value->GetName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(KeyType key, ValueType* value) const
|
||||||
|
{
|
||||||
|
return (value->GetParent()->GetID() == key.id
|
||||||
|
&& !strcmp(value->GetName(), key.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType*& GetLink(ValueType* value) const
|
||||||
|
{
|
||||||
|
return value->HashLink();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// DirectoryEntryTable
|
||||||
|
class DirectoryEntryTable {
|
||||||
|
public:
|
||||||
|
DirectoryEntryTable();
|
||||||
|
~DirectoryEntryTable();
|
||||||
|
|
||||||
|
status_t InitCheck() const;
|
||||||
|
|
||||||
|
status_t AddEntry(Directory *node, Entry *child);
|
||||||
|
status_t AddEntry(ino_t, Entry *child);
|
||||||
|
status_t RemoveEntry(Directory *node, Entry *child);
|
||||||
|
status_t RemoveEntry(ino_t id, Entry *child);
|
||||||
|
status_t RemoveEntry(ino_t id, const char *name);
|
||||||
|
Entry *GetEntry(ino_t id, const char *name);
|
||||||
|
|
||||||
|
void GetAllocationInfo(AllocationInfo &info)
|
||||||
|
{
|
||||||
|
info.AddDirectoryEntryTableAllocation(0, fTable.TableSize(),
|
||||||
|
sizeof(void*), fTable.CountElements());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BOpenHashTable<DirectoryEntryHash> fTable;
|
||||||
|
status_t fInitStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
DirectoryEntryTable::DirectoryEntryTable()
|
||||||
|
{
|
||||||
|
fInitStatus = fTable.Init(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
DirectoryEntryTable::~DirectoryEntryTable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitCheck
|
||||||
|
status_t
|
||||||
|
DirectoryEntryTable::InitCheck() const
|
||||||
|
{
|
||||||
|
RETURN_ERROR(fInitStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEntry
|
||||||
|
status_t
|
||||||
|
DirectoryEntryTable::AddEntry(Directory *node, Entry *child)
|
||||||
|
{
|
||||||
|
status_t error = (node && child ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = AddEntry(node->GetID(), child);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEntry
|
||||||
|
status_t
|
||||||
|
DirectoryEntryTable::AddEntry(ino_t id, Entry *child)
|
||||||
|
{
|
||||||
|
status_t error = (child ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK) {
|
||||||
|
RemoveEntry(id, child);
|
||||||
|
SET_ERROR(error, fTable.Insert(child));
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEntry
|
||||||
|
status_t
|
||||||
|
DirectoryEntryTable::RemoveEntry(Directory *node, Entry *child)
|
||||||
|
{
|
||||||
|
status_t error = (node && child ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = RemoveEntry(node->GetID(), child->GetName());
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEntry
|
||||||
|
status_t
|
||||||
|
DirectoryEntryTable::RemoveEntry(ino_t id, Entry *child)
|
||||||
|
{
|
||||||
|
status_t error = (child ? B_OK : B_BAD_VALUE);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = RemoveEntry(id, child->GetName());
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEntry
|
||||||
|
status_t
|
||||||
|
DirectoryEntryTable::RemoveEntry(ino_t id, const char *name)
|
||||||
|
{
|
||||||
|
Entry* child = fTable.Lookup(typename DirectoryEntryHash::Key(id, name));
|
||||||
|
if (!child)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
status_t error = fTable.Remove(child);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEntry
|
||||||
|
Entry *
|
||||||
|
DirectoryEntryTable::GetEntry(ino_t id, const char *name)
|
||||||
|
{
|
||||||
|
Entry *child = fTable.Lookup(typename DirectoryEntryHash::Key(id, name));
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DIRECTORY_ENTRY_TABLE_H
|
||||||
@@ -24,6 +24,8 @@ public:
|
|||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|
||||||
|
Entry*& HashLink() { return fHashLink; }
|
||||||
|
|
||||||
inline void SetParent(Directory *parent) { fParent = parent; }
|
inline void SetParent(Directory *parent) { fParent = parent; }
|
||||||
Directory *GetParent() const { return fParent; }
|
Directory *GetParent() const { return fParent; }
|
||||||
|
|
||||||
@@ -50,6 +52,7 @@ public:
|
|||||||
void GetAllocationInfo(AllocationInfo &info);
|
void GetAllocationInfo(AllocationInfo &info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Entry *fHashLink;
|
||||||
Directory *fParent;
|
Directory *fParent;
|
||||||
Node *fNode;
|
Node *fNode;
|
||||||
String fName;
|
String fName;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "BlockAllocator.h"
|
#include "BlockAllocator.h"
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
|
#include "DirectoryEntryTable.h"
|
||||||
#include "Entry.h"
|
#include "Entry.h"
|
||||||
#include "EntryListener.h"
|
#include "EntryListener.h"
|
||||||
#include "IndexDirectory.h"
|
#include "IndexDirectory.h"
|
||||||
@@ -37,7 +38,6 @@
|
|||||||
#include "Misc.h"
|
#include "Misc.h"
|
||||||
#include "NameIndex.h"
|
#include "NameIndex.h"
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
#include "NodeChildTable.h"
|
|
||||||
#include "NodeListener.h"
|
#include "NodeListener.h"
|
||||||
#include "NodeTable.h"
|
#include "NodeTable.h"
|
||||||
#include "TwoKeyAVLTree.h"
|
#include "TwoKeyAVLTree.h"
|
||||||
@@ -535,7 +535,7 @@ Volume::EntryAdded(ino_t id, Entry *entry)
|
|||||||
{
|
{
|
||||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
error = fDirectoryEntryTable->AddNodeChild(id, entry);
|
error = fDirectoryEntryTable->AddEntry(id, entry);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
// notify listeners
|
// notify listeners
|
||||||
// listeners interested in that entry
|
// listeners interested in that entry
|
||||||
@@ -566,7 +566,7 @@ Volume::EntryRemoved(ino_t id, Entry *entry)
|
|||||||
{
|
{
|
||||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
error = fDirectoryEntryTable->RemoveNodeChild(id, entry);
|
error = fDirectoryEntryTable->RemoveEntry(id, entry);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
// notify listeners
|
// notify listeners
|
||||||
// listeners interested in that entry
|
// listeners interested in that entry
|
||||||
@@ -597,7 +597,7 @@ Volume::FindEntry(ino_t id, const char *name, Entry **entry)
|
|||||||
{
|
{
|
||||||
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
status_t error = (entry ? B_OK : B_BAD_VALUE);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
*entry = fDirectoryEntryTable->GetNodeChild(id, name);
|
*entry = fDirectoryEntryTable->GetEntry(id, name);
|
||||||
if (!*entry)
|
if (!*entry)
|
||||||
error = B_ENTRY_NOT_FOUND;
|
error = B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user