28 namespace cola_section_detail {
29 inline constexpr std::uint16_t
version = 3;
32 constexpr std::size_t
profile_slot(
unsigned route)
noexcept {
return 5 * route; }
33 constexpr std::size_t
rank_slot(
unsigned route)
noexcept {
return 10 + 2 * route; }
34 constexpr std::size_t
flags_slot(
unsigned route)
noexcept {
return 14 + route; }
35 constexpr std::size_t
cuts_slot(
unsigned route)
noexcept {
return 16 + route; }
38 std::array<section_detail::descriptor, section_count>
sections{};
47 inline std::span<std::byte const>
section(std::span<std::byte const> body,
48 directory const & layout, std::size_t slot) {
49 if (slot >=
section_count) error_detail::raise<std::out_of_range>(
"COLA section slot");
50 auto const & part = layout.
sections[slot];
51 if (part.offset > body.size() || part.length > body.size() - part.offset)
52 error_detail::raise<std::invalid_argument>(
"COLA section exceeds body");
53 return body.subspan(
static_cast<std::size_t
>(part.offset),
static_cast<std::size_t
>(part.length));
57 body.size() > std::numeric_limits<std::uint64_t>::max() - 7)
58 error_detail::raise<std::invalid_argument>(
"invalid COLA index container");
60 error_detail::raise<std::invalid_argument>(
"COLA index must occupy complete bytes");
61 for (
unsigned i = 0; i != 4; ++i)
62 if (std::to_integer<unsigned>(body[i]) !=
unsigned(
"IX03"[i]))
63 error_detail::raise<std::invalid_argument>(
"unexpected COLA index magic");
65 error_detail::raise<std::invalid_argument>(
"unsupported COLA index directory");
66 directory result{{},
file_detail::get(body, 8, 8), {}, {}, {}, {}, {},
section_detail::get_id(body, 88), {}, {}};
67 for (
unsigned route = 0; route != 2; ++route) {
76 error_detail::raise<std::invalid_argument>(
"invalid COLA target flag");
83 if (result.counts[0] > result.virtual_count || result.counts[1] > result.virtual_count - result.counts[0] ||
84 result.counts[0] + result.counts[1] != header.
record_count ||
85 (!
main && result.counts[0]) || (!
secondary && result.counts[1]))
86 error_detail::raise<std::invalid_argument>(
"COLA index count or target mismatch");
91 if (part.offset !=
section_detail::align(end) || part.offset > body.size() || part.length > body.size() - part.offset)
92 error_detail::raise<std::invalid_argument>(
"noncanonical COLA section range");
93 end = part.offset + part.length;
94 result.sections[i] = part;
96 if (end != body.size()) error_detail::raise<std::invalid_argument>(
"trailing COLA section bytes");
100 std::span<std::byte const> body,
directory const & layout,
unsigned route) {
101 auto metadata = profile_detail::initial_metadata<P, stream_role::borrowed>();
102 metadata.record_count = layout.
counts[route];
103 metadata.extent = layout.
extents[route];
105 metadata.common_value_width = 0;
107 auto part = [&](
unsigned offset) {
return section(body, layout, first + offset); };
108 auto count = metadata.record_count;
109 auto samples =
profile_detail::add(count / P::codec_block_size + (count % P::codec_block_size != 0), 1);
114 result.validate_offset_metadata();
128 converted_(std::move(other.converted_)),
active_(std::exchange(other.active_,
false)) {}
130 if (
this != &other) {
132 converted_ = std::move(other.converted_);
active_ = std::exchange(other.active_,
false);
136 template <
class Native,
class Main>
138 std::optional<blob_identity> main_id = {}, std::optional<object_id> secondary_id = {}) {
140 error_detail::raise<std::invalid_argument>(
"COLA encoding needs exact target identities");
142 auto & directory = result.directory_;
143 for (
unsigned i = 0; i != 4; ++i) directory[i] = std::byte(
"IX03"[i]);
158 for (
unsigned route = 0;
route != 2; ++
route) {
159 auto const & array = source.
borrowed(route);
160 auto const & metadata = array.metadata();
161 auto const & offsets = array.group_offsets();
162 result.header_.record_count =
profile_detail::add(result.header_.record_count, metadata.record_count);
165 file_detail::put(directory, 48 + 8 * route, 8, metadata.terminal_key_units);
168 result.sections_.push_back(array.bytes());
169 result.words(offsets.low); result.words(offsets.high); result.samples(offsets.samples); result.words(offsets.sparse);
171 for (
unsigned route = 0;
route != 2; ++
route) {
178 for (std::size_t i = 0; i != result.sections_.size(); ++i) {
188 template <
class Native,
class Main>
190 std::optional<blob_identity> = {}, std::optional<object_id> = {}) =
delete;
194 std::vector<std::span<std::
byte const>>
chunks() const & {
196 std::vector<std::span<std::byte const>> result;
197 result.reserve(2 *
sections_.size() + 1);
202 if (gap) result.push_back(std::span(
zero_).first(
static_cast<std::size_t
>(gap)));
203 result.push_back(bytes); end += gap + bytes.size();
207 std::vector<std::span<std::byte const>>
chunks() const && = delete;
209 std::vector<std::byte> body;
210 auto count = file_detail::body_bytes<P>(
header().extent);
211 if (count > body.max_size()) error_detail::raise<std::length_error>(
"COLA section body is too large");
212 body.reserve(
static_cast<std::size_t
>(count));
213 for (
auto part :
chunks()) body.insert(body.end(), part.begin(), part.end());
224 std::array<std::byte, cola_section_detail::directory_bytes>
directory_{};
231 if (!
active_) error_detail::raise<std::logic_error>(
"COLA encoding has no source");
234 if constexpr (std::endian::native == std::endian::little)
sections_.push_back(std::as_bytes(
words));
244 if constexpr (std::endian::native == std::endian::little)
sections_.push_back(std::as_bytes(
samples));
247 for (std::size_t i = 0; i !=
samples.size(); ++i) {
258 object_id const & native_id, std::optional<blob_identity> main_id = {}, std::optional<object_id> secondary_id = {}) {
262 object_id const &, std::optional<blob_identity> = {}, std::optional<object_id> = {}) =
delete;
271 auto body = source.
body();
275 std::array<borrowed_view, 2> profiles{cola_section_detail::profile<P>(body.bytes(),
layout, 0),
276 cola_section_detail::profile<P>(body.bytes(),
layout, 1)};
279 std::array<std::span<std::byte const>, 2> flags{part(14), part(15)};
280 std::array<word_view, 2> cuts{words(16), words(17)};
282 for (
unsigned route = 0; route != 2; ++route)
283 if (profiles[route].size() > std::numeric_limits<std::uint64_t>::max() - 7 ||
284 flags[route].size() != ((profiles[route].size() + 7) >> 3) || cuts[route].size() != groups)
285 error_detail::raise<std::invalid_argument>(
"COLA navigation shape mismatch");
286 return {std::move(source), std::move(body), std::move(
layout), profiles, ranks, flags, cuts};
306 std::optional<blob_identity>
const &
main_id() const && = delete;
312 std::span<std::
byte const>
section(std::
size_t slot) const & {
315 std::span<std::byte const>
section(std::size_t)
const && =
delete;
326 "nonzero COLA section alignment padding");
327 end =
static_cast<std::size_t
>(part.offset + part.length);
329 for (
unsigned route = 0; route != 2; ++route) {
333 for (std::uint64_t group = 0; group != groups; ++group) {
334 auto width = std::min<std::uint64_t>(P::group_size,
layout_.
virtual_count - group * P::group_size);
335 auto population =
ranks_[route].class_at(group);
336 auto other =
ranks_[1 - route].class_at(group);
337 if (population > width || other > width - population)
338 error_detail::raise<std::invalid_argument>(
"overlapping COLA rank populations");
339 builder.
append(population, width);
341 auto expected = builder.
finish();
342 if (expected.view().count() !=
profiles_[route].size())
343 error_detail::raise<std::invalid_argument>(
"COLA rank total mismatch");
346 if (
auto tail = (
profiles_[route].size() & 7))
347 if (std::to_integer<unsigned>(
flags_[route].back()) >> tail)
348 error_detail::raise<std::invalid_argument>(
"nonzero COLA false-borrow padding");
357 std::array<std::span<std::byte const>, 2>
flags_;
360 std::array<borrowed_view, 2> profiles, std::array<rank_view, 2> ranks,
361 std::array<std::span<std::byte const>, 2> flags, std::array<word_view, 2> cuts)
365 if (!
active()) error_detail::raise<std::logic_error>(
"COLA index has no mapping");
Declares dual-target main/secondary fractional indexes for COLA.
unsigned route(unsigned value)
Definition cola_index.h:37
constexpr std::size_t profile_slot(unsigned route) noexcept
Definition cola_sections.h:32
directory parse(file_header< P > const &header, std::span< std::byte const > body)
Definition cola_sections.h:55
constexpr std::size_t directory_bytes
Definition cola_sections.h:31
constexpr std::size_t section_count
Definition cola_sections.h:30
constexpr std::size_t flags_slot(unsigned route) noexcept
Definition cola_sections.h:34
constexpr std::uint16_t version
Definition cola_sections.h:29
constexpr std::size_t cuts_slot(unsigned route) noexcept
Definition cola_sections.h:35
constexpr std::size_t descriptor_offset
Definition cola_sections.h:30
profile_view< P, stream_role::borrowed > profile(std::span< std::byte const > body, directory const &layout, unsigned route)
Definition cola_sections.h:99
constexpr std::size_t rank_slot(unsigned route) noexcept
Definition cola_sections.h:33
std::span< std::byte const > section(std::span< std::byte const > body, directory const &layout, std::size_t slot)
Definition cola_sections.h:47
void put(std::span< std::byte > bytes, std::size_t at, unsigned width, std::uint64_t value) noexcept
Definition file.h:70
void validate_metadata(file_header< P > const &header)
Definition file.h:93
std::uint64_t get(std::span< std::byte const > bytes, std::size_t at, unsigned width) noexcept
Definition file.h:65
std::uint64_t add(std::uint64_t a, std::uint64_t b)
Definition profile.h:39
std::uint64_t multiply(std::uint64_t a, std::uint64_t b)
Definition profile.h:44
object_id get_id(std::span< std::byte const > bytes, std::size_t at)
Definition sections.h:83
std::uint64_t align(std::uint64_t value) noexcept
Definition sections.h:68
void scan_profile(profile_view< P, Role > const &view)
Definition sections.h:179
void put_id(std::span< std::byte > bytes, std::size_t at, object_id const &id)
Definition sections.h:75
void equal_words(word_view actual, std::span< std::uint64_t const > expected, char const *message)
Definition sections.h:174
void zero(std::span< std::byte const > bytes, char const *message)
Definition sections.h:71
Definition active_engine.h:18
encoded_cola_sections< P > encode_cola_sections(cola_index< P, Native, Main > const &source, object_id const &native_id, std::optional< blob_identity > main_id={}, std::optional< object_id > secondary_id={})
Definition cola_sections.h:256
file_open_mode
Definition file.h:32
std::vector< std::byte > encode_file(file_header< P > const &header, std::span< std::byte const > body)
Definition file.h:221
Encodes portable blob sections and retains mmap-backed profile directories.
Definition cola_index.h:114
Definition cola_index.h:315
borrowed_array const & borrowed(unsigned route) const &
Definition cola_index.h:341
main_pointer main_target() const noexcept
Definition cola_index.h:357
std::span< std::uint64_t const > cut_lcps(unsigned route) const &
Definition cola_index.h:353
std::span< std::byte const > false_borrow_bits(unsigned route) const &
Definition cola_index.h:349
rank_groups< group_size > const & interleave(unsigned route) const &
Definition cola_index.h:345
std::uint64_t virtual_size() const noexcept
Definition cola_index.h:359
native_pointer secondary_target() const noexcept
Definition cola_index.h:358
Definition cola_sections.h:37
std::array< std::uint64_t, 2 > terminal_units
Definition cola_sections.h:40
std::array< section_detail::descriptor, section_count > sections
Definition cola_sections.h:38
std::optional< object_id > secondary_id
Definition cola_sections.h:44
std::optional< blob_identity > main_id
Definition cola_sections.h:43
object_id native_id
Definition cola_sections.h:42
std::array< unsigned, 2 > low_widths
Definition cola_sections.h:41
std::array< std::uint64_t, 2 > extents
Definition cola_sections.h:40
std::array< std::uint64_t, 2 > universes
Definition cola_sections.h:40
std::array< std::uint64_t, 2 > counts
Definition cola_sections.h:40
std::uint64_t virtual_count
Definition cola_sections.h:39
Definition elias_fano.h:195
Definition elias_fano.h:212
Definition cola_sections.h:122
void samples(std::span< elias_fano_sample const > samples)
Definition cola_sections.h:241
encoded_cola_sections & operator=(encoded_cola_sections const &)=delete
std::vector< std::span< std::byte const > > sections_
Definition cola_sections.h:226
std::vector< std::byte > materialize() const
Definition cola_sections.h:208
encoded_cola_sections(encoded_cola_sections const &)=delete
std::array< std::byte, 8 > zero_
Definition cola_sections.h:225
std::vector< std::span< std::byte const > > chunks() const &&=delete
P policy_type
Definition cola_sections.h:123
std::array< std::byte, cola_section_detail::directory_bytes > directory_
Definition cola_sections.h:224
file_header< P > header_
Definition cola_sections.h:223
std::vector< std::span< std::byte const > > chunks() const &
Definition cola_sections.h:194
bool active_
Definition cola_sections.h:228
encoded_cola_sections(encoded_cola_sections &&other) noexcept
Definition cola_sections.h:126
encoded_cola_sections()=default
object_seal_receipt seal(std::filesystem::path const &root, object_id const &id, object_attempt_id const &attempt) const
Definition cola_sections.h:216
void words(std::span< std::uint64_t const > words)
Definition cola_sections.h:233
void require_active() const
Definition cola_sections.h:230
static encoded_cola_sections from(cola_index< P, Native, Main > const &&, object_id const &, std::optional< blob_identity >={}, std::optional< object_id >={})=delete
std::vector< std::vector< std::byte > > converted_
Definition cola_sections.h:227
file_header< P > const & header() const &
Definition cola_sections.h:192
static encoded_cola_sections from(cola_index< P, Native, Main > const &source, object_id const &native_id, std::optional< blob_identity > main_id={}, std::optional< object_id > secondary_id={})
Definition cola_sections.h:137
file_header< P > const & header() const &&=delete
encoded_cola_sections & operator=(encoded_cola_sections &&other) noexcept
Definition cola_sections.h:129
file_header< P > header() const
Definition file.h:268
mapped_slice body() const
Definition file.h:269
Definition cola_sections.h:266
static mapped_cola_index from_slice(mapped_slice source, file_open_mode mode=file_open_mode::checked)
Definition cola_sections.h:289
static mapped_cola_index open(file< P > source)
Definition cola_sections.h:270
file< P > source_
Definition cola_sections.h:352
object_id const & native_id() const &&=delete
std::span< std::byte const > section(std::size_t slot) const &
Definition cola_sections.h:312
std::optional< object_id > const & secondary_id() const &
Definition cola_sections.h:307
borrowed_view borrowed(unsigned) const &&=delete
std::array< word_view, 2 > cuts_
Definition cola_sections.h:358
word_view cut_lcps(unsigned) const &&=delete
void require_active() const
Definition cola_sections.h:364
mapped_slice body_
Definition cola_sections.h:353
bool active() const noexcept
Definition cola_sections.h:292
std::span< std::byte const > false_borrow_bits(unsigned) const &&=delete
cola_section_detail::directory const & layout() const &
Definition cola_sections.h:310
static mapped_cola_index open(std::filesystem::path const &path)
Definition cola_sections.h:288
std::optional< blob_identity > const & main_id() const &&=delete
rank_groups_view< P::group_size > rank_view
Definition cola_sections.h:269
P policy_type
Definition cola_sections.h:267
rank_view interleave(unsigned route) const &
Definition cola_sections.h:295
std::uint64_t virtual_size() const
Definition cola_sections.h:309
std::array< rank_view, 2 > ranks_
Definition cola_sections.h:356
word_view cut_lcps(unsigned route) const &
Definition cola_sections.h:301
cola_section_detail::directory const & layout() const &&=delete
std::span< std::byte const > section(std::size_t) const &&=delete
std::span< std::byte const > false_borrow_bits(unsigned route) const &
Definition cola_sections.h:297
cola_index_view< P > view(profile_view< P, stream_role::native > native) const &
Definition cola_sections.h:316
borrowed_view borrowed(unsigned route) const &
Definition cola_sections.h:293
std::optional< object_id > const & secondary_id() const &&=delete
std::array< borrowed_view, 2 > profiles_
Definition cola_sections.h:355
std::optional< blob_identity > const & main_id() const &
Definition cola_sections.h:305
mapped_cola_index(file< P > source, mapped_slice body, cola_section_detail::directory layout, std::array< borrowed_view, 2 > profiles, std::array< rank_view, 2 > ranks, std::array< std::span< std::byte const >, 2 > flags, std::array< word_view, 2 > cuts)
Definition cola_sections.h:359
void scan() const
Definition cola_sections.h:320
std::array< std::span< std::byte const >, 2 > flags_
Definition cola_sections.h:357
cola_index_view< P > view(profile_view< P, stream_role::native >) const &&=delete
rank_view interleave(unsigned) const &&=delete
cola_section_detail::directory layout_
Definition cola_sections.h:354
object_id const & native_id() const &
Definition cola_sections.h:303
Definition mapped_file.h:81
std::span< std::byte const > bytes() const &noexcept
Definition mapped_file.h:99
bool empty() const noexcept
Definition mapped_file.h:97
Definition object_writer.h:39
Definition object_path.h:38
Definition object_writer.h:88
static object_seal_receipt seal(std::filesystem::path const &root, object_id const &id, object_attempt_id const &attempt, file_header< P > const &header, std::span< std::span< std::byte const > const > chunks, Ops &ops)
Definition object_writer.h:164
static profile_view from_sections(std::span< std::byte const > bytes, elias_fano_view offsets, profile_metadata metadata)
Definition profile.h:708
Definition rank_groups.h:283
std::uint64_t group_count() const noexcept
Definition rank_groups.h:302
rank_groups< K > finish()
Definition rank_groups.h:330
void append(std::uint64_t population, std::uint64_t width=K)
Definition rank_groups.h:305
std::vector< std::uint64_t > checkpoints
Definition rank_groups.h:275
std::vector< std::uint64_t > classes
Definition rank_groups.h:274
static sample_view little_endian(std::span< std::byte const > bytes)
Definition word_view.h:92
Definition word_view.h:31
static word_view little_endian(std::span< std::byte const > bytes)
Definition word_view.h:36