xref: /haiku/src/add-ons/kernel/file_systems/ramfs/DirectoryEntryTable.h (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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