1 // AttributeIndexImpl.cpp 2 3 #include <TypeConstants.h> 4 5 #include "AttributeIndexImpl.h" 6 #include "Debug.h" 7 #include "Entry.h" 8 #include "EntryListener.h" 9 #include "IndexImpl.h" 10 #include "Misc.h" 11 #include "Node.h" 12 #include "NodeListener.h" 13 #include "ramfs.h" 14 #include "TwoKeyAVLTree.h" 15 #include "Volume.h" 16 17 // compare_integral 18 template<typename Key> 19 static inline 20 int 21 compare_integral(const Key &a, const Key &b) 22 { 23 if (a < b) 24 return -1; 25 else if (a > b) 26 return 1; 27 return 0; 28 } 29 30 // compare_keys 31 static 32 int 33 compare_keys(const uint8 *key1, size_t length1, const uint8 *key2, 34 size_t length2, uint32 type) 35 { 36 switch (type) { 37 case B_INT32_TYPE: 38 return compare_integral(*(int32*)key1, *(int32*)key2); 39 case B_UINT32_TYPE: 40 return compare_integral(*(uint32*)key1, *(uint32*)key2); 41 case B_INT64_TYPE: 42 return compare_integral(*(int64*)key1, *(int64*)key2); 43 case B_UINT64_TYPE: 44 return compare_integral(*(uint64*)key1, *(uint64*)key2); 45 case B_FLOAT_TYPE: 46 return compare_integral(*(float*)key1, *(float*)key2); 47 case B_DOUBLE_TYPE: 48 return compare_integral(*(double*)key1, *(double*)key2); 49 case B_STRING_TYPE: 50 { 51 int result = strncmp((const char*)key1, (const char*)key2, 52 min(length1, length2)); 53 if (result == 0) { 54 result = compare_integral(strnlen((const char*)key1, length1), 55 strnlen((const char*)key2, length2)); 56 } 57 return result; 58 } 59 } 60 return -1; 61 } 62 63 // PrimaryKey 64 class AttributeIndexImpl::PrimaryKey { 65 public: 66 PrimaryKey(Attribute *attribute, const uint8 *key, 67 size_t length) 68 : attribute(attribute), key(key), length(length) {} 69 PrimaryKey(Attribute *attribute) 70 : attribute(attribute) { attribute->GetKey(&key, &length); } 71 PrimaryKey(const uint8 *key, size_t length) 72 : attribute(NULL), key(key), length(length) {} 73 74 Attribute *attribute; 75 const uint8 *key; 76 size_t length; 77 }; 78 79 // GetPrimaryKey 80 class AttributeIndexImpl::GetPrimaryKey { 81 public: 82 inline PrimaryKey operator()(Attribute *a) 83 { 84 return PrimaryKey(a); 85 } 86 87 inline PrimaryKey operator()(Attribute *a) const 88 { 89 return PrimaryKey(a); 90 } 91 }; 92 93 // PrimaryKeyCompare 94 class AttributeIndexImpl::PrimaryKeyCompare 95 { 96 public: 97 PrimaryKeyCompare(uint32 type) : fType(type) {} 98 99 inline int operator()(const PrimaryKey &a, 100 const PrimaryKey &b) const 101 { 102 if (a.attribute != NULL && a.attribute == b.attribute) 103 return 0; 104 return compare_keys(a.key, a.length, b.key, b.length, fType); 105 } 106 107 uint32 fType; 108 }; 109 110 // AttributeNodeIterator 111 template<typename AttributeIterator> 112 class AttributeNodeIterator { 113 public: 114 inline Node **GetCurrent() 115 { 116 if (Attribute **attribute = fIterator.GetCurrent()) { 117 fNode = (*attribute)->GetNode(); 118 return &fNode; 119 } 120 return NULL; 121 } 122 123 inline Node **GetNext() 124 { 125 if (Attribute **attribute = fIterator.GetNext()) { 126 fNode = (*attribute)->GetNode(); 127 return &fNode; 128 } 129 return NULL; 130 } 131 132 AttributeIterator fIterator; 133 Node *fNode; 134 }; 135 136 137 // AttributeTree 138 class AttributeIndexImpl::AttributeTree 139 : public TwoKeyAVLTree<Attribute*, PrimaryKey, PrimaryKeyCompare, 140 GetPrimaryKey> { 141 public: 142 AttributeTree(uint32 type) 143 : TwoKeyAVLTree<Attribute*, PrimaryKey, PrimaryKeyCompare, 144 GetPrimaryKey>(PrimaryKeyCompare(type), 145 GetPrimaryKey(), TwoKeyAVLTreeStandardCompare<Attribute*>(), 146 TwoKeyAVLTreeStandardGetKey<Attribute*, Attribute*>()) 147 { 148 } 149 }; 150 151 152 // Iterator 153 class AttributeIndexImpl::Iterator 154 : public NodeEntryIterator< 155 AttributeNodeIterator<AttributeTree::Iterator> >, 156 public DoublyLinkedListLinkImpl<Iterator>, public EntryListener, 157 public NodeListener { 158 public: 159 Iterator(); 160 virtual ~Iterator(); 161 162 virtual Entry *GetCurrent(); 163 virtual Entry *GetCurrent(uint8 *buffer, size_t *keyLength); 164 165 virtual status_t Suspend(); 166 virtual status_t Resume(); 167 168 bool SetTo(AttributeIndexImpl *index, const uint8 *key, size_t length, 169 bool ignoreValue = false); 170 void Unset(); 171 172 virtual void EntryRemoved(Entry *entry); 173 virtual void NodeRemoved(Node *node); 174 175 private: 176 typedef NodeEntryIterator< 177 AttributeNodeIterator<AttributeTree::Iterator> > BaseClass; 178 179 private: 180 AttributeIndexImpl *fIndex; 181 }; 182 183 184 // IteratorList 185 class AttributeIndexImpl::IteratorList : public DoublyLinkedList<Iterator> {}; 186 187 188 // AttributeIndexImpl 189 190 // constructor 191 AttributeIndexImpl::AttributeIndexImpl(Volume *volume, const char *name, 192 uint32 type, size_t keyLength) 193 : AttributeIndex(volume, name, type, (keyLength > 0), keyLength), 194 fAttributes(new(nothrow) AttributeTree(type)), 195 fIterators(new(nothrow) IteratorList) 196 { 197 if (fInitStatus == B_OK && (!fAttributes || !fIterators)) 198 fInitStatus = B_NO_MEMORY; 199 } 200 201 // destructor 202 AttributeIndexImpl::~AttributeIndexImpl() 203 { 204 if (fIterators) { 205 // unset the iterators 206 for (Iterator *iterator = fIterators->First(); 207 iterator; 208 iterator = fIterators->GetNext(iterator)) { 209 iterator->SetTo(NULL, NULL, 0); 210 } 211 delete fIterators; 212 } 213 // unset all attributes and delete the tree 214 if (fAttributes) { 215 AttributeTree::Iterator it; 216 fAttributes->GetIterator(&it); 217 for (Attribute **attribute = it.GetCurrent(); attribute; it.GetNext()) 218 (*attribute)->SetIndex(NULL, false); 219 delete fAttributes; 220 } 221 } 222 223 // CountEntries 224 int32 225 AttributeIndexImpl::CountEntries() const 226 { 227 return fAttributes->CountItems(); 228 } 229 230 // Changed 231 status_t 232 AttributeIndexImpl::Changed(Attribute *attribute, const uint8 *oldKey, 233 size_t oldLength) 234 { 235 status_t error = B_BAD_VALUE; 236 if (attribute && attribute->GetIndex() == this) { 237 // update the iterators and remove the attribute from the tree 238 error = B_OK; 239 if (attribute->IsInIndex()) { 240 AttributeTree::Iterator it; 241 Attribute **foundAttribute = fAttributes->Find( 242 PrimaryKey(attribute, oldKey, oldLength), attribute, &it); 243 if (foundAttribute && *foundAttribute == attribute) { 244 Node *node = attribute->GetNode(); 245 // update the iterators 246 for (Iterator *iterator = fIterators->First(); 247 iterator; 248 iterator = fIterators->GetNext(iterator)) { 249 if (iterator->GetCurrentNode() == node) 250 iterator->NodeRemoved(node); 251 } 252 // remove and re-insert the attribute 253 it.Remove(); 254 } 255 } 256 // re-insert the attribute 257 if (fKeyLength > 0 && attribute->GetSize() != fKeyLength) { 258 attribute->SetIndex(this, false); 259 } else { 260 error = fAttributes->Insert(attribute); 261 if (error == B_OK) 262 attribute->SetIndex(this, true); 263 else 264 attribute->SetIndex(NULL, false); 265 } 266 } 267 return error; 268 } 269 270 // Added 271 status_t 272 AttributeIndexImpl::Added(Attribute *attribute) 273 { 274 PRINT(("AttributeIndex::Add(%p)\n", attribute)); 275 status_t error = (attribute ? B_OK : B_BAD_VALUE); 276 if (error == B_OK) { 277 size_t size = attribute->GetSize(); 278 if (fKeyLength > 0 && size != fKeyLength) { 279 attribute->SetIndex(this, false); 280 } else { 281 error = fAttributes->Insert(attribute); 282 if (error == B_OK) 283 attribute->SetIndex(this, true); 284 } 285 } 286 return error; 287 } 288 289 // Removed 290 bool 291 AttributeIndexImpl::Removed(Attribute *attribute) 292 { 293 PRINT(("AttributeIndex::Removed(%p)\n", attribute)); 294 bool result = (attribute && attribute->GetIndex() == this); 295 if (result) { 296 if (attribute->IsInIndex()) 297 fAttributes->Remove(attribute, attribute); 298 attribute->SetIndex(NULL, false); 299 } 300 return result; 301 } 302 303 // InternalGetIterator 304 AbstractIndexEntryIterator * 305 AttributeIndexImpl::InternalGetIterator() 306 { 307 Iterator *iterator = new(nothrow) Iterator; 308 if (iterator) { 309 if (!iterator->SetTo(this, NULL, 0, true)) { 310 delete iterator; 311 iterator = NULL; 312 } 313 } 314 return iterator; 315 } 316 317 // InternalFind 318 AbstractIndexEntryIterator * 319 AttributeIndexImpl::InternalFind(const uint8 *key, size_t length) 320 { 321 if (!key || (fKeyLength > 0 && length != fKeyLength)) 322 return NULL; 323 Iterator *iterator = new(nothrow) Iterator; 324 if (iterator) { 325 if (!iterator->SetTo(this, key, length)) { 326 delete iterator; 327 iterator = NULL; 328 } 329 } 330 return iterator; 331 } 332 333 // _AddIterator 334 void 335 AttributeIndexImpl::_AddIterator(Iterator *iterator) 336 { 337 fIterators->Insert(iterator); 338 } 339 340 // _RemoveIterator 341 void 342 AttributeIndexImpl::_RemoveIterator(Iterator *iterator) 343 { 344 fIterators->Remove(iterator); 345 } 346 347 348 // Iterator 349 350 // constructor 351 AttributeIndexImpl::Iterator::Iterator() 352 : BaseClass(), 353 fIndex(NULL) 354 { 355 } 356 357 // destructor 358 AttributeIndexImpl::Iterator::~Iterator() 359 { 360 SetTo(NULL, NULL, 0); 361 } 362 363 // GetCurrent 364 Entry * 365 AttributeIndexImpl::Iterator::GetCurrent() 366 { 367 return BaseClass::GetCurrent(); 368 } 369 370 // GetCurrent 371 Entry * 372 AttributeIndexImpl::Iterator::GetCurrent(uint8 *buffer, size_t *keyLength) 373 { 374 Entry *entry = GetCurrent(); 375 if (entry) { 376 if (Attribute **attribute = fIterator.fIterator.GetCurrent()) { 377 if ((*attribute)->GetNode() == entry->GetNode()) { 378 (*attribute)->GetKey(buffer, keyLength); 379 } else { 380 FATAL(("Node of current attribute and node of current entry " 381 "differ: %Ld vs. %Ld\n", 382 (*attribute)->GetNode()->GetID(), 383 entry->GetNode()->GetID())); 384 entry = NULL; 385 } 386 } else { 387 FATAL(("We have a current entry (`%s', node: %Ld), but no current " 388 "attribute.\n", entry->GetName(), 389 entry->GetNode()->GetID())); 390 entry = NULL; 391 } 392 } 393 return entry; 394 } 395 396 // Suspend 397 status_t 398 AttributeIndexImpl::Iterator::Suspend() 399 { 400 status_t error = BaseClass::Suspend(); 401 if (error == B_OK) { 402 if (fNode) { 403 error = fIndex->GetVolume()->AddNodeListener(this, fNode, 404 NODE_LISTEN_REMOVED); 405 if (error == B_OK && fEntry) { 406 error = fIndex->GetVolume()->AddEntryListener(this, fEntry, 407 ENTRY_LISTEN_REMOVED); 408 if (error != B_OK) 409 fIndex->GetVolume()->RemoveNodeListener(this, fNode); 410 } 411 if (error != B_OK) 412 BaseClass::Resume(); 413 } 414 } 415 return error; 416 } 417 418 // Resume 419 status_t 420 AttributeIndexImpl::Iterator::Resume() 421 { 422 status_t error = BaseClass::Resume(); 423 if (error == B_OK) { 424 if (fEntry) 425 error = fIndex->GetVolume()->RemoveEntryListener(this, fEntry); 426 if (fNode) { 427 if (error == B_OK) 428 error = fIndex->GetVolume()->RemoveNodeListener(this, fNode); 429 else 430 fIndex->GetVolume()->RemoveNodeListener(this, fNode); 431 } 432 } 433 return error; 434 } 435 436 // SetTo 437 bool 438 AttributeIndexImpl::Iterator::SetTo(AttributeIndexImpl *index, 439 const uint8 *key, size_t length, bool ignoreValue) 440 { 441 Resume(); 442 Unset(); 443 // set the new values 444 fIndex = index; 445 if (fIndex) 446 fIndex->_AddIterator(this); 447 fInitialized = fIndex; 448 // get the attribute node's first entry 449 if (fIndex) { 450 // get the first node 451 bool found = true; 452 if (ignoreValue) 453 fIndex->fAttributes->GetIterator(&fIterator.fIterator); 454 else { 455 found = fIndex->fAttributes->FindFirst(PrimaryKey(key, length), 456 &(fIterator.fIterator)); 457 } 458 // get the first entry 459 if (found) { 460 if (Node **nodeP = fIterator.GetCurrent()) { 461 fNode = *nodeP; 462 fEntry = fNode->GetFirstReferrer(); 463 if (!fEntry) 464 BaseClass::GetNext(); 465 if (Attribute **attribute = fIterator.fIterator.GetCurrent()) { 466 const uint8 *attrKey; 467 size_t attrKeyLength; 468 (*attribute)->GetKey(&attrKey, &attrKeyLength); 469 if (!ignoreValue 470 && compare_keys(attrKey, attrKeyLength, key, length, 471 fIndex->GetType()) != 0) { 472 Unset(); 473 } 474 } 475 } 476 } 477 } 478 return fEntry; 479 } 480 481 // Unset 482 void 483 AttributeIndexImpl::Iterator::Unset() 484 { 485 if (fIndex) { 486 fIndex->_RemoveIterator(this); 487 fIndex = NULL; 488 } 489 BaseClass::Unset(); 490 } 491 492 // EntryRemoved 493 void 494 AttributeIndexImpl::Iterator::EntryRemoved(Entry */*entry*/) 495 { 496 Resume(); 497 fIsNext = BaseClass::GetNext(); 498 Suspend(); 499 } 500 501 // NodeRemoved 502 void 503 AttributeIndexImpl::Iterator::NodeRemoved(Node */*node*/) 504 { 505 Resume(); 506 fEntry = NULL; 507 fIsNext = BaseClass::GetNext(); 508 Suspend(); 509 } 510 511