Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f435ead8 authored by David Anderson's avatar David Anderson Committed by Automerger Merge Worker
Browse files

Merge changes I7ec850b5,I62aa8c7b am: c274088e

parents b7f153e1 c274088e
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -28,9 +28,6 @@ static constexpr uint32_t kCowVersionMinor = 0;

static constexpr uint32_t kCowVersionManifest = 2;

static constexpr size_t BLOCK_SZ = 4096;
static constexpr size_t BLOCK_SHIFT = (__builtin_ffs(BLOCK_SZ) - 1);

// This header appears as the first sequence of bytes in the COW. All fields
// in the layout are little-endian encoded. The on-disk layout is:
//
+5 −3
Original line number Diff line number Diff line
@@ -63,7 +63,9 @@ class ICowReader {
    //
    // Partial reads are not possible unless |buffer_size| is less than the
    // operation block size.
    virtual ssize_t ReadData(const CowOperation& op, void* buffer, size_t buffer_size,
    //
    // The operation pointer must derive from ICowOpIter::Get().
    virtual ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
                             size_t ignore_bytes = 0) = 0;
};

@@ -77,7 +79,7 @@ class ICowOpIter {
    virtual bool AtEnd() = 0;

    // Read the current operation.
    virtual const CowOperation& Get() = 0;
    virtual const CowOperation* Get() = 0;

    // Advance to the next item.
    virtual void Next() = 0;
@@ -121,7 +123,7 @@ class CowReader final : public ICowReader {
    std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress = false) override;
    std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress = false) override;

    ssize_t ReadData(const CowOperation& op, void* buffer, size_t buffer_size,
    ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
                     size_t ignore_bytes = 0) override;

    CowHeader& GetHeader() override { return header_; }
+75 −75
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ class CowTest : public ::testing::Test {
};

