Skip to content

Unload unused data from DataStorage #143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 192 commits into
base: storage_data_unloading
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
192 commits
Select commit Hold shift + click to select a range
2985eec
DeltaZigZag and DeltaDeltaZigZag encodings
Apr 17, 2025
c32babe
encoding fix
Apr 23, 2025
9902f6e
tmp
Apr 23, 2025
17a681a
tmp benchmark
Apr 25, 2025
33d4b18
update bare_bones/encoding.h
Apr 25, 2025
56827c6
benchmark fix
Apr 29, 2025
15393b7
encoding changes
Apr 29, 2025
beddbb1
remove benchmark for another branch
Apr 29, 2025
bb0607e
Merge branch 'pp' into delta-zigzag-encoders
Apr 29, 2025
7dbe4b0
format fix
Apr 29, 2025
e1b88cd
Merge branch 'pp' into delta-zigzag-encoders
May 12, 2025
7e4e43e
Merge branch 'refs/heads/delta-zigzag-encoders' into snapshot-encoder
May 14, 2025
e6f0136
basic snapshot
May 14, 2025
12a5381
tmp
May 14, 2025
b30baae
remove finalized bitmap from dataStorage
May 19, 2025
4d60a84
non-const stream getter for unloadable encoders
May 19, 2025
01be041
trim lower bits for CompactBitSequence
May 19, 2025
844befc
unloader entrypoint
May 19, 2025
3cc5949
unloader tmp
May 19, 2025
6c55930
remove snapshot data structure
May 19, 2025
179716b
unloader refactoring
May 20, 2025
8cc034f
fix
May 21, 2025
9c7283f
empty loader test
May 21, 2025
3871aaf
change Sequence to CompactSequence in Unloader
May 22, 2025
fd57b6e
Loader/Unloader current
May 27, 2025
36335be
Loader correctly reads BitSequence
May 28, 2025
62faf73
unloader refactoring
Jun 2, 2025
3a9745d
outdated chunk merger merge only loaded series
Jun 2, 2025
1cec645
loader + loader tests
Jun 2, 2025
64c99fe
Loader/Unloader refactoring
Jun 2, 2025
1afb363
Merge branch 'pp' into snapshot-encoder
Jun 2, 2025
f3515f8
tidy fix
Jun 3, 2025
48df6cb
trim_lower_bytes fix
Jun 17, 2025
f5e13de
bit-unit manipulation
Jun 17, 2025
d83d6ec
unloader fixes
Jun 17, 2025
bc5a935
rework loader for sequential read
Jun 18, 2025
d4cf341
assorted fixes
Jun 18, 2025
97952c2
add common.h for both loader and unloader
Jun 18, 2025
c0a49f8
Merge branch 'pp' into snapshot-encoder
Jun 18, 2025
ee39ce1
Merge branch 'pp' into unloader-entrypoint
Jun 23, 2025
d198163
initial entrypoint
Jun 24, 2025
71f2b02
entrypoint tmp
Jun 25, 2025
3f0186c
queriers now mark queried series and stores series to load
Jun 25, 2025
c278595
inject Loader into queries routine
Jun 26, 2025
9f7de3d
fixes
Jun 26, 2025
fc04970
assorted fixes
Jun 26, 2025
277f225
querier and instant_querier small querier-loader-unloader tests
Jun 26, 2025
2062360
fix
Jun 26, 2025
50c4284
add Loader to chunk recoder
Jun 27, 2025
26f0f13
Merge branch 'pp' into snapshot-encoder
Jun 30, 2025
ac7423e
span saving to DataStorage fix
Jun 30, 2025
1248c56
review fixes
Jul 2, 2025
9d49669
used NewDataStorage function
cherep58 Jul 3, 2025
ef20e14
created UnloadedDataStorage
cherep58 Jul 4, 2025
631a38f
created Head.UnloadUnusedSeriesData method
cherep58 Jul 4, 2025
bf3c288
created UnloadedDataLoader
cherep58 Jul 4, 2025
765f7de
text fixes
Jul 7, 2025
724fa04
push_back_bytes optim
Jul 8, 2025
507bc88
move lock to task
u-veles-a Jul 8, 2025
3bfe318
tidy fix
Jul 8, 2025
866f1c3
some fix
u-veles-a Jul 8, 2025
3e62db1
tests fix
Jul 8, 2025
a4ae77a
bitset atomic set/reset
Jul 8, 2025
886e4eb
change roaring::Roaring to BareBones::Bitset
Jul 8, 2025
bc8fa44
entrypoint fix
Jul 8, 2025
6cfd7a8
review fix
Jul 8, 2025
f5fdaf6
Merge branch 'pp' into snapshot-encoder
Jul 8, 2025
efd78ec
added read_iterator
Jul 9, 2025
38424aa
fixes
Jul 9, 2025
086934b
change popcount == 0 check to empty() method
Jul 9, 2025
f6450d0
fix review
u-veles-a Jul 14, 2025
a66b8f7
atomic bitset fix
Jul 14, 2025
1e92dbe
Loader will merge outdated chunks only for freshly loaded series
Jul 14, 2025
71cbb32
Loader ctor update
Jul 14, 2025
a99de0c
fix review 2
u-veles-a Jul 14, 2025
0361752
change internal Loader infos from map to vector
Jul 14, 2025
e61ac12
Loader: buffer size validation
Jul 14, 2025
ec95c52
Merge branch 'pp' into lock_in_task
u-veles-a Jul 14, 2025
bafb45f
review assorted fixes
Jul 15, 2025
0b77498
move outdated_chunks.erase into OutdatedChunkMerger::merge(ls_id)
Jul 15, 2025
7a40d5e
Merge branch 'pp' into snapshot-encoder
Jul 15, 2025
7d4e4fa
minimal required fixes
Jul 16, 2025
c35b078
_Querier tests check storage_.queried_series_bitmap
Jul 16, 2025
10e18bf
set/reset on iterators + tests
Jul 16, 2025
206716d
BareBones::Bitset::create_read_iterator tests
Jul 16, 2025
5a7b651
BareBones::CompactSequence<>::create_read_iterator tests
Jul 16, 2025
1e029ad
Merge branch 'snapshot-encoder' of https://github.com/deckhouse/promp…
cherep58 Jul 17, 2025
ae4499b
BareBones::CompactSequence::size_in_bytes() fix
Jul 17, 2025
71de83a
Bitset tests fix
Jul 17, 2025
1914e62
Merge branch 'snapshot-encoder' of https://github.com/deckhouse/promp…
cherep58 Jul 17, 2025
54cd722
Bitset tests better coverage
Jul 17, 2025
84d62fe
(instant) querier tests move and fix
Jul 17, 2025
9f9aefa
Merge branch 'lock_in_task' of https://github.com/deckhouse/prompp in…
cherep58 Jul 17, 2025
8b3adfe
refactored UnloadedDataStorage test
cherep58 Jul 17, 2025
4e40971
small fix
u-veles-a Jul 17, 2025
0c64b13
Unloader tests better coverage
Jul 17, 2025
15c7b91
Loader tests better coverage
Jul 18, 2025
b38af07
renamed ForEachShard to ForEachSnapshot
cherep58 Jul 18, 2025
4f28d90
added lock in UnloadUnusedSeriesData method
cherep58 Jul 18, 2025
f31bd58
created Head::CreateDataStorageLoadAndQueryTask
cherep58 Jul 18, 2025
d8cefac
created GenericTask::SetShardsNumber
cherep58 Jul 21, 2025
1efed63
created Head::EnqueueOnShard
cherep58 Jul 21, 2025
2ea1875
Merge branch 'task_for_shard' of https://github.com/deckhouse/prompp …
cherep58 Jul 21, 2025
c643046
used EnqueueOnShard in Head::CreateDataStorageLoadAndQueryTask
cherep58 Jul 21, 2025
8a8afaa
refactored TaskWaiter
cherep58 Jul 21, 2025
fef2354
added data load support for DataStorage::Query method
cherep58 Jul 21, 2025
a3c6769
added data load support for DataStorage::InstantQuery method
cherep58 Jul 21, 2025
709a2f5
Querier concept and Querier Wrappers
Jul 22, 2025
65a8795
entrypoint changes
Jul 22, 2025
891368f
Loader from Slice of Queriers
Jul 22, 2025
e8e792e
Merge branch 'snapshot-encoder-loader' of https://github.com/deckhous…
cherep58 Jul 22, 2025
93c67a3
fixed compilation errors
cherep58 Jul 22, 2025
5139dc1
removed unused code
cherep58 Jul 22, 2025
3e3749f
created CBytes type and refactored HeadDataStorageSerializedChunks
cherep58 Jul 22, 2025
df6d3a5
added truncating unloaded data storage file at loading
cherep58 Jul 23, 2025
aa329fa
fixed out of bound bug in GenericTask
cherep58 Jul 23, 2025
6db0229
added flag for unload storage data by timer
cherep58 Jul 23, 2025
d0155ec
fixed bug in DataLoader
cherep58 Jul 23, 2025
97b2827
added writing format version in UnloadedDataStorage
cherep58 Jul 23, 2025
7856628
special Encoder for outdated chunks + OutdatedSampleEncoder disintegr…
Jul 23, 2025
81e5be4
don't unload chunks with stream's size < 1 byte
Jul 23, 2025
73ae6f7
remove Loader's buffer size validation
Jul 23, 2025
603218c
test for big outdated chunk
Jul 23, 2025
fc30748
include clean-up
Jul 23, 2025
40cf6a4
Merge branch 'pp' into snapshot-encoder
Jul 23, 2025
1ffb484
added unit tests for relabeler/querier/Querier
cherep58 Jul 23, 2025
71d459e
added unit tests for relabeler/querier/ChunkQuerier
cherep58 Jul 23, 2025
69f57b5
created LoaderVariantPtr
cherep58 Jul 24, 2025
517067b
added extra map to loader
Jul 24, 2025
1aaf7ec
wrap into a new class
Jul 24, 2025
27aeb38
created BatchIterator
cherep58 Jul 25, 2025
892d200
review fixes
Jul 25, 2025
965e9f6
created bindings for SeriesIdBatchIterator
cherep58 Jul 25, 2025
4117914
added unit test for BatchIteratorFixture
cherep58 Jul 25, 2025
f609eaa
UnorderedVector fixes
Jul 25, 2025
4e449f6
Loader::UnorderedVector tests
Jul 25, 2025
7b8e60b
Merge branch 'pp' into snapshot-encoder
Jul 25, 2025
5ba9afc
merge fixes
Jul 25, 2025
9138b3f
Merge branch 'snapshot-encoder' of https://github.com/deckhouse/promp…
cherep58 Jul 25, 2025
e5fabce
changed logic of using LsIdBatchIterator
cherep58 Jul 28, 2025
4461bc4
Merge branch 'storage_data_unloading' of https://github.com/deckhouse…
cherep58 Jul 28, 2025
339925f
Merge branch 'storage_data_unloading' of https://github.com/deckhouse…
cherep58 Jul 30, 2025
db9d0eb
refactored block writer
cherep58 Jul 31, 2025
0cd3879
created RevertableLoader and used it in BlockWriter in GO
cherep58 Aug 1, 2025
6bea26e
changed loader logic: load only unloaded series
cherep58 Aug 1, 2025
136bcd8
changed reverter logic: revert only not queried series
cherep58 Aug 1, 2025
0d4e3b6
renamed BlockWriter to Writer
cherep58 Aug 1, 2025
42b702e
refactored block.Writer input parameters
cherep58 Aug 1, 2025
c73eccf
removed lsIdBatchSize input parameter from block.Writer
cherep58 Aug 1, 2025
ffe953a
fixed bug in reverter logic
cherep58 Aug 4, 2025
5330191
moved mutex lock logic in BlockWriter
cherep58 Aug 4, 2025
400cddb
created blockWriters
cherep58 Aug 4, 2025
a389579
added latest_timestamp to return value in prompp_head_wal_decoder_dec…
cherep58 Aug 5, 2025
3bb2d95
refactored test for head loading
cherep58 Aug 5, 2025
b4230ba
refactored shard loader
cherep58 Aug 5, 2025
f3d6d77
1) added earliest_timestamp to return value in prompp_head_wal_decode…
cherep58 Aug 6, 2025
0838894
return create_timestamp and encode_timestamp instead of earliest_time…
cherep58 Aug 6, 2025
3288c98
split Unloader interface into 2 functions: create_snapshot and unload
cherep58 Aug 6, 2025
f35aa77
created bindings for series_data unloader and used it in GO
cherep58 Aug 6, 2025
e134f46
moved UnloadedDataStorage from cppbridge to relabeler/head
cherep58 Aug 6, 2025
edb30eb
added locks in UnloadedDataStorage
cherep58 Aug 6, 2025
ba5fdfe
created GO-binding for get queries series bitset
cherep58 Aug 7, 2025
ee1a09d
created QueriedSeriesStorageWriter and QueriedSeriesStorageReader
cherep58 Aug 7, 2025
cfe5e51
added ability to read empty bitset in QueriedSeriesStorageReader
cherep58 Aug 8, 2025
dd16601
created prompp_series_data_data_storage_queried_series_set_bitset GO-…
cherep58 Aug 11, 2025
f38bca2
1) used bool flag instead unload interval for data storage unloading
cherep58 Aug 11, 2025
749a385
split UnloadedStatStorage::Write into two methods
cherep58 Aug 11, 2025
5f42102
added flag validation before unloading data in timer
cherep58 Aug 11, 2025
dd618d2
added errors logging in Head::UnloadUnusedSeriesData
cherep58 Aug 11, 2025
e606f0f
fixed bug with queried_series_bitmap reallocation in DataStorage
cherep58 Aug 11, 2025
f9a64f2
Merge branch 'storage_data_unloading' of https://github.com/deckhouse…
cherep58 Aug 11, 2025
b2d81ac
fixed compilation error
cherep58 Aug 11, 2025
952f682
fixed compilation error
cherep58 Aug 11, 2025
e100a98
changed mechanism of bitset serialization in GO-bindings
cherep58 Aug 11, 2025
bb147c1
optimized memory allocations in ReadSegment method
cherep58 Aug 11, 2025
700c8c2
added logging for enabled unload data storage feature
cherep58 Aug 11, 2025
5b69b25
Merge branch 'pp' of https://github.com/deckhouse/prompp into snapsho…
cherep58 Aug 19, 2025
0b0391c
Merge branch 'storage_data_unloading' into snapshot-encoder-loader
cherep58 Aug 19, 2025
cac9e21
added Sync call in QueriedSeriesStorage::Write method
cherep58 Aug 19, 2025
db33ad3
added unit tests for UnloadedDataStorage
cherep58 Aug 19, 2025
8ce1d1e
added unit tests for QueriedSeriesStorage
cherep58 Aug 19, 2025
d084fe7
added unit tests for HeadLoadSuite
cherep58 Aug 21, 2025
91caa9f
changed UnloadedDataStorage work logic
cherep58 Aug 21, 2025
322faac
added unit test in HeadLoadSuite
cherep58 Aug 21, 2025
6742038
changed QueriedSeriesStorage work logic
cherep58 Aug 22, 2025
45a14e2
changed UnloadedDataStorage work logic
cherep58 Aug 22, 2025
cddd1d1
added unit tests for head loading
cherep58 Aug 22, 2025
ca2d910
removed logs
cherep58 Aug 22, 2025
051c7f5
Merge branch 'storage_data_unloading' of https://github.com/deckhouse…
cherep58 Aug 22, 2025
1003e07
added valid storage logic in QueriedSeriesStorage
cherep58 Aug 22, 2025
8019545
changed open file logic in storages
cherep58 Aug 22, 2025
7047738
fixes after merge
cherep58 Aug 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmd/prometheus/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ func main() {
// x3 ScrapeInterval timeout for write block
time.Duration(cfgFile.GlobalConfig.ScrapeInterval*3),
cfg.WalMaxSamplesPerSegment,
appender.UnloadDataStorage,
)
if err != nil {
level.Error(logger).Log("msg", "failed to create a receiver", "err", err)
Expand Down Expand Up @@ -2105,6 +2106,10 @@ func readPromPPFeatures(logger log.Logger) {
case "disable_commits_on_remote_write":
rwprocessor.AlwaysCommit = false
pphandler.OTLPAlwaysCommit = false

case "unload_data_storage":
appender.UnloadDataStorage = true
_ = level.Info(logger).Log("msg", "[FEATURE] Data storage unloading is enabled.")
}
}
}
9 changes: 4 additions & 5 deletions cmd/prompptool/walpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (cmd *cmdWALPPToBlock) Do(
level.Debug(logger).Log("msg", "catalog records", "len", len(headRecords))

var inputRelabelerConfig []*config.InputRelabelerConfig
bw := block.NewBlockWriter(workingDir, block.DefaultChunkSegmentSize, time.Duration(cmd.blockDuration), registerer)
bw := block.NewWriter(workingDir, block.DefaultChunkSegmentSize, time.Duration(cmd.blockDuration), registerer)
for _, headRecord := range headRecords {
if err := ctx.Err(); err != nil {
return err
Expand All @@ -99,6 +99,7 @@ func (cmd *cmdWALPPToBlock) Do(
0,
head.NoOpLastAppendedSegmentIDSetter{},
registerer,
time.Duration(0),
)
if err != nil {
level.Error(logger).Log(
Expand All @@ -116,10 +117,8 @@ func (cmd *cmdWALPPToBlock) Do(
tBlockWrite := h.CreateTask(
relabeler.BlockWrite,
func(shard relabeler.Shard) error {
shard.LSSLock()
defer shard.LSSUnlock()

return bw.Write(relabeler.NewBlock(shard.LSS().Raw(), shard.DataStorage().Raw()))
_, err := bw.Write(shard)
return err
},
relabeler.ForLSSTask,
)
Expand Down
12 changes: 10 additions & 2 deletions pp-pkg/receiver/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func NewReceiver(
headRetentionTimeout time.Duration,
writeTimeout time.Duration,
maxSegmentSize uint32,
unloadDataStorage bool,
) (*Receiver, error) {
if logger == nil {
logger = log.NewNopLogger()
Expand Down Expand Up @@ -170,25 +171,31 @@ func NewReceiver(
return nil, err
}

var unloadDataStorageInterval time.Duration
if unloadDataStorage {
unloadDataStorageInterval = appender.DefaultMergeDuration
}

headManager, err := headmanager.New(
dataDir,
clock,
headConfigStorage,
headCatalog,
maxSegmentSize,
registerer,
unloadDataStorageInterval,
)
if err != nil {
return nil, fmt.Errorf("failed to create head manager: %w", err)
}

activeHead, rotatedHeads, err := headManager.Restore(rotationInfo.BlockDuration)
activeHead, rotatedHeads, err := headManager.Restore(rotationInfo.BlockDuration, unloadDataStorageInterval)
if err != nil {
return nil, fmt.Errorf("failed to restore heads: %w", err)
}
readyNotifier.NotifyReady()
queryableStorage := appender.NewQueryableStorageWithWriteNotifier(
block.NewBlockWriter(dataDir, block.DefaultChunkSegmentSize, rotationInfo.BlockDuration, registerer),
block.NewWriter(dataDir, block.DefaultChunkSegmentSize, rotationInfo.BlockDuration, registerer),
registerer,
querier.NewMetrics(registerer, querier.QueryableStorageSource),
triggerNotifier,
Expand Down Expand Up @@ -228,6 +235,7 @@ func NewReceiver(
relabeler.NewRotateTimerWithSeed(clock, rotationInfo.BlockDuration, rotationInfo.Seed),
appender.NewConstantIntervalTimer(clock, commitInterval),
appender.NewConstantIntervalTimer(clock, appender.DefaultMergeDuration),
unloadDataStorage,
registerer,
),

Expand Down
41 changes: 35 additions & 6 deletions pp/bare_bones/bitset.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <numeric>

#include "bit.h"
#include "concepts.h"
#include "memory.h"
#include "streams.h"
#include "type_traits.h"
Expand All @@ -38,7 +39,7 @@ class Bitset {
if (__builtin_expect(size > std::numeric_limits<uint32_t>::max(), false))
std::abort();

const uint64_t size_in_uint64_elements = Bit::to_ceil_units<uint64_t>(size);
const auto size_in_uint64_elements = Bit::to_ceil_units<uint64_t>(size);

if (size_in_uint64_elements <= data_.size()) {
return;
Expand Down Expand Up @@ -186,21 +187,26 @@ class Bitset {
}

[[nodiscard]] PROMPP_ALWAYS_INLINE uint32_t get_write_size() const noexcept {
const uint32_t data_size_in_bytes = Bit::to_ceil_units<uint64_t>(size()) * sizeof(uint64_t);
const uint32_t data_size_in_bytes = memory_size_in_bytes();
return sizeof(data_size_in_bytes) + data_size_in_bytes;
}

template <OutputStream S>
PROMPP_ALWAYS_INLINE void write_to(S& stream) const noexcept {
const uint32_t data_size_in_bits = size();
const uint32_t data_size_in_bytes = Bit::to_ceil_units<uint64_t>(data_size_in_bits) * sizeof(uint64_t);
const uint32_t data_size_in_bytes = memory_size_in_bytes();

if constexpr (BareBones::concepts::has_reserve<S>) {
stream.reserve(sizeof(data_size_in_bits) + data_size_in_bytes);
}

stream.write(reinterpret_cast<const char*>(&data_size_in_bits), sizeof(data_size_in_bits));
stream.write(reinterpret_cast<const char*>(data_.begin()), data_size_in_bytes);
}

static PROMPP_ALWAYS_INLINE Iterator create_read_iterator(std::span<const uint8_t>& buffer) noexcept {
if (buffer.size() < sizeof(uint32_t)) [[unlikely]] {
return Iterator{};
return Iterator{nullptr, 0, 0};
}

uint32_t bit_count = 0;
Expand All @@ -210,17 +216,40 @@ class Bitset {
const uint32_t uint64_count = BareBones::Bit::to_ceil_units<uint64_t>(bit_count);
const uint32_t byte_count = uint64_count * sizeof(uint64_t);
if (buffer.size() < byte_count) [[unlikely]] {
return Iterator{};
return Iterator{nullptr, 0, 0};
}

const std::span bit_data(reinterpret_cast<const uint64_t*>(buffer.data()), uint64_count);
buffer = buffer.subspan(byte_count);

return Iterator(bit_data.data(), bit_count);
return Iterator(bit_data.data(), bit_count, 0);
}

[[nodiscard]] bool read_from(std::istream& stream) {
uint32_t bit_count{};
stream.read(reinterpret_cast<char*>(&bit_count), sizeof(uint32_t));
if (stream.gcount() != sizeof(uint32_t)) [[unlikely]] {
return false;
}

if (bit_count == 0) {
return true;
}

resize(bit_count);
const auto size_in_bytes = static_cast<std::streamsize>(memory_size_in_bytes(bit_count));
stream.read(reinterpret_cast<char*>(data_.begin()), size_in_bytes);

return stream.gcount() == size_in_bytes;
}

private:
PROMPP_ALWAYS_INLINE void set_size(uint32_t new_size) noexcept { data_.control_block().items_count = new_size; }

[[nodiscard]] static PROMPP_ALWAYS_INLINE size_t memory_size_in_bytes(uint32_t bytes) noexcept {
return Bit::to_ceil_units<uint64_t>(bytes) * sizeof(uint64_t);
}
[[nodiscard]] PROMPP_ALWAYS_INLINE size_t memory_size_in_bytes() const noexcept { return memory_size_in_bytes(size()); }
};

template <>
Expand Down
46 changes: 46 additions & 0 deletions pp/bare_bones/iterator.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#pragma once

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>

#include "preprocess.h"

namespace BareBones::iterator {

Expand All @@ -19,4 +24,45 @@ class OperationIterator {
Operation* operation_;
};

template <class Iterator, class IteratorSentinel>
class BatchIterator {
public:
using difference_type = typename Iterator::difference_type;
using iterator_category = std::input_iterator_tag;
using value_type = typename Iterator::value_type;
using pointer = value_type*;
using reference = value_type&;

PROMPP_ALWAYS_INLINE BatchIterator(Iterator iterator, uint32_t batch_size) noexcept : iterator_(std::move(iterator)), batch_size_(batch_size) {
assert(batch_size > 0);
}

[[nodiscard]] uint32_t batch_size() const noexcept { return batch_size_; }
void next_batch() { processed_ = 0; }

PROMPP_ALWAYS_INLINE BatchIterator& operator++() noexcept {
++processed_;
++iterator_;
return *this;
}

PROMPP_ALWAYS_INLINE BatchIterator operator++(int) noexcept {
const auto result = *this;
++*this;
return result;
}

auto operator*() const noexcept { return *iterator_; }
auto operator*() noexcept { return *iterator_; }
auto operator->() const noexcept { return iterator_.operator->(); }
auto operator->() noexcept { return iterator_.operator->(); }

PROMPP_ALWAYS_INLINE bool operator==(const IteratorSentinel& end) const noexcept { return processed_ == batch_size_ || iterator_ == end; }

private:
Iterator iterator_;
uint32_t batch_size_;
uint32_t processed_{};
};

}; // namespace BareBones::iterator
68 changes: 68 additions & 0 deletions pp/bare_bones/tests/bitset_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <algorithm>
#include <random>
#include <spanstream>
#include <string>
#include <vector>

Expand All @@ -9,6 +10,8 @@

namespace {

using std::operator""sv;

class BitsetFixture : public testing::Test {
protected:
BareBones::Bitset bs_;
Expand Down Expand Up @@ -358,4 +361,69 @@ TEST_F(BitsetCreateIteratorValidFixture, CreateReadIteratorValid) {
EXPECT_EQ(buffer.size(), 0);
}

class BitsetReadFromFixture : public testing::Test {
protected:
BareBones::Bitset bs_;
};

TEST_F(BitsetReadFromFixture, ReadSizeError) {
// Arrange
std::ispanstream stream{""};

// Act
const auto result = bs_.read_from(stream);

// Assert
EXPECT_FALSE(result);
}

TEST_F(BitsetReadFromFixture, ReadBytesError) {
// Arrange
std::ispanstream stream{"\x01\x00\x00\x00"sv};

// Act
const auto result = bs_.read_from(stream);

// Assert
EXPECT_FALSE(result);
}

TEST_F(BitsetReadFromFixture, ReadEmptyBitset) {
// Arrange
std::ispanstream stream{"\x00\x00\x00\x00"sv};

// Act
const auto result = bs_.read_from(stream);

// Assert
EXPECT_TRUE(result);
}

TEST_F(BitsetReadFromFixture, ReadSuccess) {
// Arrange
std::ispanstream stream{"\x01\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"sv};

// Act
const auto result = bs_.read_from(stream);

// Assert
EXPECT_TRUE(result);
EXPECT_EQ(1U, bs_.size());
EXPECT_TRUE(bs_.is_set(0));
}

TEST_F(BitsetReadFromFixture, OverwriteBitsetAfterRead) {
// Arrange
bs_.set({1, 2, 3, 4, 5});
std::ispanstream stream{"\x01\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"sv};

// Act
const auto result = bs_.read_from(stream);

// Assert
EXPECT_TRUE(result);
EXPECT_EQ(1U, bs_.size());
EXPECT_TRUE(bs_.is_set(0));
}

} // namespace
Loading
Loading