From e58322127037e91a4190fb1fde4f60bff9970dae Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sat, 31 Aug 2019 12:25:39 -0400 Subject: [PATCH] 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. --- .../file_systems/ramfs/DirectoryEntryTable.h | 153 ++++++++++++++++++ src/add-ons/kernel/file_systems/ramfs/Entry.h | 3 + .../kernel/file_systems/ramfs/Volume.cpp | 8 +- 3 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/ramfs/DirectoryEntryTable.h diff --git a/src/add-ons/kernel/file_systems/ramfs/DirectoryEntryTable.h b/src/add-ons/kernel/file_systems/ramfs/DirectoryEntryTable.h new file mode 100644 index 0000000000..71ea63779e --- /dev/null +++ b/src/add-ons/kernel/file_systems/ramfs/DirectoryEntryTable.h @@ -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 + +#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 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 diff --git a/src/add-ons/kernel/file_systems/ramfs/Entry.h b/src/add-ons/kernel/file_systems/ramfs/Entry.h index 6e6ffbaf53..6fb55517e0 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Entry.h +++ b/src/add-ons/kernel/file_systems/ramfs/Entry.h @@ -24,6 +24,8 @@ public: status_t InitCheck() const; + Entry*& HashLink() { return fHashLink; } + inline void SetParent(Directory *parent) { fParent = parent; } Directory *GetParent() const { return fParent; } @@ -50,6 +52,7 @@ public: void GetAllocationInfo(AllocationInfo &info); private: + Entry *fHashLink; Directory *fParent; Node *fNode; String fName; diff --git a/src/add-ons/kernel/file_systems/ramfs/Volume.cpp b/src/add-ons/kernel/file_systems/ramfs/Volume.cpp index c1b374ff3b..95c0795598 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/Volume.cpp @@ -30,6 +30,7 @@ #include "BlockAllocator.h" #include "DebugSupport.h" #include "Directory.h" +#include "DirectoryEntryTable.h" #include "Entry.h" #include "EntryListener.h" #include "IndexDirectory.h" @@ -37,7 +38,6 @@ #include "Misc.h" #include "NameIndex.h" #include "Node.h" -#include "NodeChildTable.h" #include "NodeListener.h" #include "NodeTable.h" #include "TwoKeyAVLTree.h" @@ -535,7 +535,7 @@ Volume::EntryAdded(ino_t id, Entry *entry) { status_t error = (entry ? B_OK : B_BAD_VALUE); if (error == B_OK) { - error = fDirectoryEntryTable->AddNodeChild(id, entry); + error = fDirectoryEntryTable->AddEntry(id, entry); if (error == B_OK) { // notify listeners // 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); if (error == B_OK) { - error = fDirectoryEntryTable->RemoveNodeChild(id, entry); + error = fDirectoryEntryTable->RemoveEntry(id, entry); if (error == B_OK) { // notify listeners // 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); if (error == B_OK) { - *entry = fDirectoryEntryTable->GetNodeChild(id, name); + *entry = fDirectoryEntryTable->GetEntry(id, name); if (!*entry) error = B_ENTRY_NOT_FOUND; }