<commit_before>#pragma once

#include <boost/optional.hpp>
#include <boost/none.hpp>
#include <algorithm>

#include <bdtree.h>
#include "primitive_types.h"
#include "base_types.h"
#include "util.h"
#include "merge_operation.h"
#include <bdtree/config.h>

namespace bdtree {
    template<typename Key, typename Value>
    struct bdtree_iterator : public std::iterator<std::bidirectional_iterator_tag, const std::pair<Key, Value>> {
        typedef std::bidirectional_iterator_tag Category;
        boost::optional<operation_context<Key, Value>> context_;
        node_pointer<Key, Value>* current_ = nullptr;
        typename decltype(leaf_node<Key,Value>::array_)::iterator current_iterator_;
        key_compare<Key, Value> cmp_;
        bdtree_iterator(){}
        bdtree_iterator(operation_context<Key, Value> && context, decltype(current_) n, const Key & key)
            : context_(std::move(context)), current_(n) {
            assert(current_ != nullptr);
            current_iterator_ = std::lower_bound(current_->as_leaf()->array_.begin(), current_->as_leaf()->array_.end(), key, cmp_);
            while (current_iterator_ == current_->as_leaf()->array_.end()) {
                if (set_void_if_after())
                    return;
                current_ = get_next(*context_, current_);
                current_iterator_ = std::lower_bound(current_->as_leaf()->array_.begin(), current_->as_leaf()->array_.end(), key, cmp_);
            }
        }
        
        template <uint FakeParam = 1>
        erase_result erase_if_no_newer() {
            assert(!after());
            leaf_node<Key, Value>* leaf = current_->as_leaf();
            leaf_node<Key, Value>* nl = new leaf_node<Key, Value>(*leaf);
            size_t current_index = current_iterator_ - current_->as_leaf()->array_.begin();
            nl->array_.erase(nl->array_.begin() + current_index);
            std::vector<uint8_t> data;
            static_assert(CONSOLIDATE_AT == 0 && FakeParam == 1, "bdtree_iterator::erase_if_no_newer cannot correctly handle delta chains");
            assert(nl->deltas_.size() == 0);
            auto s = nl->serialized_size();
            if (s < MIN_NODE_SIZE) {
                merge_operation<Key, Value>::execute_merge(current_, leaf, *context_);
                return erase_result::Merged;
            }
            data = nl->serialize();
            physical_pointer pptr = context_->cache.get_next_physical_ptr();
            nl->leaf_pptr_ = pptr;
            auto rc_res = rc_write(context_->get_node_table().value, pptr.value_ptr(), pptr.length, reinterpret_cast<char*>(data.data()), data.size());
            assert(rc_res == STATUS_OK);
            ramcloud_reject_rules rules;
            rules.doesntExist = 1;
            rules.givenVersion = current_->rc_version_;
            rules.versionNeGiven = 1;
            uint64_t rc_version;
            auto last_tx_id = get_last_tx_id();
            rc_res = rc_write_with_reject(context_->get_ptr_table().value, current_->lptr_.value_ptr(), current_->lptr_.length, pptr.value_ptr(), pptr.length, &rules, &rc_version);
            if (rc_res == STATUS_WRONG_VERSION || rc_res == STATUS_OBJECT_DOESNT_EXIST) {
                delete nl;
                rc_res = rc_remove(context_->get_node_table().value, pptr.value_ptr(), pptr.length);
                return erase_result::Failed;
            }
            node_pointer<Key, Value>* np = new node_pointer<Key, Value>(current_->lptr_, pptr, rc_version);
            np->node_ = nl;
            static_assert(CONSOLIDATE_AT == 0 && FakeParam == 1, "bdtree_iterator::erase_if_no_newer cannot correctly handle delta chains");
            rc_res = rc_remove(context_->get_node_table().value, current_->ptr_.value_ptr(), current_->ptr_.length);
            assert(rc_res == STATUS_OK);
            if (!context_->cache.add_entry(np, last_tx_id)) {
                delete np;
                ++(*this);
            } else {
                current_ = np;
                if (current_->as_leaf()->array_.size() <= current_index) {
                    current_iterator_ = current_->as_leaf()->array_.end() - 1;
                    ++(*this);
                } else {
                    current_iterator_ = current_->as_leaf()->array_.begin() + current_index;
                }
            }
            return erase_result::Success;
        }

