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