| 671 | } |
| 672 | |
| 673 | static fdb_status _fdb_iterator_prev(fdb_iterator *iterator) |
| 674 | { |
| 675 | int cmp; |
| 676 | void *key; |
| 677 | size_t keylen; |
| 678 | uint64_t offset; |
| 679 | hbtrie_result hr = HBTRIE_RESULT_SUCCESS; |
| 680 | struct docio_handle *dhandle; |
| 681 | struct snap_wal_entry *snap_item = NULL; |
| 682 | |
| 683 | if (iterator->direction == FDB_ITR_FORWARD) { |
| 684 | iterator->_offset = BLK_NOT_FOUND; // need to re-examine Trie/trees |
| 685 | if (!iterator->tree_cursor && iterator->tree_cursor_prev) { |
| 686 | // this only happens right after HANDLE operation |
| 687 | // (when seek is executed using a key larger than |
| 688 | // the largest key in WAL) |
| 689 | if (iterator->status == FDB_ITR_WAL) { |
| 690 | iterator->tree_cursor = avl_prev(iterator->tree_cursor_prev); |
| 691 | iterator->tree_cursor_prev = iterator->tree_cursor; |
| 692 | } else { |
| 693 | iterator->tree_cursor = iterator->tree_cursor_prev; |
| 694 | } |
| 695 | } else if (iterator->tree_cursor) { // on turning direction |
| 696 | if (iterator->status == FDB_ITR_WAL) { // skip 2 items |
| 697 | iterator->tree_cursor = avl_prev(iterator->tree_cursor_prev); |
| 698 | } else { // skip 1 item if the last doc was returned from the main index |
| 699 | iterator->tree_cursor = avl_prev(iterator->tree_cursor); |
| 700 | } |
| 701 | iterator->tree_cursor_prev = iterator->tree_cursor; |
| 702 | } |
| 703 | } |
| 704 | iterator->tree_cursor = iterator->tree_cursor_prev; |
| 705 | start: |
| 706 | key = iterator->_key; |
| 707 | dhandle = iterator->handle->dhandle; |
| 708 | |
| 709 | // retrieve from hb-trie |
| 710 | if (iterator->_offset == BLK_NOT_FOUND) { |
| 711 | // no key waiting for being returned |
| 712 | // get next key from hb-trie (or idtree) |
| 713 | struct docio_object _doc; |
| 714 | uint64_t _offset; |
| 715 | do { |
| 716 | hr = hbtrie_prev(iterator->hbtrie_iterator, key, |
| 717 | &iterator->_keylen, (void*)&iterator->_offset); |
| 718 | btreeblk_end(iterator->handle->bhandle); |
| 719 | iterator->_offset = _endian_decode(iterator->_offset); |
| 720 | if (!(iterator->opt & FDB_ITR_NO_DELETES) || |
| 721 | hr != HBTRIE_RESULT_SUCCESS) { |
| 722 | break; |
| 723 | } |
| 724 | // deletion check |
| 725 | memset(&_doc, 0x0, sizeof(struct docio_object)); |
| 726 | _offset = docio_read_doc_key_meta(dhandle, iterator->_offset, |
| 727 | &_doc, true); |
| 728 | if (_offset == iterator->_offset) { // read fail |
| 729 | continue; // get prev doc |
| 730 | } |
no test coverage detected