1/* 2 * Copyright 2019, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 */ 5#ifndef DIRECTORY_ENTRY_TABLE_H 6#define DIRECTORY_ENTRY_TABLE_H 7 8#include <util/OpenHashTable.h> 9 10#include "AllocationInfo.h" 11#include "DebugSupport.h" 12#include "Misc.h" 13#include "Node.h" 14 15// DirectoryEntryHash 16struct DirectoryEntryHash { 17 struct Key { 18 ino_t id; 19 const char* name; 20 21 Key(ino_t i, const char* n) : id(i), name(n) {} 22 }; 23 typedef Key KeyType; 24 typedef Entry ValueType; 25 26 size_t HashKey(KeyType key) const 27 { 28 return node_child_hash(key.id, key.name); 29 } 30 31 size_t Hash(ValueType* value) const 32 { 33 return HashKey(Key(value->GetParent()->GetID(), value->GetName())); 34 } 35 36 bool Compare(KeyType key, ValueType* value) const 37 { 38 return (value->GetParent()->GetID() == key.id 39 && !strcmp(value->GetName(), key.name)); 40 } 41 42 ValueType*& GetLink(ValueType* value) const 43 { 44 return value->HashLink(); 45 } 46}; 47 48// DirectoryEntryTable 49class DirectoryEntryTable { 50public: 51 DirectoryEntryTable(); 52 ~DirectoryEntryTable(); 53 54 status_t InitCheck() const; 55 56 status_t AddEntry(Directory *node, Entry *child); 57 status_t AddEntry(ino_t, Entry *child); 58 status_t RemoveEntry(Directory *node, Entry *child); 59 status_t RemoveEntry(ino_t id, Entry *child); 60 status_t RemoveEntry(ino_t id, const char *name); 61 Entry *GetEntry(ino_t id, const char *name); 62 63 void GetAllocationInfo(AllocationInfo &info) 64 { 65 info.AddDirectoryEntryTableAllocation(0, fTable.TableSize(), 66 sizeof(void*), fTable.CountElements()); 67 } 68 69protected: 70 BOpenHashTable<DirectoryEntryHash> fTable; 71 status_t fInitStatus; 72}; 73 74// constructor 75DirectoryEntryTable::DirectoryEntryTable() 76{ 77 fInitStatus = fTable.Init(1000); 78} 79 80// destructor 81DirectoryEntryTable::~DirectoryEntryTable() 82{ 83} 84 85// InitCheck 86status_t 87DirectoryEntryTable::InitCheck() const 88{ 89 RETURN_ERROR(fInitStatus); 90} 91 92// AddEntry 93status_t 94DirectoryEntryTable::AddEntry(Directory *node, Entry *child) 95{ 96 status_t error = (node && child ? B_OK : B_BAD_VALUE); 97 if (error == B_OK) 98 error = AddEntry(node->GetID(), child); 99 return error; 100} 101 102// AddEntry 103status_t 104DirectoryEntryTable::AddEntry(ino_t id, Entry *child) 105{ 106 status_t error = (child ? B_OK : B_BAD_VALUE); 107 if (error == B_OK) { 108 RemoveEntry(id, child); 109 SET_ERROR(error, fTable.Insert(child)); 110 } 111 return error; 112} 113 114// RemoveEntry 115status_t 116DirectoryEntryTable::RemoveEntry(Directory *node, Entry *child) 117{ 118 status_t error = (node && child ? B_OK : B_BAD_VALUE); 119 if (error == B_OK) 120 error = RemoveEntry(node->GetID(), child->GetName()); 121 return error; 122} 123 124// RemoveEntry 125status_t 126DirectoryEntryTable::RemoveEntry(ino_t id, Entry *child) 127{ 128 status_t error = (child ? B_OK : B_BAD_VALUE); 129 if (error == B_OK) 130 error = RemoveEntry(id, child->GetName()); 131 return error; 132} 133 134// RemoveEntry 135status_t 136DirectoryEntryTable::RemoveEntry(ino_t id, const char *name) 137{ 138 Entry* child = fTable.Lookup(DirectoryEntryHash::Key(id, name)); 139 if (!child) 140 return B_NAME_NOT_FOUND; 141 return fTable.Remove(child) ? B_OK : B_ERROR; 142} 143 144// GetEntry 145Entry * 146DirectoryEntryTable::GetEntry(ino_t id, const char *name) 147{ 148 Entry *child = fTable.Lookup(DirectoryEntryHash::Key(id, name)); 149 return child; 150} 151 152#endif // DIRECTORY_ENTRY_TABLE_H 153