xref: /haiku/src/add-ons/kernel/file_systems/packagefs/indices/NameIndex.cpp (revision 17889a8c70dbb3d59c1412f6431968753c767bab)
1 /*
2  * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "NameIndex.h"
8 
9 #include <TypeConstants.h>
10 
11 #include "DebugSupport.h"
12 #include "IndexImpl.h"
13 #include "Node.h"
14 #include "TwoKeyAVLTree.h"
15 #include "Volume.h"
16 
17 
18 // #pragma mark - NameIndexPrimaryKey
19 
20 
21 class NameIndexPrimaryKey {
22 public:
23 	NameIndexPrimaryKey(const Node* entry, const char* name = NULL)
24 		:
25 		entry(entry),
26 		name(name ? name : entry->Name())
27 	{
28 	}
29 
30 	NameIndexPrimaryKey(const char* name)
31 		:
32 		entry(NULL),
33 		name(name)
34 	{
35 	}
36 
37 	const Node*	entry;
38 	const char*	name;
39 };
40 
41 
42 // #pragma mark - NameIndexGetPrimaryKey
43 
44 
45 class NameIndexGetPrimaryKey {
46 public:
47 	inline NameIndexPrimaryKey operator()(const Node* a)
48 	{
49 		return NameIndexPrimaryKey(a);
50 	}
51 
52 	inline NameIndexPrimaryKey operator()(const Node* a) const
53 	{
54 		return NameIndexPrimaryKey(a);
55 	}
56 };
57 
58 
59 // #pragma mark - NameIndexPrimaryKeyCompare
60 
61 
62 class NameIndexPrimaryKeyCompare {
63 public:
64 	inline int operator()(const NameIndexPrimaryKey &a,
65 		const NameIndexPrimaryKey &b) const
66 	{
67 		if (a.entry != NULL && a.entry == b.entry)
68 			return 0;
69 		return strcmp(a.name, b.name);
70 	}
71 };
72 
73 
74 // #pragma mark - EntryTree
75 
76 
77 typedef TwoKeyAVLTree<Node*, NameIndexPrimaryKey, NameIndexPrimaryKeyCompare,
78 	NameIndexGetPrimaryKey> _EntryTree;
79 
80 class NameIndex::EntryTree : public _EntryTree {
81 };
82 
83 
84 // #pragma mark -  Iterator
85 
86 
87 struct NameIndex::IteratorPolicy {
88 	typedef NameIndex										Index;
89 	typedef const char*										Value;
90 	typedef NameIndex::EntryTree							NodeTree;
91 	typedef GenericIndexIteratorTreePolicy<IteratorPolicy>	TreePolicy;
92 
93 	static NodeTree* GetNodeTree(Index* index)
94 	{
95 		return index->fEntries;
96 	}
97 
98 	static void GetNodeValue(Node* node, void* buffer, size_t* _keyLength)
99 	{
100 		strlcpy((char*)buffer, node->Name(), kMaxIndexKeyLength);
101 		*_keyLength = strlen(node->Name());
102 	}
103 };
104 
105 
106 struct NameIndex::Iterator : public GenericIndexIterator<IteratorPolicy> {
107 };
108 
109 
110 // #pragma mark - NameIndex
111 
112 
113 NameIndex::NameIndex()
114 	:
115 	Index(),
116 	fEntries(NULL)
117 {
118 }
119 
120 
121 NameIndex::~NameIndex()
122 {
123 	if (IsListening())
124 		fVolume->RemoveNodeListener(this);
125 
126 	delete fEntries;
127 	// Actually we would need to maintain a list of iterators and unset the
128 	// still existing iterators here. But since the name index is deleted
129 	// when the volume is unmounted, there shouldn't be any iterators left
130 	// anymore.
131 }
132 
133 
134 status_t
135 NameIndex::Init(Volume* volume)
136 {
137 	status_t error = Index::Init(volume, "name", B_STRING_TYPE, false);
138 	if (error != B_OK)
139 		return error;
140 
141 	fVolume->AddNodeListener(this, NULL);
142 
143 	fEntries = new(std::nothrow) EntryTree;
144 	if (fEntries == NULL)
145 		return B_NO_MEMORY;
146 
147 	return B_OK;
148 }
149 
150 
151 int32
152 NameIndex::CountEntries() const
153 {
154 	return fEntries->CountItems();
155 }
156 
157 
158 void
159 NameIndex::NodeAdded(Node* node)
160 {
161 	fEntries->Insert(node);
162 
163 	// update live queries
164 	_UpdateLiveQueries(node, NULL, node->Name());
165 }
166 
167 
168 void
169 NameIndex::NodeRemoved(Node* node)
170 {
171 	fEntries->Remove(node, node);
172 
173 	// update live queries
174 	_UpdateLiveQueries(node, node->Name(), NULL);
175 }
176 
177 
178 void
179 NameIndex::NodeChanged(Node* node, uint32 statFields,
180 	const OldNodeAttributes& oldAttributes)
181 {
182 	// nothing to do -- the name remains the same
183 }
184 
185 
186 AbstractIndexIterator*
187 NameIndex::InternalGetIterator()
188 {
189 	Iterator* iterator = new(std::nothrow) Iterator;
190 	if (iterator != NULL) {
191 		if (!iterator->SetTo(this, NULL, true)) {
192 			delete iterator;
193 			iterator = NULL;
194 		}
195 	}
196 	return iterator;
197 }
198 
199 
200 AbstractIndexIterator*
201 NameIndex::InternalFind(const void* _key, size_t length)
202 {
203 	if (length == 0)
204 		return NULL;
205 
206 	const char* key = (const char*)_key;
207 
208 	// if the key is not null-terminated, copy it
209 	char clonedKey[kMaxIndexKeyLength];
210 	if (key[length - 1] != '\0') {
211 		if (length >= kMaxIndexKeyLength)
212 			length = kMaxIndexKeyLength - 1;
213 
214 		memcpy(clonedKey, key, length);
215 		clonedKey[length] = '\0';
216 		length++;
217 		key = clonedKey;
218 	}
219 
220 	Iterator* iterator = new(std::nothrow) Iterator;
221 	if (iterator != NULL) {
222 		if (!iterator->SetTo(this, (const char*)key)) {
223 			delete iterator;
224 			iterator = NULL;
225 		}
226 	}
227 	return iterator;
228 }
229 
230 
231 void
232 NameIndex::_UpdateLiveQueries(Node* entry, const char* oldName,
233 	const char* newName)
234 {
235 	fVolume->UpdateLiveQueries(entry, Name(), Type(),
236 		oldName, oldName ? strlen(oldName) : 0,
237 		newName, newName ? strlen(newName) : 0);
238 }
239