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 21class NameIndexPrimaryKey { 22public: 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 45class NameIndexGetPrimaryKey { 46public: 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 62class NameIndexPrimaryKeyCompare { 63public: 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 77typedef TwoKeyAVLTree<Node*, NameIndexPrimaryKey, NameIndexPrimaryKeyCompare, 78 NameIndexGetPrimaryKey> _EntryTree; 79 80class NameIndex::EntryTree : public _EntryTree { 81}; 82 83 84// #pragma mark - Iterator 85 86 87struct 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 106struct NameIndex::Iterator : public GenericIndexIterator<IteratorPolicy> { 107}; 108 109 110// #pragma mark - NameIndex 111 112 113NameIndex::NameIndex() 114 : 115 Index(), 116 fEntries(NULL) 117{ 118} 119 120 121NameIndex::~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 134status_t 135NameIndex::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 151int32 152NameIndex::CountEntries() const 153{ 154 return fEntries->CountItems(); 155} 156 157 158void 159NameIndex::NodeAdded(Node* node) 160{ 161 fEntries->Insert(node); 162 163 // update live queries 164 _UpdateLiveQueries(node, NULL, node->Name()); 165} 166 167 168void 169NameIndex::NodeRemoved(Node* node) 170{ 171 fEntries->Remove(node, node); 172 173 // update live queries 174 _UpdateLiveQueries(node, node->Name(), NULL); 175} 176 177 178void 179NameIndex::NodeChanged(Node* node, uint32 statFields, 180 const OldNodeAttributes& oldAttributes) 181{ 182 // nothing to do -- the name remains the same 183} 184 185 186AbstractIndexIterator* 187NameIndex::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 200AbstractIndexIterator* 201NameIndex::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 231void 232NameIndex::_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