// Helper to check read sizes.
static inline bool ReadData(CowReader& reader, const CowOperation& op, void* buffer, size_t size) {
static inline bool ReadData(CowReader& reader, const CowOperation* op, void* buffer, size_t size) {
    return reader.ReadData(op, buffer, size) == size;
}

@@ -80,7 +80,7 @@ TEST_F(CowTest, CopyContiguous) {

    size_t i = 0;
    while (!iter->AtEnd()) {
        auto op = &iter->Get();
        auto op = iter->Get();
        ASSERT_EQ(op->type, kCowCopyOp);
        ASSERT_EQ(op->compression, kCowCompressNone);
        ASSERT_EQ(op->data_length, 0);
@@ -126,7 +126,7 @@ TEST_F(CowTest, ReadWrite) {
    auto iter = reader.GetOpIter();
    ASSERT_NE(iter, nullptr);
    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();

    ASSERT_EQ(op->type, kCowCopyOp);
    ASSERT_EQ(op->compression, kCowCompressNone);
@@ -138,18 +138,18 @@ TEST_F(CowTest, ReadWrite) {

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_EQ(op->compression, kCowCompressNone);
    ASSERT_EQ(op->data_length, 4096);
    ASSERT_EQ(op->new_block, 50);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data);

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    // Note: the zero operation gets split into two blocks.
    ASSERT_EQ(op->type, kCowZeroOp);
@@ -160,7 +160,7 @@ TEST_F(CowTest, ReadWrite) {

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    ASSERT_EQ(op->type, kCowZeroOp);
    ASSERT_EQ(op->compression, kCowCompressNone);
@@ -205,7 +205,7 @@ TEST_F(CowTest, ReadWriteXor) {
    auto iter = reader.GetOpIter();
    ASSERT_NE(iter, nullptr);
    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();

    ASSERT_EQ(op->type, kCowCopyOp);
    ASSERT_EQ(op->compression, kCowCompressNone);
@@ -217,19 +217,19 @@ TEST_F(CowTest, ReadWriteXor) {

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    ASSERT_EQ(op->type, kCowXorOp);
    ASSERT_EQ(op->compression, kCowCompressNone);
    ASSERT_EQ(op->data_length, 4096);
    ASSERT_EQ(op->new_block, 50);
    ASSERT_EQ(op->source, 98314);  // 4096 * 24 + 10
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data);

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    // Note: the zero operation gets split into two blocks.
    ASSERT_EQ(op->type, kCowZeroOp);
@@ -240,7 +240,7 @@ TEST_F(CowTest, ReadWriteXor) {

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    ASSERT_EQ(op->type, kCowZeroOp);
    ASSERT_EQ(op->compression, kCowCompressNone);
@@ -274,7 +274,7 @@ TEST_F(CowTest, CompressGz) {
    auto iter = reader.GetOpIter();
    ASSERT_NE(iter, nullptr);
    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();

    std::string sink(data.size(), '\0');

@@ -282,7 +282,7 @@ TEST_F(CowTest, CompressGz) {
    ASSERT_EQ(op->compression, kCowCompressGz);
    ASSERT_EQ(op->data_length, 56);  // compressed!
    ASSERT_EQ(op->new_block, 50);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data);

    iter->Next();
@@ -329,14 +329,14 @@ TEST_P(CompressionTest, ThreadedBatchWrites) {

    int total_blocks = 0;
    while (!iter->AtEnd()) {
        auto op = &iter->Get();
        auto op = iter->Get();

        if (op->type == kCowXorOp) {
            total_blocks += 1;
            std::string sink(xor_data.size(), '\0');
            ASSERT_EQ(op->new_block, 50);
            ASSERT_EQ(op->source, 98314);  // 4096 * 24 + 10
            ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
            ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
            ASSERT_EQ(sink, xor_data);
        }

@@ -345,19 +345,19 @@ TEST_P(CompressionTest, ThreadedBatchWrites) {
            if (op->new_block == 100) {
                data.resize(options.block_size);
                std::string sink(data.size(), '\0');
                ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
                ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
                ASSERT_EQ(sink.size(), data.size());
                ASSERT_EQ(sink, data);
            }
            if (op->new_block == 6000) {
                data2.resize(options.block_size);
                std::string sink(data2.size(), '\0');
                ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
                ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
                ASSERT_EQ(sink, data2);
            }
            if (op->new_block == 9000) {
                std::string sink(data3.size(), '\0');
                ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
                ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
                ASSERT_EQ(sink, data3);
            }
        }
@@ -403,25 +403,25 @@ TEST_P(CompressionTest, NoBatchWrites) {

    int total_blocks = 0;
    while (!iter->AtEnd()) {
        auto op = &iter->Get();
        auto op = iter->Get();

        if (op->type == kCowReplaceOp) {
            total_blocks += 1;
            if (op->new_block == 50) {
                data.resize(options.block_size);
                std::string sink(data.size(), '\0');
                ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
                ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
                ASSERT_EQ(sink, data);
            }
            if (op->new_block == 3000) {
                data2.resize(options.block_size);
                std::string sink(data2.size(), '\0');
                ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
                ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
                ASSERT_EQ(sink, data2);
            }
            if (op->new_block == 5000) {
                std::string sink(data3.size(), '\0');
                ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
                ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
                ASSERT_EQ(sink, data3);
            }
        }
@@ -519,7 +519,7 @@ TEST_F(CowTest, ClusterCompressGz) {
    auto iter = reader.GetOpIter();
    ASSERT_NE(iter, nullptr);
    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();

    std::string sink(data.size(), '\0');

@@ -527,30 +527,30 @@ TEST_F(CowTest, ClusterCompressGz) {
    ASSERT_EQ(op->compression, kCowCompressGz);
    ASSERT_EQ(op->data_length, 56);  // compressed!
    ASSERT_EQ(op->new_block, 50);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data);

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    ASSERT_EQ(op->type, kCowClusterOp);

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    sink = {};
    sink.resize(data2.size(), '\0');
    ASSERT_EQ(op->compression, kCowCompressGz);
    ASSERT_EQ(op->data_length, 41);  // compressed!
    ASSERT_EQ(op->new_block, 51);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data2);

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();

    ASSERT_EQ(op->type, kCowClusterOp);

@@ -585,11 +585,11 @@ TEST_F(CowTest, CompressTwoBlocks) {

    std::string sink(options.block_size, '\0');

    auto op = &iter->Get();
    auto op = iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_EQ(op->compression, kCowCompressGz);
    ASSERT_EQ(op->new_block, 51);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
}

TEST_F(CowTest, GetSize) {
@@ -659,9 +659,9 @@ TEST_F(CowTest, AppendLabelSmall) {
    ASSERT_NE(iter, nullptr);

    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data);

    iter->Next();
@@ -669,16 +669,16 @@ TEST_F(CowTest, AppendLabelSmall) {
    sink.resize(data2.size(), '\0');

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 3);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data2);

    iter->Next();
@@ -722,14 +722,14 @@ TEST_F(CowTest, AppendLabelMissing) {
    ASSERT_NE(iter, nullptr);

    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 0);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowZeroOp);

    iter->Next();
@@ -780,7 +780,7 @@ TEST_F(CowTest, AppendExtendedCorrupted) {
    ASSERT_NE(iter, nullptr);

    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 5);

@@ -831,9 +831,9 @@ TEST_F(CowTest, AppendbyLabel) {
    ASSERT_NE(iter, nullptr);

    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data.substr(0, options.block_size));

    iter->Next();
@@ -841,33 +841,33 @@ TEST_F(CowTest, AppendbyLabel) {
    sink.resize(options.block_size, '\0');

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data.substr(options.block_size, 2 * options.block_size));

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 4);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowZeroOp);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowZeroOp);

    iter->Next();
    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 5);

@@ -912,59 +912,59 @@ TEST_F(CowTest, ClusterTest) {
    ASSERT_NE(iter, nullptr);

    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data.substr(0, options.block_size));

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 4);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowZeroOp);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowClusterOp);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowZeroOp);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 5);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowCopyOp);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowClusterOp);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 6);

