1 // SizeIndex.cpp 2 3 #include <TypeConstants.h> 4 5 #include "Entry.h" 6 #include "EntryListener.h" 7 #include "IndexImpl.h" 8 #include "Node.h" 9 #include "NodeListener.h" 10 #include "SizeIndex.h" 11 #include "Volume.h" 12 13 // SizeIndexPrimaryKey 14 class SizeIndexPrimaryKey { 15 public: 16 SizeIndexPrimaryKey(Node *node, off_t size) 17 : node(node), size(size) {} 18 SizeIndexPrimaryKey(Node *node) 19 : node(node), size(node->GetSize()) {} 20 SizeIndexPrimaryKey(off_t size) 21 : node(NULL), size(size) {} 22 23 Node *node; 24 off_t size; 25 }; 26 27 // SizeIndexGetPrimaryKey 28 class SizeIndexGetPrimaryKey { 29 public: 30 inline SizeIndexPrimaryKey operator()(Node *a) 31 { 32 return SizeIndexPrimaryKey(a); 33 } 34 35 inline SizeIndexPrimaryKey operator()(Node *a) const 36 { 37 return SizeIndexPrimaryKey(a); 38 } 39 }; 40 41 // SizeIndexPrimaryKeyCompare 42 class SizeIndexPrimaryKeyCompare 43 { 44 public: 45 inline int operator()(const SizeIndexPrimaryKey &a, 46 const SizeIndexPrimaryKey &b) const 47 { 48 if (a.node != NULL && a.node == b.node) 49 return 0; 50 if (a.size < b.size) 51 return -1; 52 if (a.size > b.size) 53 return 1; 54 return 0; 55 } 56 }; 57 58 59 // NodeTree 60 typedef TwoKeyAVLTree<Node*, SizeIndexPrimaryKey, 61 SizeIndexPrimaryKeyCompare, 62 SizeIndexGetPrimaryKey> 63 _NodeTree; 64 class SizeIndex::NodeTree : public _NodeTree {}; 65 66 67 // IteratorList 68 class SizeIndex::IteratorList : public DLList<Iterator> {}; 69 70 71 // Iterator 72 class SizeIndex::Iterator 73 : public NodeEntryIterator<SizeIndex::NodeTree::Iterator>, 74 public DLListLinkImpl<Iterator>, public EntryListener, 75 public NodeListener { 76 public: 77 Iterator(); 78 virtual ~Iterator(); 79 80 virtual Entry *GetCurrent(); 81 virtual Entry *GetCurrent(uint8 *buffer, size_t *keyLength); 82 83 virtual status_t Suspend(); 84 virtual status_t Resume(); 85 86 bool SetTo(SizeIndex *index, off_t size, bool ignoreValue = false); 87 void Unset(); 88 89 virtual void EntryRemoved(Entry *entry); 90 virtual void NodeRemoved(Node *node); 91 92 private: 93 typedef NodeEntryIterator<SizeIndex::NodeTree::Iterator> BaseClass; 94 95 private: 96 SizeIndex *fIndex; 97 }; 98 99 100 // SizeIndex 101 102 // constructor 103 SizeIndex::SizeIndex(Volume *volume) 104 : Index(volume, "size", B_INT64_TYPE, true, sizeof(off_t)), 105 fNodes(new(nothrow) NodeTree), 106 fIterators(new(nothrow) IteratorList) 107 { 108 if (fInitStatus == B_OK && (!fNodes || !fIterators)) 109 fInitStatus = B_NO_MEMORY; 110 if (fInitStatus == B_OK) { 111 fInitStatus = fVolume->AddNodeListener(this, 112 NULL, NODE_LISTEN_ANY_NODE | NODE_LISTEN_ALL); 113 } 114 } 115 116 // destructor 117 SizeIndex::~SizeIndex() 118 { 119 if (fVolume) 120 fVolume->RemoveNodeListener(this, NULL); 121 if (fIterators) { 122 // unset the iterators 123 for (Iterator *iterator = fIterators->GetFirst(); 124 iterator; 125 iterator = fIterators->GetNext(iterator)) { 126 iterator->SetTo(NULL, 0); 127 } 128 delete fIterators; 129 } 130 if (fNodes) 131 delete fNodes; 132 } 133 134 // CountEntries 135 int32 136 SizeIndex::CountEntries() const 137 { 138 return fNodes->CountItems(); 139 } 140 141 // Changed 142 status_t 143 SizeIndex::Changed(Node *node, off_t oldSize) 144 { 145 status_t error = B_BAD_VALUE; 146 if (node) { 147 NodeTree::Iterator it; 148 Node **foundNode = fNodes->Find(SizeIndexPrimaryKey(node, oldSize), 149 node, &it); 150 if (foundNode && *foundNode == node) { 151 // update the iterators 152 for (Iterator *iterator = fIterators->GetFirst(); 153 iterator; 154 iterator = fIterators->GetNext(iterator)) { 155 if (iterator->GetCurrentNode() == node) 156 iterator->NodeRemoved(node); 157 } 158 159 // remove and re-insert the node 160 it.Remove(); 161 error = fNodes->Insert(node); 162 163 // udpate live queries 164 off_t newSize = node->GetSize(); 165 fVolume->UpdateLiveQueries(NULL, node, GetName(), GetType(), 166 (const uint8*)&oldSize, sizeof(oldSize), (const uint8*)&newSize, 167 sizeof(newSize)); 168 } 169 } 170 return error; 171 } 172 173 // NodeAdded 174 void 175 SizeIndex::NodeAdded(Node *node) 176 { 177 if (node) 178 fNodes->Insert(node); 179 } 180 181 // NodeRemoved 182 void 183 SizeIndex::NodeRemoved(Node *node) 184 { 185 if (node) 186 fNodes->Remove(node, node); 187 } 188 189 // InternalGetIterator 190 AbstractIndexEntryIterator * 191 SizeIndex::InternalGetIterator() 192 { 193 Iterator *iterator = new(nothrow) Iterator; 194 if (iterator) { 195 if (!iterator->SetTo(this, 0, true)) { 196 delete iterator; 197 iterator = NULL; 198 } 199 } 200 return iterator; 201 } 202 203 // InternalFind 204 AbstractIndexEntryIterator * 205 SizeIndex::InternalFind(const uint8 *key, size_t length) 206 { 207 if (!key || length != sizeof(off_t)) 208 return NULL; 209 Iterator *iterator = new(nothrow) Iterator; 210 if (iterator) { 211 if (!iterator->SetTo(this, *(const off_t*)key)) { 212 delete iterator; 213 iterator = NULL; 214 } 215 } 216 return iterator; 217 } 218 219 // _AddIterator 220 void 221 SizeIndex::_AddIterator(Iterator *iterator) 222 { 223 fIterators->Insert(iterator); 224 } 225 226 // _RemoveIterator 227 void 228 SizeIndex::_RemoveIterator(Iterator *iterator) 229 { 230 fIterators->Remove(iterator); 231 } 232 233 234 // Iterator 235 236 // constructor 237 SizeIndex::Iterator::Iterator() 238 : BaseClass(), 239 fIndex(NULL) 240 { 241 } 242 243 // destructor 244 SizeIndex::Iterator::~Iterator() 245 { 246 SetTo(NULL, 0); 247 } 248 249 // GetCurrent 250 Entry * 251 SizeIndex::Iterator::GetCurrent() 252 { 253 return BaseClass::GetCurrent(); 254 } 255 256 // GetCurrent 257 Entry * 258 SizeIndex::Iterator::GetCurrent(uint8 *buffer, size_t *keyLength) 259 { 260 Entry *entry = GetCurrent(); 261 if (entry) { 262 *(off_t*)buffer = entry->GetNode()->GetSize(); 263 *keyLength = sizeof(size_t); 264 } 265 return entry; 266 } 267 268 // Suspend 269 status_t 270 SizeIndex::Iterator::Suspend() 271 { 272 status_t error = BaseClass::Suspend(); 273 if (error == B_OK) { 274 if (fNode) { 275 error = fIndex->GetVolume()->AddNodeListener(this, fNode, 276 NODE_LISTEN_REMOVED); 277 if (error == B_OK && fEntry) { 278 error = fIndex->GetVolume()->AddEntryListener(this, fEntry, 279 ENTRY_LISTEN_REMOVED); 280 if (error != B_OK) 281 fIndex->GetVolume()->RemoveNodeListener(this, fNode); 282 } 283 if (error != B_OK) 284 BaseClass::Resume(); 285 } 286 } 287 return error; 288 } 289 290 // Resume 291 status_t 292 SizeIndex::Iterator::Resume() 293 { 294 status_t error = BaseClass::Resume(); 295 if (error == B_OK) { 296 if (fEntry) 297 error = fIndex->GetVolume()->RemoveEntryListener(this, fEntry); 298 if (fNode) { 299 if (error == B_OK) 300 error = fIndex->GetVolume()->RemoveNodeListener(this, fNode); 301 else 302 fIndex->GetVolume()->RemoveNodeListener(this, fNode); 303 } 304 } 305 return error; 306 } 307 308 // SetTo 309 bool 310 SizeIndex::Iterator::SetTo(SizeIndex *index, off_t size, bool ignoreValue) 311 { 312 Resume(); 313 Unset(); 314 // set the new values 315 fIndex = index; 316 if (fIndex) 317 fIndex->_AddIterator(this); 318 fInitialized = fIndex; 319 // get the node's first entry 320 if (fIndex) { 321 // get the first node 322 bool found = true; 323 if (ignoreValue) 324 fIndex->fNodes->GetIterator(&fIterator); 325 else 326 found = fIndex->fNodes->FindFirst(size, &fIterator); 327 // get the first entry 328 if (found) { 329 if (Node **nodeP = fIterator.GetCurrent()) { 330 fNode = *nodeP; 331 fEntry = fNode->GetFirstReferrer(); 332 if (!fEntry) 333 BaseClass::GetNext(); 334 if (!ignoreValue && fNode && fNode->GetSize() != size) 335 Unset(); 336 } 337 } 338 } 339 return fEntry; 340 } 341 342 // Unset 343 void 344 SizeIndex::Iterator::Unset() 345 { 346 if (fIndex) { 347 fIndex->_RemoveIterator(this); 348 fIndex = NULL; 349 } 350 BaseClass::Unset(); 351 } 352 353 // EntryRemoved 354 void 355 SizeIndex::Iterator::EntryRemoved(Entry */*entry*/) 356 { 357 Resume(); 358 fIsNext = BaseClass::GetNext(); 359 Suspend(); 360 } 361 362 // NodeRemoved 363 void 364 SizeIndex::Iterator::NodeRemoved(Node */*node*/) 365 { 366 Resume(); 367 fEntry = NULL; 368 fIsNext = BaseClass::GetNext(); 369 Suspend(); 370 } 371 372