#include "rocksdb/db.h"
namespace ROCKSDB_NAMESPACE {
using MultiScanIterator = MultiScan::MultiScanIterator;
MultiScan::MultiScan(const ReadOptions& read_options,
const MultiScanArgs& scan_opts, DB* db,
ColumnFamilyHandle* cfh)
: read_options_(read_options), scan_opts_(scan_opts), db_(db), cfh_(cfh) {
bool slow_path = false;
if (scan_opts.GetScanRanges()[0].range.limit) {
upper_bound_ = *scan_opts.GetScanRanges()[0].range.limit;
read_options_.iterate_upper_bound = &upper_bound_;
} else {
read_options_.iterate_upper_bound = nullptr;
}
for (const auto& opts : scan_opts.GetScanRanges()) {
if (opts.range.limit.has_value() !=
scan_opts.GetScanRanges()[0].range.limit.has_value()) {
slow_path = true;
break;
}
}
db_iter_.reset(db->NewIterator(read_options_, cfh));
if (!slow_path) {
db_iter_->Prepare(scan_opts);
}
}
MultiScanIterator& MultiScanIterator::operator++() {
status_ = db_iter_->status();
if (!status_.ok()) {
throw MultiScanException(status_);
}
if (idx_ >= scan_opts_.size()) {
throw std::logic_error("Index out of range");
}
idx_++;
if (idx_ < scan_opts_.size()) {
if (scan_opts_[idx_].range.limit.has_value() !=
(read_options_.iterate_upper_bound != nullptr)) {
if (scan_opts_[idx_].range.limit) {
*upper_bound_ = *scan_opts_[idx_].range.limit;
read_options_.iterate_upper_bound = upper_bound_;
} else {
read_options_.iterate_upper_bound = nullptr;
}
db_iter_.reset(db_->NewIterator(read_options_, cfh_));
scan_.Reset(db_iter_.get());
} else if (scan_opts_[idx_].range.limit) {
*upper_bound_ = *scan_opts_[idx_].range.limit;
}
db_iter_->Seek(*scan_opts_[idx_].range.start);
status_ = db_iter_->status();
if (!status_.ok()) {
throw MultiScanException(status_);
}
}
return *this;
}
}