@@ -1011,22 +1011,22 @@ TEST_F(CowTest, ClusterAppendTest) {
    ASSERT_NE(iter, nullptr);

    ASSERT_FALSE(iter->AtEnd());
    auto op = &iter->Get();
    auto op = iter->Get();
    ASSERT_EQ(op->type, kCowLabelOp);
    ASSERT_EQ(op->source, 50);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowReplaceOp);
    ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
    ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
    ASSERT_EQ(sink, data2);

    iter->Next();

    ASSERT_FALSE(iter->AtEnd());
    op = &iter->Get();
    op = iter->Get();
    ASSERT_EQ(op->type, kCowClusterOp);

    iter->Next();
@@ -1066,7 +1066,7 @@ AssertionResult WriteDataBlock(CowWriter* writer, uint64_t new_block, std::strin
    return AssertionSuccess();
}

AssertionResult CompareDataBlock(CowReader* reader, const CowOperation& op,
AssertionResult CompareDataBlock(CowReader* reader, const CowOperation* op,
                                 const std::string& data) {
    const auto& header = reader->GetHeader();

@@ -1124,12 +1124,12 @@ TEST_F(CowTest, ResumeMidCluster) {
        num_in_cluster++;
        max_in_cluster = std::max(max_in_cluster, num_in_cluster);

        if (op.type == kCowReplaceOp) {
        if (op->type == kCowReplaceOp) {
            num_replace++;

            ASSERT_EQ(op.new_block, num_replace);
            ASSERT_EQ(op->new_block, num_replace);
            ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace)));
        } else if (op.type == kCowClusterOp) {
        } else if (op->type == kCowClusterOp) {
            num_in_cluster = 0;
            num_clusters++;
        }
@@ -1185,12 +1185,12 @@ TEST_F(CowTest, ResumeEndCluster) {
        num_in_cluster++;
        max_in_cluster = std::max(max_in_cluster, num_in_cluster);

        if (op.type == kCowReplaceOp) {
        if (op->type == kCowReplaceOp) {
            num_replace++;

            ASSERT_EQ(op.new_block, num_replace);
            ASSERT_EQ(op->new_block, num_replace);
            ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace)));
        } else if (op.type == kCowClusterOp) {
        } else if (op->type == kCowClusterOp) {
            num_in_cluster = 0;
            num_clusters++;
        }
