| 1644 | } |
| 1645 | |
| 1646 | static fdb_status _fdb_iterator_seq_prev(fdb_iterator *iterator) |
| 1647 | { |
| 1648 | size_t size_id, size_seq, seq_kv_len; |
| 1649 | uint8_t *seq_kv; |
| 1650 | uint64_t offset = BLK_NOT_FOUND; |
| 1651 | btree_result br = BTREE_RESULT_FAIL; |
| 1652 | hbtrie_result hr; |
| 1653 | struct docio_object _doc; |
| 1654 | struct docio_object _hbdoc; |
| 1655 | struct docio_handle *dhandle; |
| 1656 | struct snap_wal_entry *snap_item = NULL; |
| 1657 | fdb_seqnum_t seqnum; |
| 1658 | fdb_kvs_id_t kv_id; |
| 1659 | struct avl_node *cursor; |
| 1660 | |
| 1661 | size_id = sizeof(fdb_kvs_id_t); |
| 1662 | size_seq = sizeof(fdb_seqnum_t); |
| 1663 | seq_kv = alca(uint8_t, size_id + size_seq); |
| 1664 | |
| 1665 | // in forward iteration, cursor points to the next key to be returned |
| 1666 | // therefore, in return iteration, make cursor point to prev key |
| 1667 | if (iterator->direction == FDB_ITR_FORWARD) { |
| 1668 | if (iterator->status == FDB_ITR_IDX) { |
| 1669 | iterator->_offset = BLK_NOT_FOUND; // need to re-examine Trie/trees |
| 1670 | } |
| 1671 | if (iterator->tree_cursor) { // on turning direction |
| 1672 | if (iterator->status == FDB_ITR_WAL) { // skip 2 items |
| 1673 | iterator->tree_cursor = avl_prev(iterator->tree_cursor_prev); |
| 1674 | } else { // skip 1 item if the last doc was returned from main index |
| 1675 | iterator->tree_cursor = avl_prev(iterator->tree_cursor); |
| 1676 | } |
| 1677 | iterator->tree_cursor_prev = iterator->tree_cursor; |
| 1678 | } |
| 1679 | } |
| 1680 | iterator->tree_cursor = iterator->tree_cursor_prev; |
| 1681 | start_seq: |
| 1682 | seqnum = iterator->_seqnum; |
| 1683 | dhandle = iterator->handle->dhandle; |
| 1684 | |
| 1685 | if (iterator->_offset == BLK_NOT_FOUND || // was iterating over btree |
| 1686 | !iterator->tree_cursor) { // WAL exhausted |
| 1687 | if (iterator->handle->kvs) { // multi KV instance mode |
| 1688 | hr = hbtrie_prev(iterator->seqtrie_iterator, seq_kv, &seq_kv_len, |
| 1689 | (void *)&offset); |
| 1690 | if (hr == HBTRIE_RESULT_SUCCESS) { |
| 1691 | br = BTREE_RESULT_SUCCESS; |
| 1692 | buf2kvid(size_id, seq_kv, &kv_id); |
| 1693 | if (kv_id != iterator->handle->kvs->id) { |
| 1694 | // iterator is beyond the boundary |
| 1695 | br = BTREE_RESULT_FAIL; |
| 1696 | } |
| 1697 | memcpy(&seqnum, seq_kv + size_id, size_seq); |
| 1698 | } else { |
| 1699 | br = BTREE_RESULT_FAIL; |
| 1700 | } |
| 1701 | } else { |
| 1702 | br = btree_prev(iterator->seqtree_iterator, &seqnum, |
| 1703 | (void *)&offset); |
no test coverage detected