        void set_void() {
            current_ = nullptr;<commit_msg>delivery transaction should also work on empty new-order table<commit_after>#pragma once

#include <boost/optional.hpp>
#include <boost/none.hpp>
#include <algorithm>

#include <bdtree.h>
#include "primitive_types.h"
#include "base_types.h"
#include "util.h"
#include "merge_operation.h"
#include <bdtree/config.h>

namespace bdtree {
    template<typename Key, typename Value>
    struct bdtree_iterator : public std::iterator<std::bidirectional_iterator_tag, const std::pair<Key, Value>> {
        typedef std::bidirectional_iterator_tag Category;
        boost::optional<operation_context<Key, Value>> context_;
        node_pointer<Key, Value>* current_ = nullptr;
        typename decltype(leaf_node<Key,Value>::array_)::iterator current_iterator_;
        key_compare<Key, Value> cmp_;
        bdtree_iterator(){}
        bdtree_iterator(operation_context<Key, Value> && context, decltype(current_) n, const Key & key)
            : context_(std::move(context)), current_(n) {
            assert(current_ != nullptr);
            current_iterator_ = std::lower_bound(current_->as_leaf()->array_.begin(), current_->as_leaf()->array_.end(), key, cmp_);
            while (current_iterator_ == current_->as_leaf()->array_.end()) {
                if (set_void_if_after())
                    return;
                current_ = get_next(*context_, current_);
                current_iterator_ = std::lower_bound(current_->as_leaf()->array_.begin(), current_->as_leaf()->array_.end(), key, cmp_);
            }
        }
        
        template <uint FakeParam = 1>
        erase_result erase_if_no_newer() {
            assert(!after());
            leaf_node<Key, Value>* leaf = current_->as_leaf();
            leaf_node<Key, Value>* nl = new leaf_node<Key, Value>(*leaf);
            size_t current_index = current_iterator_ - current_->as_leaf()->array_.begin();
            nl->array_.erase(nl->array_.begin() + current_index);
            std::vector<uint8_t> data;
            static_assert(CONSOLIDATE_AT == 0 && FakeParam == 1, "bdtree_iterator::erase_if_no_newer cannot correctly handle delta chains");
            assert(nl->deltas_.size() == 0);
            auto s = nl->serialized_size();
            if (s < MIN_NODE_SIZE) {
                merge_operation<Key, Value>::execute_merge(current_, leaf, *context_);
                return erase_result::Merged;
            }
            data = nl->serialize();
            physical_pointer pptr = context_->cache.get_next_physical_ptr();
            nl->leaf_pptr_ = pptr;
            auto rc_res = rc_write(context_->get_node_table().value, pptr.value_ptr(), pptr.length, reinterpret_cast<char*>(data.data()), data.size());
            assert(rc_res == STATUS_OK);
            ramcloud_reject_rules rules;
            rules.doesntExist = 1;
            rules.givenVersion = current_->rc_version_;
            rules.versionNeGiven = 1;
            uint64_t rc_version;
            auto last_tx_id = get_last_tx_id();
            rc_res = rc_write_with_reject(context_->get_ptr_table().value, current_->lptr_.value_ptr(), current_->lptr_.length, pptr.value_ptr(), pptr.length, &rules, &rc_version);
            if (rc_res == STATUS_WRONG_VERSION || rc_res == STATUS_OBJECT_DOESNT_EXIST) {
                delete nl;
                rc_res = rc_remove(context_->get_node_table().value, pptr.value_ptr(), pptr.length);
                return erase_result::Failed;
            }
            node_pointer<Key, Value>* np = new node_pointer<Key, Value>(current_->lptr_, pptr, rc_version);
            np->node_ = nl;
            static_assert(CONSOLIDATE_AT == 0 && FakeParam == FakeParam, "bdtree_iterator::erase_if_no_newer cannot correctly handle delta chains");
            rc_res = rc_remove(context_->get_node_table().value, current_->ptr_.value_ptr(), current_->ptr_.length);
            assert(rc_res == STATUS_OK);
            if (!context_->cache.add_entry(np, last_tx_id)) {
                delete np;
                ++(*this);
            } else {
                current_ = np;
                if (current_->as_leaf()->array_.size() <= current_index) {
                    current_iterator_ = current_->as_leaf()->array_.end() - 1;
                    ++(*this);
                } else {
                    current_iterator_ = current_->as_leaf()->array_.begin() + current_index;
                }
            }
            return erase_result::Success;
        }

        void set_void() {
            current_ = nullptr;
{'fraction_non_alphanumeric': 0.1290719802977723, 'fraction_numerical': 0.0025747229374230383, 'mean_word_length': 2.4574303405572757, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 125, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '63033', 'n_tokens_mistral': 2637, 'n_tokens_neox': 2578, 'n_words': 475}