@@ -1236,12 +1236,12 @@ TEST_F(CowTest, DeleteMidCluster) {

        num_in_cluster++;
        max_in_cluster = std::max(max_in_cluster, num_in_cluster);
        if (op.type == kCowReplaceOp) {
        if (op->type == kCowReplaceOp) {
            num_replace++;

            ASSERT_EQ(op.new_block, num_replace);
            ASSERT_EQ(op->new_block, num_replace);
            ASSERT_TRUE(CompareDataBlock(&reader, op, "Block " + std::to_string(num_replace)));
        } else if (op.type == kCowClusterOp) {
        } else if (op->type == kCowClusterOp) {
            num_in_cluster = 0;
            num_clusters++;
        }
@@ -1278,7 +1278,7 @@ TEST_F(CowTest, BigSeqOp) {
        ASSERT_TRUE(!iter->AtEnd());
        const auto& op = iter->Get();

        ASSERT_EQ(op.new_block, seq_len - i);
        ASSERT_EQ(op->new_block, seq_len - i);

        iter->Next();
    }
@@ -1345,7 +1345,7 @@ TEST_F(CowTest, ResumeSeqOp) {
        ASSERT_FALSE(iter->AtEnd());
        const auto& op = iter->Get();

        ASSERT_EQ(op.new_block, expected_block);
        ASSERT_EQ(op->new_block, expected_block);

        iter->Next();
        expected_block--;
@@ -1395,7 +1395,7 @@ TEST_F(CowTest, RevMergeOpItrTest) {
    while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) {
        const auto& op = iter->Get();

        ASSERT_EQ(op.new_block, *expected_new_block);
        ASSERT_EQ(op->new_block, *expected_new_block);

        iter->Next();
        expected_new_block++;
@@ -1444,7 +1444,7 @@ TEST_F(CowTest, LegacyRevMergeOpItrTest) {
    while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) {
        const auto& op = iter->Get();

        ASSERT_EQ(op.new_block, *expected_new_block);
        ASSERT_EQ(op->new_block, *expected_new_block);

        iter->Next();
        expected_new_block++;
+0 −2
Original line number Diff line number Diff line
@@ -57,8 +57,6 @@ std::ostream& operator<<(std::ostream& os, CowOperation const& op) {
    os << "data_length:" << op.data_length << ",\t";
    os << "new_block:" << op.new_block << ",\t";
    os << "source:" << op.source;
    if (op.type == kCowXorOp)
        os << " (block:" << op.source / BLOCK_SZ << " offset:" << op.source % BLOCK_SZ << ")";
    os << ")";
    return os;
}
+29 −29
Original line number Diff line number Diff line
@@ -508,37 +508,37 @@ bool CowReader::PrepMergeOps() {

bool CowReader::VerifyMergeOps() {
    auto itr = GetMergeOpIter(true);
    std::unordered_map<uint64_t, CowOperation> overwritten_blocks;
    std::unordered_map<uint64_t, const CowOperation*> overwritten_blocks;
    while (!itr->AtEnd()) {
        CowOperation op = itr->Get();
        const auto& op = itr->Get();
        uint64_t block;
        bool offset;
        if (op.type == kCowCopyOp) {
            block = op.source;
        if (op->type == kCowCopyOp) {
            block = op->source;
            offset = false;
        } else if (op.type == kCowXorOp) {
            block = op.source / BLOCK_SZ;
            offset = (op.source % BLOCK_SZ) != 0;
        } else if (op->type == kCowXorOp) {
            block = op->source / header_.block_size;
            offset = (op->source % header_.block_size) != 0;
        } else {
            itr->Next();
            continue;
        }

        CowOperation* overwrite = nullptr;
        const CowOperation* overwrite = nullptr;
        if (overwritten_blocks.count(block)) {
            overwrite = &overwritten_blocks[block];
            overwrite = overwritten_blocks[block];
            LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
                       << op << "\noverwritten by previously merged op:\n"
                       << *overwrite;
        }
        if (offset && overwritten_blocks.count(block + 1)) {
            overwrite = &overwritten_blocks[block + 1];
            overwrite = overwritten_blocks[block + 1];
            LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
                       << op << "\noverwritten by previously merged op:\n"
                       << *overwrite;
        }
        if (overwrite != nullptr) return false;
        overwritten_blocks[op.new_block] = op;
        overwritten_blocks[op->new_block] = op;
        itr->Next();
    }
    return true;
@@ -561,7 +561,7 @@ class CowOpIter final : public ICowOpIter {
    CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops, uint64_t start);

    bool AtEnd() override;
    const CowOperation& Get() override;
    const CowOperation* Get() override;
    void Next() override;

    void Prev() override;
@@ -595,9 +595,9 @@ void CowOpIter::Next() {
    op_iter_++;
}

const CowOperation& CowOpIter::Get() {
const CowOperation* CowOpIter::Get() {
    CHECK(!AtEnd());
    return (*op_iter_);
    return &(*op_iter_);
}

class CowRevMergeOpIter final : public ICowOpIter {
@@ -606,7 +606,7 @@ class CowRevMergeOpIter final : public ICowOpIter {
                               std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);

    bool AtEnd() override;
    const CowOperation& Get() override;
    const CowOperation* Get() override;
    void Next() override;

    void Prev() override;
@@ -625,7 +625,7 @@ class CowMergeOpIter final : public ICowOpIter {
                            std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);

    bool AtEnd() override;
    const CowOperation& Get() override;
    const CowOperation* Get() override;
    void Next() override;

    void Prev() override;
@@ -664,9 +664,9 @@ void CowMergeOpIter::Next() {
    block_iter_++;
}

const CowOperation& CowMergeOpIter::Get() {
const CowOperation* CowMergeOpIter::Get() {
    CHECK(!AtEnd());
    return ops_->data()[*block_iter_];
    return &ops_->data()[*block_iter_];
}

CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
@@ -696,9 +696,9 @@ void CowRevMergeOpIter::Next() {
    block_riter_++;
}

const CowOperation& CowRevMergeOpIter::Get() {
const CowOperation* CowRevMergeOpIter::Get() {
    CHECK(!AtEnd());
    return ops_->data()[*block_riter_];
    return &ops_->data()[*block_riter_];
}

std::unique_ptr<ICowOpIter> CowReader::GetOpIter(bool merge_progress) {
@@ -765,10 +765,10 @@ class CowDataStream final : public IByteStream {
    size_t remaining_;
};

ssize_t CowReader::ReadData(const CowOperation& op, void* buffer, size_t buffer_size,
ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
                            size_t ignore_bytes) {
    std::unique_ptr<IDecompressor> decompressor;
    switch (op.compression) {
    switch (op->compression) {
        case kCowCompressNone:
            break;
        case kCowCompressGz:
@@ -778,28 +778,28 @@ ssize_t CowReader::ReadData(const CowOperation& op, void* buffer, size_t buffer_
            decompressor = IDecompressor::Brotli();
            break;
        case kCowCompressLz4:
            if (header_.block_size != op.data_length) {
            if (header_.block_size != op->data_length) {
                decompressor = IDecompressor::Lz4();
            }
            break;
        default:
            LOG(ERROR) << "Unknown compression type: " << op.compression;
            LOG(ERROR) << "Unknown compression type: " << op->compression;
            return -1;
    }

    uint64_t offset;
    if (op.type == kCowXorOp) {
        offset = data_loc_->at(op.new_block);
    if (op->type == kCowXorOp) {
        offset = data_loc_->at(op->new_block);
    } else {
        offset = op.source;
        offset = op->source;
    }

    if (!decompressor) {
        CowDataStream stream(this, offset + ignore_bytes, op.data_length - ignore_bytes);
        CowDataStream stream(this, offset + ignore_bytes, op->data_length - ignore_bytes);
        return stream.ReadFully(buffer, buffer_size);
    }

    CowDataStream stream(this, offset, op.data_length);
    CowDataStream stream(this, offset, op->data_length);
    decompressor->set_stream(&stream);
    return decompressor->Decompress(buffer, buffer_size, header_.block_size, ignore_bytes);
}
Loading