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 14class SizeIndexPrimaryKey { 15public: 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 28class SizeIndexGetPrimaryKey { 29public: 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 42class SizeIndexPrimaryKeyCompare 43{ 44public: 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 60typedef TwoKeyAVLTree<Node*, SizeIndexPrimaryKey, 61 SizeIndexPrimaryKeyCompare, 62 SizeIndexGetPrimaryKey> 63 _NodeTree; 64class SizeIndex::NodeTree : public _NodeTree {}; 65 66 67// IteratorList 68class SizeIndex::IteratorList : public DoublyLinkedList<Iterator> {}; 69 70 71// Iterator 72class SizeIndex::Iterator 73 : public NodeEntryIterator<SizeIndex::NodeTree::Iterator>, 74 public DoublyLinkedListLinkImpl<Iterator>, public EntryListener, 75 public NodeListener { 76public: 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 92private: 93 typedef NodeEntryIterator<SizeIndex::NodeTree::Iterator> BaseClass; 94 95private: 96 SizeIndex *fIndex; 97}; 98 99 100// SizeIndex 101 102// constructor 103SizeIndex::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 117SizeIndex::~SizeIndex() 118{ 119 if (fVolume) 120 fVolume->RemoveNodeListener(this, NULL); 121 if (fIterators) { 122 // unset the iterators 123 for (Iterator *iterator = fIterators->First(); 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 135int32 136SizeIndex::CountEntries() const 137{ 138 return fNodes->CountItems(); 139} 140 141// Changed 142status_t 143SizeIndex::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->First(); 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 fNodes->Remove(it); 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 174void 175SizeIndex::NodeAdded(Node *node) 176{ 177 if (node) 178 fNodes->Insert(node); 179} 180 181// NodeRemoved 182void 183SizeIndex::NodeRemoved(Node *node) 184{ 185 if (node) 186 fNodes->Remove(node, node); 187} 188 189// InternalGetIterator 190AbstractIndexEntryIterator * 191SizeIndex::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 204AbstractIndexEntryIterator * 205SizeIndex::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 220void 221SizeIndex::_AddIterator(Iterator *iterator) 222{ 223 fIterators->Insert(iterator); 224} 225 226// _RemoveIterator 227void 228SizeIndex::_RemoveIterator(Iterator *iterator) 229{ 230 fIterators->Remove(iterator); 231} 232 233 234// Iterator 235 236// constructor 237SizeIndex::Iterator::Iterator() 238 : BaseClass(), 239 fIndex(NULL) 240{ 241} 242 243// destructor 244SizeIndex::Iterator::~Iterator() 245{ 246 SetTo(NULL, 0); 247} 248 249// GetCurrent 250Entry * 251SizeIndex::Iterator::GetCurrent() 252{ 253 return BaseClass::GetCurrent(); 254} 255 256// GetCurrent 257Entry * 258SizeIndex::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 269status_t 270SizeIndex::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 291status_t 292SizeIndex::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 309bool 310SizeIndex::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 343void 344SizeIndex::Iterator::Unset() 345{ 346 if (fIndex) { 347 fIndex->_RemoveIterator(this); 348 fIndex = NULL; 349 } 350 BaseClass::Unset(); 351} 352 353// EntryRemoved 354void 355SizeIndex::Iterator::EntryRemoved(Entry */*entry*/) 356{ 357 Resume(); 358 fIsNext = BaseClass::GetNext(); 359 Suspend(); 360} 361 362// NodeRemoved 363void 364SizeIndex::Iterator::NodeRemoved(Node */*node*/) 365{ 366 Resume(); 367 fEntry = NULL; 368 fIsNext = BaseClass::GetNext(); 369 Suspend(); 370} 371 372