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 16 struct 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 49 class DirectoryEntryTable { 50 public: 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 69 protected: 70 BOpenHashTable<DirectoryEntryHash> fTable; 71 status_t fInitStatus; 72 }; 73 74 // constructor 75 DirectoryEntryTable::DirectoryEntryTable() 76 { 77 fInitStatus = fTable.Init(1000); 78 } 79 80 // destructor 81 DirectoryEntryTable::~DirectoryEntryTable() 82 { 83 } 84 85 // InitCheck 86 status_t 87 DirectoryEntryTable::InitCheck() const 88 { 89 RETURN_ERROR(fInitStatus); 90 } 91 92 // AddEntry 93 status_t 94 DirectoryEntryTable::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 103 status_t 104 DirectoryEntryTable::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 115 status_t 116 DirectoryEntryTable::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 125 status_t 126 DirectoryEntryTable::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 135 status_t 136 DirectoryEntryTable::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 145 Entry * 146 DirectoryEntryTable::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