1299aba38Shyche /* 2299aba38Shyche * Copyright 2011, Jérôme Duval, korli@users.berlios.de. 3299aba38Shyche * Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de. 4299aba38Shyche * This file may be used under the terms of the MIT License. 5299aba38Shyche */ 6299aba38Shyche 7299aba38Shyche 8299aba38Shyche //! BTree implementation 9299aba38Shyche 10299aba38Shyche 11299aba38Shyche #include "BTree.h" 12299aba38Shyche 13299aba38Shyche 14299aba38Shyche //#define TRACE_BTRFS 15299aba38Shyche #ifdef TRACE_BTRFS 16299aba38Shyche # define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x) 17299aba38Shyche #else 18299aba38Shyche # define TRACE(x...) ; 19299aba38Shyche #endif 20299aba38Shyche # define ERROR(x...) dprintf("\33[34mbtrfs:\33[0m " x) 21299aba38Shyche 22299aba38Shyche 238160f31fShyche BTree::Node::Node(Volume* volume) 241481c49cShyche : 251481c49cShyche fNode(NULL), 268160f31fShyche fVolume(volume), 271481c49cShyche fBlockNumber(0), 281481c49cShyche fWritable(false) 291481c49cShyche { 301481c49cShyche } 311481c49cShyche 321481c49cShyche 338160f31fShyche BTree::Node::Node(Volume* volume, off_t block) 341481c49cShyche : 351481c49cShyche fNode(NULL), 368160f31fShyche fVolume(volume), 371481c49cShyche fBlockNumber(0), 381481c49cShyche fWritable(false) 391481c49cShyche { 401481c49cShyche SetTo(block); 411481c49cShyche } 421481c49cShyche 431481c49cShyche 44548a0d80Shyche BTree::Node::~Node() 451481c49cShyche { 461481c49cShyche Unset(); 471481c49cShyche } 481481c49cShyche 491481c49cShyche 501481c49cShyche void 51548a0d80Shyche BTree::Node::Keep() 521481c49cShyche { 531481c49cShyche fNode = NULL; 541481c49cShyche } 551481c49cShyche 561481c49cShyche void 57548a0d80Shyche BTree::Node::Unset() 581481c49cShyche { 591481c49cShyche if (fNode != NULL) { 608160f31fShyche block_cache_put(fVolume->BlockCache(), fBlockNumber); 611481c49cShyche fNode = NULL; 621481c49cShyche } 631481c49cShyche } 641481c49cShyche 651481c49cShyche 661481c49cShyche void 67548a0d80Shyche BTree::Node::SetTo(off_t block) 681481c49cShyche { 691481c49cShyche Unset(); 701481c49cShyche fBlockNumber = block; 718160f31fShyche fNode = (btrfs_stream*)block_cache_get(fVolume->BlockCache(), block); 721481c49cShyche } 731481c49cShyche 741481c49cShyche 751481c49cShyche void 76548a0d80Shyche BTree::Node::SetToWritable(off_t block, int32 transactionId, bool empty) 771481c49cShyche { 781481c49cShyche Unset(); 791481c49cShyche fBlockNumber = block; 801481c49cShyche fWritable = true; 811481c49cShyche if (empty) { 828160f31fShyche fNode = (btrfs_stream*)block_cache_get_empty(fVolume->BlockCache(), 838160f31fShyche block, transactionId); 841481c49cShyche } else { 858160f31fShyche fNode = (btrfs_stream*)block_cache_get_writable(fVolume->BlockCache(), 868160f31fShyche block, transactionId); 871481c49cShyche } 881481c49cShyche } 891481c49cShyche 901481c49cShyche 912ed88a48Shyche status_t 922ed88a48Shyche BTree::Node::SearchSlot(const btrfs_key& key, int* slot, btree_traversing type) 932ed88a48Shyche const 9491d7f850Shyche { 9591d7f850Shyche //binary search for item slot in a node 9691d7f850Shyche int entrySize = sizeof(btrfs_entry); 9791d7f850Shyche if (Level() != 0) { 9891d7f850Shyche // internal node 9991d7f850Shyche entrySize = sizeof(btrfs_index); 10091d7f850Shyche } 10191d7f850Shyche 10291d7f850Shyche int high = ItemCount(); 1032ed88a48Shyche int low = 0, mid = 0, comp = 0; 1042ed88a48Shyche uint8* base = (uint8*)fNode + sizeof(btrfs_header); 10591d7f850Shyche const btrfs_key* other; 10691d7f850Shyche while (low < high) { 10791d7f850Shyche mid = (low + high) / 2; 1082ed88a48Shyche other = (const btrfs_key*)(base + mid * entrySize); 1090d726c5cShyche comp = key.Compare(*other); 11091d7f850Shyche if (comp < 0) 11191d7f850Shyche high = mid; 11291d7f850Shyche else if (comp > 0) 11391d7f850Shyche low = mid + 1; 11491d7f850Shyche else { 11591d7f850Shyche *slot = mid; 1160d726c5cShyche return B_OK; //if key is in node 11791d7f850Shyche } 11891d7f850Shyche } 1190d726c5cShyche 1202ed88a48Shyche // |--item1--|--item2--|--item3--|--etc--| 1212ed88a48Shyche // m-1 m m+1 1222ed88a48Shyche // k : comp < 0 1232ed88a48Shyche // k : comp > 0 1242ed88a48Shyche if (type == BTREE_BACKWARD) { 1252ed88a48Shyche *slot = mid - 1; 1262ed88a48Shyche if (comp > 0) 1272ed88a48Shyche *slot = mid; 1282ed88a48Shyche } else if (type == BTREE_FORWARD) { 1292ed88a48Shyche *slot = mid; 1302ed88a48Shyche if (comp > 0) 1312ed88a48Shyche *slot = mid + 1; 1322ed88a48Shyche } 1332ed88a48Shyche 1342ed88a48Shyche if (type == BTREE_EXACT || *slot < 0) 1352ed88a48Shyche return B_ENTRY_NOT_FOUND; 1362ed88a48Shyche 1370d726c5cShyche TRACE("SearchSlot() found slot %" B_PRId32 " comp %" B_PRId32 "\n", 1380d726c5cShyche *slot, comp); 1390d726c5cShyche return B_OK; 14091d7f850Shyche } 14191d7f850Shyche 14291d7f850Shyche 143*3216460dShyche // #pragma mark - BTree::Path implementation 144*3216460dShyche 145*3216460dShyche 146*3216460dShyche BTree::Path::Path(BTree* tree) 147*3216460dShyche : 148*3216460dShyche fTree(tree) 149*3216460dShyche { 150*3216460dShyche for (int i = 0; i < BTRFS_MAX_TREE_DEPTH; ++i) { 151*3216460dShyche fNodes[i] = NULL; 152*3216460dShyche fSlots[i] = 0; 153*3216460dShyche } 154*3216460dShyche } 155*3216460dShyche 156*3216460dShyche 157*3216460dShyche BTree::Path::~Path() 158*3216460dShyche { 159*3216460dShyche for (int i = 0; i < BTRFS_MAX_TREE_DEPTH; ++i) { 160*3216460dShyche delete fNodes[i]; 161*3216460dShyche fNodes[i] = NULL; 162*3216460dShyche fSlots[i] = 0; 163*3216460dShyche } 164*3216460dShyche } 165*3216460dShyche 166*3216460dShyche 167*3216460dShyche BTree::Node* 168*3216460dShyche BTree::Path::GetNode(int level, int* _slot) const 169*3216460dShyche { 170*3216460dShyche if (_slot != NULL) 171*3216460dShyche *_slot = fSlots[level]; 172*3216460dShyche return fNodes[level]; 173*3216460dShyche } 174*3216460dShyche 175*3216460dShyche 176*3216460dShyche BTree::Node* 177*3216460dShyche BTree::Path::SetNode(off_t block, int slot) 178*3216460dShyche { 179*3216460dShyche Node node(fTree->SystemVolume(), block); 180*3216460dShyche return SetNode(&node, slot); 181*3216460dShyche } 182*3216460dShyche 183*3216460dShyche 184*3216460dShyche BTree::Node* 185*3216460dShyche BTree::Path::SetNode(const Node* node, int slot) 186*3216460dShyche { 187*3216460dShyche uint8 level = node->Level(); 188*3216460dShyche if (fNodes[level] == NULL) { 189*3216460dShyche fNodes[level] = new Node(fTree->SystemVolume(), node->BlockNum()); 190*3216460dShyche if (fNodes[level] == NULL) 191*3216460dShyche return NULL; 192*3216460dShyche } else 193*3216460dShyche fNodes[level]->SetTo(node->BlockNum()); 194*3216460dShyche 195*3216460dShyche if (slot == -1) 196*3216460dShyche fSlots[level] = fNodes[level]->ItemCount() - 1; 197*3216460dShyche else 198*3216460dShyche fSlots[level] = slot; 199*3216460dShyche return fNodes[level]; 200*3216460dShyche } 201*3216460dShyche 202*3216460dShyche 203*3216460dShyche int 204*3216460dShyche BTree::Path::Move(int level, int step) 205*3216460dShyche { 206*3216460dShyche fSlots[level] += step; 207*3216460dShyche if (fSlots[level] < 0) 208*3216460dShyche return -1; 209*3216460dShyche if (fSlots[level] >= fNodes[level]->ItemCount()) 210*3216460dShyche return 1; 211*3216460dShyche return 0; 212*3216460dShyche } 213*3216460dShyche 214*3216460dShyche 215*3216460dShyche status_t 216*3216460dShyche BTree::Path::GetEntry(int slot, btrfs_key* _key, void** _value, uint32* _size, 217*3216460dShyche uint32* _offset) 218*3216460dShyche { 219*3216460dShyche BTree::Node* leaf = fNodes[0]; 220*3216460dShyche if (slot < 0 || slot >= leaf->ItemCount()) 221*3216460dShyche return B_ENTRY_NOT_FOUND; 222*3216460dShyche 223*3216460dShyche if (_key != NULL) 224*3216460dShyche *_key = leaf->Item(slot)->key; 225*3216460dShyche 226*3216460dShyche uint32 itemSize = leaf->Item(slot)->Size(); 227*3216460dShyche if (_value != NULL) { 228*3216460dShyche *_value = malloc(itemSize); 229*3216460dShyche if (*_value == NULL) 230*3216460dShyche return B_NO_MEMORY; 231*3216460dShyche 232*3216460dShyche memcpy(*_value, leaf->ItemData(slot), itemSize); 233*3216460dShyche } 234*3216460dShyche 235*3216460dShyche if (_size != NULL) 236*3216460dShyche *_size = itemSize; 237*3216460dShyche 238*3216460dShyche if (_offset != NULL) 239*3216460dShyche *_offset = leaf->Item(slot)->Offset(); 240*3216460dShyche 241*3216460dShyche return B_OK; 242*3216460dShyche } 243*3216460dShyche 244*3216460dShyche 245*3216460dShyche // #pragma mark - BTree implementation 2461481c49cShyche 2471481c49cShyche 248fc4a1e78Shyche BTree::BTree(Volume* volume) 249fc4a1e78Shyche : 250fc4a1e78Shyche fRootBlock(0), 251fc4a1e78Shyche fVolume(volume) 252fc4a1e78Shyche { 253fc4a1e78Shyche mutex_init(&fIteratorLock, "btrfs b+tree iterator"); 254fc4a1e78Shyche } 255fc4a1e78Shyche 256fc4a1e78Shyche 257299aba38Shyche BTree::BTree(Volume* volume, btrfs_stream* stream) 258299aba38Shyche : 259299aba38Shyche fRootBlock(0), 260299aba38Shyche fVolume(volume) 261299aba38Shyche { 262299aba38Shyche mutex_init(&fIteratorLock, "btrfs b+tree iterator"); 263299aba38Shyche } 264299aba38Shyche 265299aba38Shyche 266299aba38Shyche BTree::BTree(Volume* volume, fsblock_t rootBlock) 267299aba38Shyche : 268299aba38Shyche fRootBlock(rootBlock), 269299aba38Shyche fVolume(volume) 270299aba38Shyche { 271299aba38Shyche mutex_init(&fIteratorLock, "btrfs b+tree iterator"); 272299aba38Shyche } 273299aba38Shyche 274299aba38Shyche 275299aba38Shyche BTree::~BTree() 276299aba38Shyche { 277299aba38Shyche // if there are any TreeIterators left, we need to stop them 278299aba38Shyche // (can happen when the tree's inode gets deleted while 279299aba38Shyche // traversing the tree - a TreeIterator doesn't lock the inode) 280299aba38Shyche mutex_lock(&fIteratorLock); 281299aba38Shyche 282299aba38Shyche SinglyLinkedList<TreeIterator>::Iterator iterator 283299aba38Shyche = fIterators.GetIterator(); 284299aba38Shyche while (iterator.HasNext()) 285299aba38Shyche iterator.Next()->Stop(); 286299aba38Shyche mutex_destroy(&fIteratorLock); 287299aba38Shyche } 288299aba38Shyche 289299aba38Shyche 290299aba38Shyche int32 291875a0552Shyche btrfs_key::Compare(const btrfs_key& key) const 292299aba38Shyche { 293875a0552Shyche if (ObjectID() > key.ObjectID()) 294299aba38Shyche return 1; 295875a0552Shyche if (ObjectID() < key.ObjectID()) 296299aba38Shyche return -1; 297875a0552Shyche if (Type() > key.Type()) 298299aba38Shyche return 1; 299875a0552Shyche if (Type() < key.Type()) 300299aba38Shyche return -1; 301875a0552Shyche if (Offset() > key.Offset()) 302299aba38Shyche return 1; 303875a0552Shyche if (Offset() < key.Offset()) 304299aba38Shyche return -1; 305299aba38Shyche return 0; 306299aba38Shyche } 307299aba38Shyche 308299aba38Shyche 309*3216460dShyche /* Traverse from root to fill in the path along way its finding. 310*3216460dShyche * Return current slot at leaf if successful. 311*3216460dShyche */ 312*3216460dShyche status_t 313*3216460dShyche BTree::Traverse(btree_traversing type, Path* path, const btrfs_key& key) 314*3216460dShyche const 315*3216460dShyche { 316*3216460dShyche TRACE("BTree::Traverse() objectid %" B_PRId64 " type %d offset %" 317*3216460dShyche B_PRId64 " \n", key.ObjectID(), key.Type(), key.Offset()); 318*3216460dShyche fsblock_t physicalBlock = fRootBlock; 319*3216460dShyche Node node(fVolume, physicalBlock); 320*3216460dShyche int slot; 321*3216460dShyche status_t status = B_OK; 322*3216460dShyche 323*3216460dShyche while (node.Level() != 0) { 324*3216460dShyche TRACE("BTree::Traverse() level %d count %d\n", node.Level(), 325*3216460dShyche node.ItemCount()); 326*3216460dShyche status = node.SearchSlot(key, &slot, BTREE_BACKWARD); 327*3216460dShyche if (status != B_OK) 328*3216460dShyche return status; 329*3216460dShyche if (path->SetNode(&node, slot) == NULL) 330*3216460dShyche return B_NO_MEMORY; 331*3216460dShyche 332*3216460dShyche TRACE("BTree::Traverse() getting index %" B_PRIu32 "\n", slot); 333*3216460dShyche 334*3216460dShyche status = fVolume->FindBlock(node.Index(slot)->LogicalAddress(), 335*3216460dShyche physicalBlock); 336*3216460dShyche if (status != B_OK) { 337*3216460dShyche ERROR("BTree::Traverse() unmapped block %" B_PRId64 "\n", 338*3216460dShyche node.Index(slot)->LogicalAddress()); 339*3216460dShyche return status; 340*3216460dShyche } 341*3216460dShyche node.SetTo(physicalBlock); 342*3216460dShyche } 343*3216460dShyche 344*3216460dShyche TRACE("BTree::Traverse() dump count %" B_PRId32 "\n", node.ItemCount()); 345*3216460dShyche status = node.SearchSlot(key, &slot, type); 346*3216460dShyche if (status != B_OK) 347*3216460dShyche return status; 348*3216460dShyche if (path->SetNode(&node, slot) == NULL) 349*3216460dShyche return B_NO_MEMORY; 350*3216460dShyche 351*3216460dShyche TRACE("BTree::Traverse() found %" B_PRIu32 " %" B_PRIu32 "\n", 352*3216460dShyche node.Item(slot)->Offset(), node.Item(slot)->Size()); 353*3216460dShyche return slot; 354*3216460dShyche } 355*3216460dShyche 356*3216460dShyche 357299aba38Shyche /*! Searches the key in the tree, and stores the allocated found item in 358299aba38Shyche _value, if successful. 359299aba38Shyche Returns B_OK when the key could be found, B_ENTRY_NOT_FOUND if not. 360299aba38Shyche It can also return other errors to indicate that something went wrong. 361299aba38Shyche */ 362299aba38Shyche status_t 363*3216460dShyche BTree::_Find(Path* path, btrfs_key& wanted, void** _value, uint32* _size, 364*3216460dShyche uint32* _offset, btree_traversing type) const 365299aba38Shyche { 366*3216460dShyche status_t status = Traverse(type, path, wanted); 367*3216460dShyche if (status < B_OK) 368*3216460dShyche return status; 369299aba38Shyche 370*3216460dShyche btrfs_key found; 371*3216460dShyche status = path->GetCurrentEntry(&found, _value, _size, _offset); 372*3216460dShyche if (status != B_OK) 373*3216460dShyche return status; 374299aba38Shyche 375*3216460dShyche if (found.Type() != wanted.Type() && wanted.Type() != BTRFS_KEY_TYPE_ANY) 37646eba5c0Shyche return B_ENTRY_NOT_FOUND; 377299aba38Shyche 378*3216460dShyche wanted = found; 379299aba38Shyche return B_OK; 380299aba38Shyche } 381299aba38Shyche 382299aba38Shyche 38346eba5c0Shyche status_t 384*3216460dShyche BTree::FindNext(Path* path, btrfs_key& key, void** _value, uint32* _size, 385*3216460dShyche uint32* _offset) const 38646eba5c0Shyche { 387*3216460dShyche return _Find(path, key, _value, _size, _offset, BTREE_FORWARD); 388299aba38Shyche } 389299aba38Shyche 390299aba38Shyche 391299aba38Shyche status_t 392*3216460dShyche BTree::FindPrevious(Path* path, btrfs_key& key, void** _value, uint32* _size, 393*3216460dShyche uint32* _offset) const 394299aba38Shyche { 395*3216460dShyche return _Find(path, key, _value, _size, _offset, BTREE_BACKWARD); 396299aba38Shyche } 397299aba38Shyche 398299aba38Shyche 399299aba38Shyche status_t 400*3216460dShyche BTree::FindExact(Path* path, btrfs_key& key, void** _value, uint32* _size, 401*3216460dShyche uint32* _offset) const 402299aba38Shyche { 403*3216460dShyche return _Find(path, key, _value, _size, _offset, BTREE_EXACT); 404*3216460dShyche } 405*3216460dShyche 406*3216460dShyche 407*3216460dShyche status_t 408*3216460dShyche BTree::PreviousLeaf(Path* path) const 409*3216460dShyche { 410*3216460dShyche // TODO: use Traverse() ??? 411*3216460dShyche int level = 0; 412*3216460dShyche int slot; 413*3216460dShyche Node* node = NULL; 414*3216460dShyche // iterate to the root until satisfy the condition 415*3216460dShyche while (true) { 416*3216460dShyche node = path->GetNode(level, &slot); 417*3216460dShyche if (node == NULL || slot != 0) 418*3216460dShyche break; 419*3216460dShyche level++; 420*3216460dShyche } 421*3216460dShyche 422*3216460dShyche // the current leaf is already the left most leaf or 423*3216460dShyche // path was not initialized 424*3216460dShyche if (node == NULL) 425*3216460dShyche return B_ENTRY_NOT_FOUND; 426*3216460dShyche 427*3216460dShyche path->Move(level, BTREE_BACKWARD); 428*3216460dShyche fsblock_t physicalBlock; 429*3216460dShyche // change all nodes below this level and slot to the ending 430*3216460dShyche do { 431*3216460dShyche status_t status = fVolume->FindBlock( 432*3216460dShyche node->Index(slot)->LogicalAddress(), physicalBlock); 433*3216460dShyche if (status != B_OK) 434*3216460dShyche return status; 435*3216460dShyche 436*3216460dShyche node = path->SetNode(physicalBlock, -1); 437*3216460dShyche if (node == NULL) 438*3216460dShyche return B_NO_MEMORY; 439*3216460dShyche slot = node->ItemCount() - 1; 440*3216460dShyche level--; 441*3216460dShyche } while(level != 0); 442*3216460dShyche 443*3216460dShyche return B_OK; 444*3216460dShyche } 445*3216460dShyche 446*3216460dShyche 447*3216460dShyche status_t 448*3216460dShyche BTree::NextLeaf(Path* path) const 449*3216460dShyche { 450*3216460dShyche int level = 0; 451*3216460dShyche int slot; 452*3216460dShyche Node* node = NULL; 453*3216460dShyche // iterate to the root until satisfy the condition 454*3216460dShyche while (true) { 455*3216460dShyche node = path->GetNode(level, &slot); 456*3216460dShyche if (node == NULL || slot < node->ItemCount() - 1) 457*3216460dShyche break; 458*3216460dShyche level++; 459*3216460dShyche } 460*3216460dShyche 461*3216460dShyche // the current leaf is already the right most leaf or 462*3216460dShyche // path was not initialized 463*3216460dShyche if (node == NULL) 464*3216460dShyche return B_ENTRY_NOT_FOUND; 465*3216460dShyche 466*3216460dShyche path->Move(level, BTREE_FORWARD); 467*3216460dShyche fsblock_t physicalBlock; 468*3216460dShyche // change all nodes below this level and slot to the beginning 469*3216460dShyche do { 470*3216460dShyche status_t status = fVolume->FindBlock( 471*3216460dShyche node->Index(slot)->LogicalAddress(), physicalBlock); 472*3216460dShyche if (status != B_OK) 473*3216460dShyche return status; 474*3216460dShyche 475*3216460dShyche node = path->SetNode(physicalBlock, 0); 476*3216460dShyche if (node == NULL) 477*3216460dShyche return B_NO_MEMORY; 478*3216460dShyche slot = 0; 479*3216460dShyche level--; 480*3216460dShyche } while(level != 0); 481*3216460dShyche 482*3216460dShyche return B_OK; 483299aba38Shyche } 484299aba38Shyche 485299aba38Shyche 486fc4a1e78Shyche status_t 487fc4a1e78Shyche BTree::SetRoot(off_t logical, fsblock_t* block) 488fc4a1e78Shyche { 489fc4a1e78Shyche if (block != NULL) { 490fc4a1e78Shyche fRootBlock = *block; 491370ee09fShyche //TODO: mapping physical block -> logical address 492fc4a1e78Shyche } else { 493370ee09fShyche fLogicalRoot = logical; 494fc4a1e78Shyche if (fVolume->FindBlock(logical, fRootBlock) != B_OK) { 495fc4a1e78Shyche ERROR("Find() unmapped block %" B_PRId64 "\n", fRootBlock); 496fc4a1e78Shyche return B_ERROR; 497fc4a1e78Shyche } 498fc4a1e78Shyche } 499fc4a1e78Shyche return B_OK; 500fc4a1e78Shyche } 501fc4a1e78Shyche 502fc4a1e78Shyche 503299aba38Shyche void 504299aba38Shyche BTree::_AddIterator(TreeIterator* iterator) 505299aba38Shyche { 506299aba38Shyche MutexLocker _(fIteratorLock); 507299aba38Shyche fIterators.Add(iterator); 508299aba38Shyche } 509299aba38Shyche 510299aba38Shyche 511299aba38Shyche void 512299aba38Shyche BTree::_RemoveIterator(TreeIterator* iterator) 513299aba38Shyche { 514299aba38Shyche MutexLocker _(fIteratorLock); 515299aba38Shyche fIterators.Remove(iterator); 516299aba38Shyche } 517299aba38Shyche 518299aba38Shyche 519299aba38Shyche // #pragma mark - 520299aba38Shyche 521299aba38Shyche 522299aba38Shyche TreeIterator::TreeIterator(BTree* tree, btrfs_key& key) 523299aba38Shyche : 524299aba38Shyche fTree(tree), 525299aba38Shyche fCurrentKey(key) 526299aba38Shyche { 527299aba38Shyche Rewind(); 528299aba38Shyche tree->_AddIterator(this); 529299aba38Shyche } 530299aba38Shyche 531299aba38Shyche 532299aba38Shyche TreeIterator::~TreeIterator() 533299aba38Shyche { 534299aba38Shyche if (fTree) 535299aba38Shyche fTree->_RemoveIterator(this); 536299aba38Shyche } 537299aba38Shyche 538299aba38Shyche 539299aba38Shyche /*! Iterates through the tree in the specified direction. 540299aba38Shyche */ 541299aba38Shyche status_t 542299aba38Shyche TreeIterator::Traverse(btree_traversing direction, btrfs_key& key, 54316de9db5Shyche void** value, uint32* size) 544299aba38Shyche { 545299aba38Shyche if (fTree == NULL) 546299aba38Shyche return B_INTERRUPTED; 547299aba38Shyche 548299aba38Shyche fCurrentKey.SetOffset(fCurrentKey.Offset() + direction); 549*3216460dShyche BTree::Path path(fTree); 550*3216460dShyche status_t status = fTree->_Find(&path, fCurrentKey, value, size, direction); 551299aba38Shyche if (status != B_OK) { 552299aba38Shyche TRACE("TreeIterator::Traverse() Find failed\n"); 553299aba38Shyche return B_ENTRY_NOT_FOUND; 554299aba38Shyche } 555299aba38Shyche 556299aba38Shyche return B_OK; 557299aba38Shyche } 558299aba38Shyche 559299aba38Shyche 560299aba38Shyche /*! just sets the current key in the iterator. 561299aba38Shyche */ 562299aba38Shyche status_t 563299aba38Shyche TreeIterator::Find(btrfs_key& key) 564299aba38Shyche { 565299aba38Shyche if (fTree == NULL) 566299aba38Shyche return B_INTERRUPTED; 567299aba38Shyche fCurrentKey = key; 568299aba38Shyche return B_OK; 569299aba38Shyche } 570299aba38Shyche 571299aba38Shyche 572299aba38Shyche void 573299aba38Shyche TreeIterator::Stop() 574299aba38Shyche { 575299aba38Shyche fTree = NULL; 576299aba38Shyche } 577