xref: /haiku/src/add-ons/kernel/file_systems/packagefs/indices/AttributeIndex.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 "AttributeIndex.h"
8 
9 #include <new>
10 
11 #include <TypeConstants.h>
12 
13 #include <util/AVLTree.h>
14 #include <util/SinglyLinkedList.h>
15 
16 #include <file_systems/QueryParserUtils.h>
17 
18 #include "AttributeIndexer.h"
19 #include "DebugSupport.h"
20 #include "IndexImpl.h"
21 #include "Node.h"
22 #include "Volume.h"
23 
24 
25 struct AttributeIndexTreeKey {
26 	const void*	data;
27 	size_t		length;
28 
29 	AttributeIndexTreeKey()
30 	{
31 	}
32 
33 	AttributeIndexTreeKey(const void* data, size_t length)
34 		:
35 		data(data),
36 		length(length)
37 	{
38 	}
39 };
40 
41 
42 struct AttributeIndexTreeValue : AVLTreeNode {
43 	Node*					node;
44 	IndexedAttributeOwner*	owner;
45 	void*					attributeCookie;
46 	size_t					length;
47 	uint8					data[0];
48 
49 	static AttributeIndexTreeValue* Create(IndexedAttributeOwner* owner,
50 		void* attributeCookie, size_t length)
51 	{
52 		AttributeIndexTreeValue* self = (AttributeIndexTreeValue*)malloc(
53 			sizeof(AttributeIndexTreeValue) + length);
54 		if (self == NULL)
55 			return NULL;
56 
57 		self->owner = owner;
58 		self->attributeCookie = attributeCookie;
59 		self->length = length;
60 		return self;
61 	}
62 
63 	void Delete()
64 	{
65 		free(this);
66 	}
67 };
68 
69 
70 struct AttributeIndex::TreeDefinition {
71 	typedef TreeKey		Key;
72 	typedef TreeValue	Value;
73 
74 	TreeDefinition(uint32 type)
75 		:
76 		fType(type)
77 	{
78 	}
79 
80 	AVLTreeNode* GetAVLTreeNode(Value* value) const
81 	{
82 		return value;
83 	}
84 
85 	Value* GetValue(AVLTreeNode* node) const
86 	{
87 		return static_cast<Value*>(node);
88 	}
89 
90 	int Compare(const Key& a, const Value* b) const
91 	{
92 		int cmp = QueryParser::compareKeys(fType, a.data, a.length, b->data,
93 			b->length);
94 		if (cmp != 0)
95 			return cmp;
96 
97 		// The attribute value is the same. Since the tree value is the tree
98 		// node itself, we must not return 0, though. We consider a node-less
99 		// key always less than an actual tree node with the same attribute
100 		// value.
101 		return -1;
102 	}
103 
104 	int Compare(const Value* a, const Value* b) const
105 	{
106 		if (a == b)
107 			return 0;
108 
109 		int cmp = QueryParser::compareKeys(fType, a->data, a->length, b->data,
110 			b->length);
111 		if (cmp != 0)
112 			return cmp;
113 
114 		return a < b ? -1 : 1;
115 	}
116 
117 private:
118 	uint32	fType;
119 };
120 
121 
122 // #pragma mark - NodeTree
123 
124 
125 struct AttributeIndex::NodeTree : public AVLTree<TreeDefinition> {
126 	typedef TreeValue	Node;
127 
128 	NodeTree(const TreeDefinition& definition)
129 		:
130 		AVLTree<TreeDefinition>(definition)
131 	{
132 	}
133 };
134 
135 
136 // #pragma mark - IteratorList
137 
138 
139 class AttributeIndex::IteratorList : public SinglyLinkedList<Iterator> {};
140 
141 
142 // #pragma mark - Iterator
143 
144 
145 struct AttributeIndex::IteratorPolicy {
146 	typedef AttributeIndex				Index;
147 	typedef TreeKey						Value;
148 	typedef AttributeIndex::NodeTree	NodeTree;
149 	typedef TreeValue					TreeNode;
150 	typedef IteratorPolicy				TreePolicy;
151 
152 	static NodeTree* GetNodeTree(Index* index)
153 	{
154 		return index->fNodes;
155 	}
156 
157 	static void GetTreeNodeValue(TreeNode* node, void* buffer,
158 		size_t* _keyLength)
159 	{
160 		if (node->length > 0)
161 			memcpy(buffer, node->data, node->length);
162 		*_keyLength = node->length;
163 	}
164 
165 	static Node* GetNode(TreeNode* treeNode)
166 	{
167 		return treeNode->node;
168 	}
169 
170 	static TreeNode* GetFirstTreeNode(Index* index)
171 	{
172 		return index->fNodes->GetIterator().Next();
173 	}
174 
175 	static TreeNode* FindClosestTreeNode(Index* index, const Value& value)
176 	{
177 		return index->fNodes->FindClosest(value, false);
178 	}
179 };
180 
181 
182 class AttributeIndex::Iterator : public GenericIndexIterator<IteratorPolicy>,
183 	public SinglyLinkedListLinkImpl<Iterator> {
184 public:
185 	virtual	void				NodeChanged(Node* node, uint32 statFields,
186 									const OldNodeAttributes& oldAttributes);
187 };
188 
189 
190 // #pragma mark - AttributeIndexer
191 
192 
193 AttributeIndexer::AttributeIndexer(AttributeIndex* index)
194 	:
195 	fIndex(index),
196 	fIndexName(index->Name()),
197 	fIndexType(index->Type()),
198 	fCookie(NULL)
199 {
200 }
201 
202 
203 AttributeIndexer::~AttributeIndexer()
204 {
205 }
206 
207 
208 status_t
209 AttributeIndexer::CreateCookie(IndexedAttributeOwner* owner,
210 	void* attributeCookie, uint32 attributeType, size_t attributeSize,
211 	void*& _data, size_t& _toRead)
212 {
213 	// check the attribute type and size
214 	if (attributeType != fIndexType)
215 		return B_ERROR;
216 
217 	if (fIndex->HasFixedKeyLength()) {
218 		if (attributeSize != fIndex->KeyLength())
219 			return B_ERROR;
220 	} else if (attributeSize > kMaxIndexKeyLength)
221 		attributeSize = kMaxIndexKeyLength;
222 
223 	// create the tree value
224 	fCookie = AttributeIndexTreeValue::Create(owner, attributeCookie,
225 		attributeSize);
226 	if (fCookie == NULL)
227 		return B_NO_MEMORY;
228 
229 	_data = fCookie->data;
230 	_toRead = attributeSize;
231 
232 	return B_OK;
233 }
234 
235 
236 void
237 AttributeIndexer::DeleteCookie()
238 {
239 	fCookie->Delete();
240 	fCookie = NULL;
241 }
242 
243 
244 // #pragma mark - AttributeIndex
245 
246 
247 AttributeIndex::AttributeIndex()
248 	:
249 	Index(),
250 	fNodes(NULL),
251 	fIteratorsToUpdate(NULL),
252 	fIndexer(NULL)
253 {
254 }
255 
256 
257 AttributeIndex::~AttributeIndex()
258 {
259 	if (IsListening())
260 		fVolume->RemoveNodeListener(this);
261 
262 	ASSERT(fIteratorsToUpdate->IsEmpty());
263 
264 	delete fIteratorsToUpdate;
265 	delete fNodes;
266 	delete fIndexer;
267 }
268 
269 
270 status_t
271 AttributeIndex::Init(Volume* volume, const char* name,  uint32 type,
272 	size_t keyLength)
273 {
274 	status_t error = Index::Init(volume, name, type, keyLength > 0, keyLength);
275 	if (error != B_OK)
276 		return error;
277 
278 	// TODO: Letting each attribute index be a listener is gets more expensive
279 	// the more attribute indices we have. Since most attribute indices are
280 	// rather sparse, it might be a good idea to rather let Volume iterate
281 	// through the actual attributes of an added node and look up and call the
282 	// index for each one explicitly. When removing the node, the volume would
283 	// iterate through the attributes again and determine based on the index
284 	// cookie whether an index has to be notified.
285 	fVolume->AddNodeListener(this, NULL);
286 
287 	fNodes = new(std::nothrow) NodeTree(TreeDefinition(type));
288 	fIteratorsToUpdate = new(std::nothrow) IteratorList;
289 	fIndexer = new(std::nothrow) AttributeIndexer(this);
290 
291 	if (fNodes == NULL || fIteratorsToUpdate == NULL || fIndexer == NULL)
292 		return B_NO_MEMORY;
293 
294 	return B_OK;
295 }
296 
297 
298 int32
299 AttributeIndex::CountEntries() const
300 {
301 	return fNodes->Count();
302 }
303 
304 
305 void
306 AttributeIndex::NodeAdded(Node* node)
307 {
308 	if (node->IndexAttribute(fIndexer) != B_OK)
309 		return;
310 
311 	TreeValue* treeValue = fIndexer->Cookie();
312 	treeValue->node = node;
313 
314 	fNodes->Insert(treeValue);
315 }
316 
317 
318 void
319 AttributeIndex::NodeRemoved(Node* node)
320 {
321 	TreeValue* treeValue = (TreeValue*)node->IndexCookieForAttribute(Name());
322 	if (treeValue == NULL)
323 		return;
324 
325 	treeValue->owner->UnsetIndexCookie(treeValue->attributeCookie);
326 	fNodes->Remove(treeValue);
327 }
328 
329 
330 void
331 AttributeIndex::NodeChanged(Node* node, uint32 statFields,
332 	const OldNodeAttributes& oldAttributes)
333 {
334 	IteratorList iterators;
335 	iterators.MoveFrom(fIteratorsToUpdate);
336 
337 	TreeValue* oldTreeValue
338 		= (TreeValue*)oldAttributes.IndexCookieForAttribute(Name());
339 	TreeValue* treeValue = (TreeValue*)node->IndexCookieForAttribute(Name());
340 	if (treeValue == NULL && oldTreeValue == NULL)
341 		return;
342 
343 	// move the iterators that point to the node to the previous node
344 	if (oldTreeValue != NULL) {
345 		for (IteratorList::Iterator it = iterators.GetIterator();
346 				Iterator* iterator = it.Next();) {
347 			iterator->NodeChangeBegin(node);
348 		}
349 
350 		// remove the node
351 		fNodes->Remove(oldTreeValue);
352 	}
353 
354 	// re-insert the node
355 	if (treeValue != NULL)
356 		fNodes->Insert(treeValue);
357 
358 	// Move the iterators to the next node again. If the node hasn't changed
359 	// its place, they will point to it again, otherwise to the node originally
360 	// succeeding it.
361 	if (oldTreeValue != NULL) {
362 		for (IteratorList::Iterator it = iterators.GetIterator();
363 				Iterator* iterator = it.Next();) {
364 			iterator->NodeChangeEnd(node);
365 		}
366 	}
367 
368 	// update live queries
369 	fVolume->UpdateLiveQueries(node, Name(), Type(),
370 		oldTreeValue != NULL ? oldTreeValue->data : NULL,
371 		oldTreeValue != NULL ? oldTreeValue->length : 0,
372 		treeValue != NULL ? treeValue->data : NULL,
373 		treeValue != NULL ? treeValue->length : 0);
374 
375 	if (oldTreeValue != NULL)
376 		oldTreeValue->Delete();
377 }
378 
379 
380 AbstractIndexIterator*
381 AttributeIndex::InternalGetIterator()
382 {
383 	Iterator* iterator = new(std::nothrow) Iterator;
384 	if (iterator != NULL) {
385 		if (!iterator->SetTo(this, TreeKey(), true)) {
386 			delete iterator;
387 			iterator = NULL;
388 		}
389 	}
390 	return iterator;
391 }
392 
393 
394 AbstractIndexIterator*
395 AttributeIndex::InternalFind(const void* key, size_t length)
396 {
397 	if (HasFixedKeyLength() && length != KeyLength())
398 		return NULL;
399 
400 	Iterator* iterator = new(std::nothrow) Iterator;
401 	if (iterator != NULL) {
402 		if (!iterator->SetTo(this, TreeKey(key, length))) {
403 			delete iterator;
404 			iterator = NULL;
405 		}
406 	}
407 	return iterator;
408 }
409 
410 
411 void
412 AttributeIndex::_AddIteratorToUpdate(Iterator* iterator)
413 {
414 	fIteratorsToUpdate->Add(iterator);
415 }
416 
417 
418 // #pragma mark - Iterator
419 
420 
421 void
422 AttributeIndex::Iterator::NodeChanged(Node* node, uint32 statFields,
423 	const OldNodeAttributes& oldAttributes)
424 {
425 	fIndex->_AddIteratorToUpdate(this);
426 }
427