From 3a0e6783d65672f9efa20e8d2f5307850fe744c3 Mon Sep 17 00:00:00 2001 From: Sebastian Hiebl Date: Sun, 12 Nov 2023 18:45:16 +0100 Subject: [PATCH] fix Contiguity + add test cases --- src/ChunkedJournal.hpp | 49 +++++++++++++++++------------------ test/ChunkedJournal_test.cpp | 50 ++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/ChunkedJournal.hpp b/src/ChunkedJournal.hpp index 73314cf..c28afe2 100644 --- a/src/ChunkedJournal.hpp +++ b/src/ChunkedJournal.hpp @@ -13,17 +13,18 @@ namespace jess { +enum class Adjacency { + NON_ADJACENT, + AFTER_CURRENT, + BEFORE_CURRENT, +}; + enum class Contiguity { CONTIGUOUS, NON_CONTIGUOUS, OVERLAPPING, }; -enum class InsertPosition { - BEFORE, - AFTER, -}; - struct Chunk { std::map lowestIdsInChunk{}; std::map highestIdsInChunk{}; @@ -52,7 +53,7 @@ class ChunkedJournal const auto& getChunks() const { return m_chunks; } private: - auto createChunkAtCurrentPosition( const InsertPosition insertPos, const Contiguity contiguity ) -> decltype( m_chunks.begin() ) + auto createChunkAtCurrentPosition( const Adjacency adjacency ) -> decltype( m_chunks.begin() ) { Chunk newChunk{ {}, {}, {} }; @@ -84,27 +85,23 @@ class ChunkedJournal } auto insertIt = m_pCurrentChunk; - if ( insertPos == InsertPosition::AFTER ) + if ( adjacency == Adjacency::AFTER_CURRENT ) { std::advance( insertIt, 1 ); } auto newChunkIt = m_chunks.insert( insertIt, std::move( newChunk ) ); - if ( insertPos == InsertPosition::BEFORE ) + if ( adjacency == Adjacency::BEFORE_CURRENT ) { - newChunkIt->contiguityEnd = contiguity; - if ( m_pCurrentChunk != m_chunks.end() ) - { - m_pCurrentChunk->contiguityBeginning = contiguity; - } + assert( m_pCurrentChunk != m_chunks.end() ); + newChunkIt->contiguityEnd = Contiguity::CONTIGUOUS; + m_pCurrentChunk->contiguityBeginning = Contiguity::CONTIGUOUS; } - else if ( insertPos == InsertPosition::AFTER ) + else if ( adjacency == Adjacency::AFTER_CURRENT ) { - if ( m_pCurrentChunk != m_chunks.end() ) - { - m_pCurrentChunk->contiguityEnd = contiguity; - } - newChunkIt->contiguityBeginning = contiguity; + assert( m_pCurrentChunk != m_chunks.end() ); + m_pCurrentChunk->contiguityEnd = Contiguity::CONTIGUOUS; + newChunkIt->contiguityBeginning = Contiguity::CONTIGUOUS; } return newChunkIt; @@ -127,7 +124,7 @@ class ChunkedJournal return ret; } - void loadChunkAtCurrentPosition( const InsertPosition insertPos, const Contiguity contiguity ) + void loadChunkAtCurrentPosition( const Adjacency adjacency ) { const auto seqid = m_journal.getSeqid(); if ( auto chunks = getChunksBySeqid( seqid ); !chunks.empty() ) @@ -136,7 +133,7 @@ class ChunkedJournal } else { - m_pCurrentChunk = createChunkAtCurrentPosition( insertPos, contiguity ); + m_pCurrentChunk = createChunkAtCurrentPosition( adjacency ); } } @@ -145,7 +142,7 @@ class ChunkedJournal { m_journal.seekToBof(); m_journal.next(); - loadChunkAtCurrentPosition( InsertPosition::BEFORE, Contiguity::CONTIGUOUS ); + loadChunkAtCurrentPosition( Adjacency::NON_ADJACENT ); m_uLineOffsetInChunk = 0; } @@ -153,7 +150,7 @@ class ChunkedJournal { m_journal.seekToEof(); m_journal.next(); - loadChunkAtCurrentPosition( InsertPosition::AFTER, Contiguity::CONTIGUOUS ); + loadChunkAtCurrentPosition( Adjacency::NON_ADJACENT ); m_uLineOffsetInChunk = m_uChunkSize - 1; } @@ -173,14 +170,14 @@ class ChunkedJournal const size_t uNumChunksToSkip = uNewOffsetRelativeToEndOfCurrentChunk / m_uChunkSize; m_uLineOffsetInChunk = uNewOffsetRelativeToEndOfCurrentChunk - uNumChunksToSkip * m_uChunkSize; - if ( const size_t uLinesToSeek = uNumChunksToSkip * m_uChunkSize; uLinesToSeek > 0) + if ( const size_t uLinesToSeek = uNumChunksToSkip * m_uChunkSize; uLinesToSeek > 0 ) { m_journal.seekLinesForward( uLinesToSeek ); m_journal.next(); } - const Contiguity contiguity = uNumChunksToSkip == 0 ? Contiguity::CONTIGUOUS : Contiguity::NON_CONTIGUOUS; - loadChunkAtCurrentPosition( InsertPosition::AFTER, contiguity ); + const Adjacency adjacency = uNumChunksToSkip == 0 ? Adjacency::AFTER_CURRENT : Adjacency::NON_ADJACENT; + loadChunkAtCurrentPosition( adjacency ); return; } diff --git a/test/ChunkedJournal_test.cpp b/test/ChunkedJournal_test.cpp index e6ccc34..a078c08 100644 --- a/test/ChunkedJournal_test.cpp +++ b/test/ChunkedJournal_test.cpp @@ -68,6 +68,8 @@ TEST_CASE( "ChunkedJournal(1) load BOF" ) REQUIRE( chunks.size() == 1 ); const jess::Chunk& firstChunk = chunks.front(); + CHECK( firstChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( firstChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); checkSequence( firstChunk, 1, 0 ); SUBCASE( "seeking to BOF shall again shall not change anything" ) @@ -85,9 +87,13 @@ TEST_CASE( "ChunkedJournal(1) load BOF" ) REQUIRE_MESSAGE( &chunks.front() == &firstChunk, "the first chunk shall remain at the first position" ); checkSequence( firstChunk, 1, 0 ); + CHECK( firstChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( firstChunk.contiguityEnd == jess::Contiguity::CONTIGUOUS ); const jess::Chunk& secondChunk = chunks2.back(); checkSequence( secondChunk, 1, 1 ); + CHECK( secondChunk.contiguityBeginning == jess::Contiguity::CONTIGUOUS ); + CHECK( secondChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); } } @@ -100,6 +106,8 @@ TEST_CASE( "ChunkedJournal(2) load BOF" ) const jess::Chunk& firstChunk = chunks.front(); checkSequence( firstChunk, 2, 0 ); + CHECK( firstChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( firstChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); SUBCASE( "seeking to BOF shall again shall not change anything" ) { @@ -116,6 +124,8 @@ TEST_CASE( "ChunkedJournal(2) load BOF" ) REQUIRE( chunks2.size() == 1 ); REQUIRE_MESSAGE( &chunks.front() == &firstChunk, "the first chunk shall remain at the first position" ); checkSequence( chunks.front(), 2, 0 ); + CHECK( firstChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( firstChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); } SUBCASE( "advance another line" ) @@ -127,6 +137,11 @@ TEST_CASE( "ChunkedJournal(2) load BOF" ) checkSequence( chunks.front(), 2, 0 ); checkSequence( chunks.back(), 2, 2 ); + + CHECK( chunks.front().contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( chunks.front().contiguityEnd == jess::Contiguity::CONTIGUOUS ); + CHECK( chunks.back().contiguityBeginning == jess::Contiguity::CONTIGUOUS ); + CHECK( chunks.back().contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); } } @@ -139,6 +154,11 @@ TEST_CASE( "ChunkedJournal(2) load BOF" ) checkSequence( chunks.front(), 2, 0 ); checkSequence( chunks.back(), 2, 2 ); + + CHECK( chunks.front().contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( chunks.front().contiguityEnd == jess::Contiguity::CONTIGUOUS ); + CHECK( chunks.back().contiguityBeginning == jess::Contiguity::CONTIGUOUS ); + CHECK( chunks.back().contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); } } @@ -150,6 +170,8 @@ TEST_CASE( "ChunkedJournal(3) load BOF" ) REQUIRE( chunks.size() == 1 ); checkSequence( chunks.front(), 3, 0 ); + CHECK( chunks.front().contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( chunks.front().contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); } TEST_CASE( "ChunkedJournal(1) load EOF" ) @@ -158,16 +180,40 @@ TEST_CASE( "ChunkedJournal(1) load EOF" ) sut.seekToEof(); const std::list& chunks = sut.getChunks(); REQUIRE( chunks.size() == 1 ); - checkSequence( chunks.front(), 1, 9 ); + const jess::Chunk& lastChunk = chunks.front(); + checkSequence( lastChunk, 1, 9 ); + CHECK( lastChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( lastChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); SUBCASE( "seek to BOF" ) { sut.seekToBof(); REQUIRE( chunks.size() == 2 ); - checkSequence( chunks.front(), 1, 0 ); + const jess::Chunk& firstChunk = chunks.front(); + checkSequence( firstChunk, 1, 0 ); + CHECK( firstChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( firstChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( lastChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( lastChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); SUBCASE( "load next line" ) { + sut.seekLines( 1 ); + REQUIRE( chunks.size() == 3 ); + auto it = chunks.begin(); + std::advance( it, 1 ); + const jess::Chunk& secondChunk = *it; + REQUIRE( &secondChunk != &firstChunk ); + REQUIRE( &secondChunk != &lastChunk ); + checkSequence( secondChunk, 1, 1 ); + CHECK( firstChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( firstChunk.contiguityEnd == jess::Contiguity::CONTIGUOUS ); + CHECK( secondChunk.contiguityBeginning == jess::Contiguity::CONTIGUOUS ); + CHECK( secondChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( lastChunk.contiguityBeginning == jess::Contiguity::NON_CONTIGUOUS ); + CHECK( lastChunk.contiguityEnd == jess::Contiguity::NON_CONTIGUOUS ); } } } + +// todo: check skipping a chunk