Merge changes Ie8ac02ad,I876f858a,Iccfd6e72 am: f9bdc146ff am: f2e17bf783

Original change: https://android-review.googlesource.com/c/platform/system/core/+/2566920

Change-Id: I3d2af2a2042fdef6eaa8760213e024d929046818
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
David Anderson 2023-05-03 18:24:42 +00:00 committed by Automerger Merge Worker
commit ba0e557238
10 changed files with 184 additions and 203 deletions

View file

@ -35,7 +35,6 @@ class ICowReader {
virtual ~ICowReader() {} virtual ~ICowReader() {}
// Return the file header. // Return the file header.
virtual bool GetHeader(CowHeader* header) = 0;
virtual CowHeader& GetHeader() = 0; virtual CowHeader& GetHeader() = 0;
// Return the file footer. // Return the file footer.
@ -68,13 +67,14 @@ class ICowReader {
size_t ignore_bytes = 0) = 0; size_t ignore_bytes = 0) = 0;
}; };
// Iterate over a sequence of COW operations. // Iterate over a sequence of COW operations. The iterator is bidirectional.
class ICowOpIter { class ICowOpIter {
public: public:
virtual ~ICowOpIter() {} virtual ~ICowOpIter() {}
// True if there are no more items to read forward, false otherwise. // Returns true if the iterator is at the end of the operation list.
virtual bool Done() = 0; // If true, Get() and Next() must not be called.
virtual bool AtEnd() = 0;
// Read the current operation. // Read the current operation.
virtual const CowOperation& Get() = 0; virtual const CowOperation& Get() = 0;
@ -82,11 +82,13 @@ class ICowOpIter {
// Advance to the next item. // Advance to the next item.
virtual void Next() = 0; virtual void Next() = 0;
// Returns true if the iterator is at the beginning of the operation list.
// If true, Prev() must not be called; Get() however will be valid if
// AtEnd() is not true.
virtual bool AtBegin() = 0;
// Advance to the previous item. // Advance to the previous item.
virtual void Prev() = 0; virtual void Prev() = 0;
// True if there are no more items to read backwards, false otherwise
virtual bool RDone() = 0;
}; };
class CowReader final : public ICowReader { class CowReader final : public ICowReader {
@ -107,7 +109,6 @@ class CowReader final : public ICowReader {
bool InitForMerge(android::base::unique_fd&& fd); bool InitForMerge(android::base::unique_fd&& fd);
bool VerifyMergeOps() override; bool VerifyMergeOps() override;
bool GetHeader(CowHeader* header) override;
bool GetFooter(CowFooter* footer) override; bool GetFooter(CowFooter* footer) override;
bool GetLastLabel(uint64_t* label) override; bool GetLastLabel(uint64_t* label) override;

View file

@ -62,23 +62,24 @@ TEST_F(CowTest, CopyContiguous) {
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader; CowReader reader;
CowHeader header;
CowFooter footer;
ASSERT_TRUE(reader.Parse(cow_->fd)); ASSERT_TRUE(reader.Parse(cow_->fd));
ASSERT_TRUE(reader.GetHeader(&header));
ASSERT_TRUE(reader.GetFooter(&footer)); const auto& header = reader.GetHeader();
ASSERT_EQ(header.magic, kCowMagicNumber); ASSERT_EQ(header.magic, kCowMagicNumber);
ASSERT_EQ(header.major_version, kCowVersionMajor); ASSERT_EQ(header.major_version, kCowVersionMajor);
ASSERT_EQ(header.minor_version, kCowVersionMinor); ASSERT_EQ(header.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size); ASSERT_EQ(header.block_size, options.block_size);
CowFooter footer;
ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 100); ASSERT_EQ(footer.op.num_ops, 100);
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
size_t i = 0; size_t i = 0;
while (!iter->Done()) { while (!iter->AtEnd()) {
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->type, kCowCopyOp);
ASSERT_EQ(op->compression, kCowCompressNone); ASSERT_EQ(op->compression, kCowCompressNone);
@ -110,20 +111,21 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader; CowReader reader;
CowHeader header;
CowFooter footer;
ASSERT_TRUE(reader.Parse(cow_->fd)); ASSERT_TRUE(reader.Parse(cow_->fd));
ASSERT_TRUE(reader.GetHeader(&header));
ASSERT_TRUE(reader.GetFooter(&footer)); const auto& header = reader.GetHeader();
ASSERT_EQ(header.magic, kCowMagicNumber); ASSERT_EQ(header.magic, kCowMagicNumber);
ASSERT_EQ(header.major_version, kCowVersionMajor); ASSERT_EQ(header.major_version, kCowVersionMajor);
ASSERT_EQ(header.minor_version, kCowVersionMinor); ASSERT_EQ(header.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size); ASSERT_EQ(header.block_size, options.block_size);
CowFooter footer;
ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 4); ASSERT_EQ(footer.op.num_ops, 4);
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->type, kCowCopyOp);
@ -135,7 +137,7 @@ TEST_F(CowTest, ReadWrite) {
std::string sink(data.size(), '\0'); std::string sink(data.size(), '\0');
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->type, kCowReplaceOp);
@ -146,7 +148,7 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(sink, data); ASSERT_EQ(sink, data);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
// Note: the zero operation gets split into two blocks. // Note: the zero operation gets split into two blocks.
@ -157,7 +159,7 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(op->source, 0); ASSERT_EQ(op->source, 0);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->type, kCowZeroOp);
@ -167,7 +169,7 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(op->source, 0); ASSERT_EQ(op->source, 0);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, ReadWriteXor) { TEST_F(CowTest, ReadWriteXor) {
@ -188,20 +190,21 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0); ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader; CowReader reader;
CowHeader header;
CowFooter footer;
ASSERT_TRUE(reader.Parse(cow_->fd)); ASSERT_TRUE(reader.Parse(cow_->fd));
ASSERT_TRUE(reader.GetHeader(&header));
ASSERT_TRUE(reader.GetFooter(&footer)); const auto& header = reader.GetHeader();
ASSERT_EQ(header.magic, kCowMagicNumber); ASSERT_EQ(header.magic, kCowMagicNumber);
ASSERT_EQ(header.major_version, kCowVersionMajor); ASSERT_EQ(header.major_version, kCowVersionMajor);
ASSERT_EQ(header.minor_version, kCowVersionMinor); ASSERT_EQ(header.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size); ASSERT_EQ(header.block_size, options.block_size);
CowFooter footer;
ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 4); ASSERT_EQ(footer.op.num_ops, 4);
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->type, kCowCopyOp);
@ -213,7 +216,7 @@ TEST_F(CowTest, ReadWriteXor) {
std::string sink(data.size(), '\0'); std::string sink(data.size(), '\0');
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowXorOp); ASSERT_EQ(op->type, kCowXorOp);
@ -225,7 +228,7 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(sink, data); ASSERT_EQ(sink, data);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
// Note: the zero operation gets split into two blocks. // Note: the zero operation gets split into two blocks.
@ -236,7 +239,7 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(op->source, 0); ASSERT_EQ(op->source, 0);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->type, kCowZeroOp);
@ -246,7 +249,7 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(op->source, 0); ASSERT_EQ(op->source, 0);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, CompressGz) { TEST_F(CowTest, CompressGz) {
@ -270,7 +273,7 @@ TEST_F(CowTest, CompressGz) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
std::string sink(data.size(), '\0'); std::string sink(data.size(), '\0');
@ -283,7 +286,7 @@ TEST_F(CowTest, CompressGz) {
ASSERT_EQ(sink, data); ASSERT_EQ(sink, data);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
class CompressionTest : public CowTest, public testing::WithParamInterface<const char*> {}; class CompressionTest : public CowTest, public testing::WithParamInterface<const char*> {};
@ -325,7 +328,7 @@ TEST_P(CompressionTest, ThreadedBatchWrites) {
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
int total_blocks = 0; int total_blocks = 0;
while (!iter->Done()) { while (!iter->AtEnd()) {
auto op = &iter->Get(); auto op = &iter->Get();
if (op->type == kCowXorOp) { if (op->type == kCowXorOp) {
@ -399,7 +402,7 @@ TEST_P(CompressionTest, NoBatchWrites) {
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
int total_blocks = 0; int total_blocks = 0;
while (!iter->Done()) { while (!iter->AtEnd()) {
auto op = &iter->Get(); auto op = &iter->Get();
if (op->type == kCowReplaceOp) { if (op->type == kCowReplaceOp) {
@ -515,7 +518,7 @@ TEST_F(CowTest, ClusterCompressGz) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
std::string sink(data.size(), '\0'); std::string sink(data.size(), '\0');
@ -528,13 +531,13 @@ TEST_F(CowTest, ClusterCompressGz) {
ASSERT_EQ(sink, data); ASSERT_EQ(sink, data);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp); ASSERT_EQ(op->type, kCowClusterOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
sink = {}; sink = {};
@ -546,13 +549,13 @@ TEST_F(CowTest, ClusterCompressGz) {
ASSERT_EQ(sink, data2); ASSERT_EQ(sink, data2);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp); ASSERT_EQ(op->type, kCowClusterOp);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, CompressTwoBlocks) { TEST_F(CowTest, CompressTwoBlocks) {
@ -576,9 +579,9 @@ TEST_F(CowTest, CompressTwoBlocks) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
std::string sink(options.block_size, '\0'); std::string sink(options.block_size, '\0');
@ -655,7 +658,7 @@ TEST_F(CowTest, AppendLabelSmall) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -665,21 +668,21 @@ TEST_F(CowTest, AppendLabelSmall) {
sink = {}; sink = {};
sink.resize(data2.size(), '\0'); sink.resize(data2.size(), '\0');
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 3); ASSERT_EQ(op->source, 3);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp); 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); ASSERT_EQ(sink, data2);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, AppendLabelMissing) { TEST_F(CowTest, AppendLabelMissing) {
@ -718,20 +721,20 @@ TEST_F(CowTest, AppendLabelMissing) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 0); ASSERT_EQ(op->source, 0);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->type, kCowZeroOp);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, AppendExtendedCorrupted) { TEST_F(CowTest, AppendExtendedCorrupted) {
@ -776,13 +779,13 @@ TEST_F(CowTest, AppendExtendedCorrupted) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5); ASSERT_EQ(op->source, 5);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, AppendbyLabel) { TEST_F(CowTest, AppendbyLabel) {
@ -827,7 +830,7 @@ TEST_F(CowTest, AppendbyLabel) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -837,7 +840,7 @@ TEST_F(CowTest, AppendbyLabel) {
sink = {}; sink = {};
sink.resize(options.block_size, '\0'); sink.resize(options.block_size, '\0');
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -845,32 +848,32 @@ TEST_F(CowTest, AppendbyLabel) {
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 4); ASSERT_EQ(op->source, 4);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->type, kCowZeroOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->type, kCowZeroOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5); ASSERT_EQ(op->source, 5);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, ClusterTest) { TEST_F(CowTest, ClusterTest) {
@ -908,7 +911,7 @@ TEST_F(CowTest, ClusterTest) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -916,58 +919,58 @@ TEST_F(CowTest, ClusterTest) {
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 4); ASSERT_EQ(op->source, 4);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->type, kCowZeroOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp); ASSERT_EQ(op->type, kCowClusterOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp); ASSERT_EQ(op->type, kCowZeroOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5); ASSERT_EQ(op->source, 5);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp); ASSERT_EQ(op->type, kCowCopyOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp); ASSERT_EQ(op->type, kCowClusterOp);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 6); ASSERT_EQ(op->source, 6);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, ClusterAppendTest) { TEST_F(CowTest, ClusterAppendTest) {
@ -1007,14 +1010,14 @@ TEST_F(CowTest, ClusterAppendTest) {
auto iter = reader.GetOpIter(); auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr); ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get(); auto op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp); ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 50); ASSERT_EQ(op->source, 50);
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp); ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size())); ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -1022,13 +1025,13 @@ TEST_F(CowTest, ClusterAppendTest) {
iter->Next(); iter->Next();
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
op = &iter->Get(); op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp); ASSERT_EQ(op->type, kCowClusterOp);
iter->Next(); iter->Next();
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, AppendAfterFinalize) { TEST_F(CowTest, AppendAfterFinalize) {
@ -1065,8 +1068,7 @@ AssertionResult WriteDataBlock(CowWriter* writer, uint64_t new_block, std::strin
AssertionResult CompareDataBlock(CowReader* reader, const CowOperation& op, AssertionResult CompareDataBlock(CowReader* reader, const CowOperation& op,
const std::string& data) { const std::string& data) {
CowHeader header; const auto& header = reader->GetHeader();
reader->GetHeader(&header);
std::string cmp = data; std::string cmp = data;
cmp.resize(header.block_size, '\0'); cmp.resize(header.block_size, '\0');
@ -1116,7 +1118,7 @@ TEST_F(CowTest, ResumeMidCluster) {
size_t max_in_cluster = 0; size_t max_in_cluster = 0;
size_t num_in_cluster = 0; size_t num_in_cluster = 0;
size_t num_clusters = 0; size_t num_clusters = 0;
while (!iter->Done()) { while (!iter->AtEnd()) {
const auto& op = iter->Get(); const auto& op = iter->Get();
num_in_cluster++; num_in_cluster++;
@ -1177,7 +1179,7 @@ TEST_F(CowTest, ResumeEndCluster) {
size_t max_in_cluster = 0; size_t max_in_cluster = 0;
size_t num_in_cluster = 0; size_t num_in_cluster = 0;
size_t num_clusters = 0; size_t num_clusters = 0;
while (!iter->Done()) { while (!iter->AtEnd()) {
const auto& op = iter->Get(); const auto& op = iter->Get();
num_in_cluster++; num_in_cluster++;
@ -1229,7 +1231,7 @@ TEST_F(CowTest, DeleteMidCluster) {
size_t max_in_cluster = 0; size_t max_in_cluster = 0;
size_t num_in_cluster = 0; size_t num_in_cluster = 0;
size_t num_clusters = 0; size_t num_clusters = 0;
while (!iter->Done()) { while (!iter->AtEnd()) {
const auto& op = iter->Get(); const auto& op = iter->Get();
num_in_cluster++; num_in_cluster++;
@ -1273,14 +1275,14 @@ TEST_F(CowTest, BigSeqOp) {
auto iter = reader.GetRevMergeOpIter(); auto iter = reader.GetRevMergeOpIter();
for (int i = 0; i < seq_len; i++) { for (int i = 0; i < seq_len; i++) {
ASSERT_TRUE(!iter->Done()); ASSERT_TRUE(!iter->AtEnd());
const auto& op = iter->Get(); const auto& op = iter->Get();
ASSERT_EQ(op.new_block, seq_len - i); ASSERT_EQ(op.new_block, seq_len - i);
iter->Next(); iter->Next();
} }
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, MissingSeqOp) { TEST_F(CowTest, MissingSeqOp) {
@ -1324,7 +1326,7 @@ TEST_F(CowTest, ResumeSeqOp) {
auto reader = std::make_unique<CowReader>(); auto reader = std::make_unique<CowReader>();
ASSERT_TRUE(reader->Parse(cow_->fd, 1)); ASSERT_TRUE(reader->Parse(cow_->fd, 1));
auto itr = reader->GetRevMergeOpIter(); auto itr = reader->GetRevMergeOpIter();
ASSERT_TRUE(itr->Done()); ASSERT_TRUE(itr->AtEnd());
writer = std::make_unique<CowWriter>(options); writer = std::make_unique<CowWriter>(options);
ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1)); ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
@ -1339,8 +1341,8 @@ TEST_F(CowTest, ResumeSeqOp) {
auto iter = reader->GetRevMergeOpIter(); auto iter = reader->GetRevMergeOpIter();
uint64_t expected_block = 10; uint64_t expected_block = 10;
while (!iter->Done() && expected_block > 0) { while (!iter->AtEnd() && expected_block > 0) {
ASSERT_FALSE(iter->Done()); ASSERT_FALSE(iter->AtEnd());
const auto& op = iter->Get(); const auto& op = iter->Get();
ASSERT_EQ(op.new_block, expected_block); ASSERT_EQ(op.new_block, expected_block);
@ -1349,7 +1351,7 @@ TEST_F(CowTest, ResumeSeqOp) {
expected_block--; expected_block--;
} }
ASSERT_EQ(expected_block, 0); ASSERT_EQ(expected_block, 0);
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, RevMergeOpItrTest) { TEST_F(CowTest, RevMergeOpItrTest) {
@ -1390,7 +1392,7 @@ TEST_F(CowTest, RevMergeOpItrTest) {
auto iter = reader.GetRevMergeOpIter(); auto iter = reader.GetRevMergeOpIter();
auto expected_new_block = revMergeOpSequence.begin(); auto expected_new_block = revMergeOpSequence.begin();
while (!iter->Done() && expected_new_block != revMergeOpSequence.end()) { while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) {
const auto& op = iter->Get(); const auto& op = iter->Get();
ASSERT_EQ(op.new_block, *expected_new_block); ASSERT_EQ(op.new_block, *expected_new_block);
@ -1399,7 +1401,7 @@ TEST_F(CowTest, RevMergeOpItrTest) {
expected_new_block++; expected_new_block++;
} }
ASSERT_EQ(expected_new_block, revMergeOpSequence.end()); ASSERT_EQ(expected_new_block, revMergeOpSequence.end());
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, LegacyRevMergeOpItrTest) { TEST_F(CowTest, LegacyRevMergeOpItrTest) {
@ -1439,7 +1441,7 @@ TEST_F(CowTest, LegacyRevMergeOpItrTest) {
auto iter = reader.GetRevMergeOpIter(); auto iter = reader.GetRevMergeOpIter();
auto expected_new_block = revMergeOpSequence.begin(); auto expected_new_block = revMergeOpSequence.begin();
while (!iter->Done() && expected_new_block != revMergeOpSequence.end()) { while (!iter->AtEnd() && expected_new_block != revMergeOpSequence.end()) {
const auto& op = iter->Get(); const auto& op = iter->Get();
ASSERT_EQ(op.new_block, *expected_new_block); ASSERT_EQ(op.new_block, *expected_new_block);
@ -1448,7 +1450,7 @@ TEST_F(CowTest, LegacyRevMergeOpItrTest) {
expected_new_block++; expected_new_block++;
} }
ASSERT_EQ(expected_new_block, revMergeOpSequence.end()); ASSERT_EQ(expected_new_block, revMergeOpSequence.end());
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->AtEnd());
} }
TEST_F(CowTest, InvalidMergeOrderTest) { TEST_F(CowTest, InvalidMergeOrderTest) {

View file

@ -509,7 +509,7 @@ bool CowReader::PrepMergeOps() {
bool CowReader::VerifyMergeOps() { bool CowReader::VerifyMergeOps() {
auto itr = GetMergeOpIter(true); auto itr = GetMergeOpIter(true);
std::unordered_map<uint64_t, CowOperation> overwritten_blocks; std::unordered_map<uint64_t, CowOperation> overwritten_blocks;
while (!itr->Done()) { while (!itr->AtEnd()) {
CowOperation op = itr->Get(); CowOperation op = itr->Get();
uint64_t block; uint64_t block;
bool offset; bool offset;
@ -544,11 +544,6 @@ bool CowReader::VerifyMergeOps() {
return true; return true;
} }
bool CowReader::GetHeader(CowHeader* header) {
*header = header_;
return true;
}
bool CowReader::GetFooter(CowFooter* footer) { bool CowReader::GetFooter(CowFooter* footer) {
if (!footer_) return false; if (!footer_) return false;
*footer = footer_.value(); *footer = footer_.value();
@ -565,12 +560,12 @@ class CowOpIter final : public ICowOpIter {
public: public:
CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops, uint64_t start); CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops, uint64_t start);
bool Done() override; bool AtEnd() override;
const CowOperation& Get() override; const CowOperation& Get() override;
void Next() override; void Next() override;
void Prev() override; void Prev() override;
bool RDone() override; bool AtBegin() override;
private: private:
std::shared_ptr<std::vector<CowOperation>> ops_; std::shared_ptr<std::vector<CowOperation>> ops_;
@ -582,26 +577,26 @@ CowOpIter::CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops, uint64_t s
op_iter_ = ops_->begin() + start; op_iter_ = ops_->begin() + start;
} }
bool CowOpIter::RDone() { bool CowOpIter::AtBegin() {
return op_iter_ == ops_->begin(); return op_iter_ == ops_->begin();
} }
void CowOpIter::Prev() { void CowOpIter::Prev() {
CHECK(!RDone()); CHECK(!AtBegin());
op_iter_--; op_iter_--;
} }
bool CowOpIter::Done() { bool CowOpIter::AtEnd() {
return op_iter_ == ops_->end(); return op_iter_ == ops_->end();
} }
void CowOpIter::Next() { void CowOpIter::Next() {
CHECK(!Done()); CHECK(!AtEnd());
op_iter_++; op_iter_++;
} }
const CowOperation& CowOpIter::Get() { const CowOperation& CowOpIter::Get() {
CHECK(!Done()); CHECK(!AtEnd());
return (*op_iter_); return (*op_iter_);
} }
@ -610,12 +605,12 @@ class CowRevMergeOpIter final : public ICowOpIter {
explicit CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops, explicit CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start); std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
bool Done() override; bool AtEnd() override;
const CowOperation& Get() override; const CowOperation& Get() override;
void Next() override; void Next() override;
void Prev() override; void Prev() override;
bool RDone() override; bool AtBegin() override;
private: private:
std::shared_ptr<std::vector<CowOperation>> ops_; std::shared_ptr<std::vector<CowOperation>> ops_;
@ -629,12 +624,12 @@ class CowMergeOpIter final : public ICowOpIter {
explicit CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops, explicit CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start); std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
bool Done() override; bool AtEnd() override;
const CowOperation& Get() override; const CowOperation& Get() override;
void Next() override; void Next() override;
void Prev() override; void Prev() override;
bool RDone() override; bool AtBegin() override;
private: private:
std::shared_ptr<std::vector<CowOperation>> ops_; std::shared_ptr<std::vector<CowOperation>> ops_;
@ -651,26 +646,26 @@ CowMergeOpIter::CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
block_iter_ = cow_op_index_vec_->begin() + start; block_iter_ = cow_op_index_vec_->begin() + start;
} }
bool CowMergeOpIter::RDone() { bool CowMergeOpIter::AtBegin() {
return block_iter_ == cow_op_index_vec_->begin(); return block_iter_ == cow_op_index_vec_->begin();
} }
void CowMergeOpIter::Prev() { void CowMergeOpIter::Prev() {
CHECK(!RDone()); CHECK(!AtBegin());
block_iter_--; block_iter_--;
} }
bool CowMergeOpIter::Done() { bool CowMergeOpIter::AtEnd() {
return block_iter_ == cow_op_index_vec_->end(); return block_iter_ == cow_op_index_vec_->end();
} }
void CowMergeOpIter::Next() { void CowMergeOpIter::Next() {
CHECK(!Done()); CHECK(!AtEnd());
block_iter_++; block_iter_++;
} }
const CowOperation& CowMergeOpIter::Get() { const CowOperation& CowMergeOpIter::Get() {
CHECK(!Done()); CHECK(!AtEnd());
return ops_->data()[*block_iter_]; return ops_->data()[*block_iter_];
} }
@ -683,26 +678,26 @@ CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>>
block_riter_ = cow_op_index_vec_->rbegin(); block_riter_ = cow_op_index_vec_->rbegin();
} }
bool CowRevMergeOpIter::RDone() { bool CowRevMergeOpIter::AtBegin() {
return block_riter_ == cow_op_index_vec_->rbegin(); return block_riter_ == cow_op_index_vec_->rbegin();
} }
void CowRevMergeOpIter::Prev() { void CowRevMergeOpIter::Prev() {
CHECK(!RDone()); CHECK(!AtBegin());
block_riter_--; block_riter_--;
} }
bool CowRevMergeOpIter::Done() { bool CowRevMergeOpIter::AtEnd() {
return block_riter_ == cow_op_index_vec_->rend() - start_; return block_riter_ == cow_op_index_vec_->rend() - start_;
} }
void CowRevMergeOpIter::Next() { void CowRevMergeOpIter::Next() {
CHECK(!Done()); CHECK(!AtEnd());
block_riter_++; block_riter_++;
} }
const CowOperation& CowRevMergeOpIter::Get() { const CowOperation& CowRevMergeOpIter::Get() {
CHECK(!Done()); CHECK(!AtEnd());
return ops_->data()[*block_riter_]; return ops_->data()[*block_riter_];
} }

View file

@ -392,10 +392,11 @@ bool CowWriter::OpenForAppend(uint64_t label) {
auto reader = std::make_unique<CowReader>(); auto reader = std::make_unique<CowReader>();
std::queue<CowOperation> toAdd; std::queue<CowOperation> toAdd;
if (!reader->Parse(fd_, {label}) || !reader->GetHeader(&header_)) { if (!reader->Parse(fd_, {label})) {
return false; return false;
} }
header_ = reader->GetHeader();
options_.block_size = header_.block_size; options_.block_size = header_.block_size;
options_.cluster_ops = header_.cluster_ops; options_.cluster_ops = header_.cluster_ops;
@ -405,7 +406,7 @@ bool CowWriter::OpenForAppend(uint64_t label) {
auto iter = reader->GetOpIter(); auto iter = reader->GetOpIter();
while (!iter->Done()) { while (!iter->AtEnd()) {
AddOperation(iter->Get()); AddOperation(iter->Get());
iter->Next(); iter->Next();
} }

View file

@ -16,6 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <chrono>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -38,16 +39,16 @@ void MyLogger(android::base::LogId, android::base::LogSeverity severity, const c
} }
static void usage(void) { static void usage(void) {
LOG(ERROR) << "Usage: inspect_cow [-sd] <COW_FILE>"; std::cerr << "Usage: inspect_cow [-sd] <COW_FILE>\n";
LOG(ERROR) << "\t -s Run Silent"; std::cerr << "\t -s Run Silent\n";
LOG(ERROR) << "\t -d Attempt to decompress"; std::cerr << "\t -d Attempt to decompress\n";
LOG(ERROR) << "\t -b Show data for failed decompress"; std::cerr << "\t -b Show data for failed decompress\n";
LOG(ERROR) << "\t -l Show ops"; std::cerr << "\t -l Show ops\n";
LOG(ERROR) << "\t -m Show ops in reverse merge order"; std::cerr << "\t -m Show ops in reverse merge order\n";
LOG(ERROR) << "\t -n Show ops in merge order"; std::cerr << "\t -n Show ops in merge order\n";
LOG(ERROR) << "\t -a Include merged ops in any merge order listing"; std::cerr << "\t -a Include merged ops in any merge order listing\n";
LOG(ERROR) << "\t -o Shows sequence op block order"; std::cerr << "\t -o Shows sequence op block order\n";
LOG(ERROR) << "\t -v Verifies merge order has no conflicts\n"; std::cerr << "\t -v Verifies merge order has no conflicts\n";
} }
enum OpIter { Normal, RevMerge, Merge }; enum OpIter { Normal, RevMerge, Merge };
@ -89,37 +90,40 @@ static bool Inspect(const std::string& path, Options opt) {
} }
CowReader reader; CowReader reader;
auto start_time = std::chrono::steady_clock::now();
if (!reader.Parse(fd)) { if (!reader.Parse(fd)) {
LOG(ERROR) << "parse failed: " << path; LOG(ERROR) << "parse failed: " << path;
return false; return false;
} }
std::chrono::duration<double> parse_time = std::chrono::steady_clock::now() - start_time;
CowHeader header; const CowHeader& header = reader.GetHeader();
if (!reader.GetHeader(&header)) {
LOG(ERROR) << "could not get header: " << path;
return false;
}
CowFooter footer; CowFooter footer;
bool has_footer = false; bool has_footer = false;
if (reader.GetFooter(&footer)) has_footer = true; if (reader.GetFooter(&footer)) has_footer = true;
if (!opt.silent) { if (!opt.silent) {
std::cout << "Major version: " << header.major_version << "\n"; std::cout << "Version: " << header.major_version << "." << header.minor_version << "\n";
std::cout << "Minor version: " << header.minor_version << "\n";
std::cout << "Header size: " << header.header_size << "\n"; std::cout << "Header size: " << header.header_size << "\n";
std::cout << "Footer size: " << header.footer_size << "\n"; std::cout << "Footer size: " << header.footer_size << "\n";
std::cout << "Block size: " << header.block_size << "\n"; std::cout << "Block size: " << header.block_size << "\n";
std::cout << "Num merge ops: " << header.num_merge_ops << "\n"; std::cout << "Merge ops: " << header.num_merge_ops << "\n";
std::cout << "RA buffer size: " << header.buffer_size << "\n"; std::cout << "Readahead buffer: " << header.buffer_size << " bytes\n";
std::cout << "\n";
if (has_footer) { if (has_footer) {
std::cout << "Total Ops size: " << footer.op.ops_size << "\n"; std::cout << "Footer: ops usage: " << footer.op.ops_size << " bytes\n";
std::cout << "Number of Ops: " << footer.op.num_ops << "\n"; std::cout << "Footer: op count: " << footer.op.num_ops << "\n";
std::cout << "\n"; } else {
std::cout << "Footer: none\n";
} }
} }
if (!opt.silent) {
std::cout << "Parse time: " << (parse_time.count() * 1000) << "ms\n";
}
if (opt.verify_sequence) { if (opt.verify_sequence) {
std::cout << "\n";
if (reader.VerifyMergeOps()) { if (reader.VerifyMergeOps()) {
std::cout << "\nMerge sequence is consistent.\n"; std::cout << "\nMerge sequence is consistent.\n";
} else { } else {
@ -140,7 +144,7 @@ static bool Inspect(const std::string& path, Options opt) {
bool success = true; bool success = true;
uint64_t xor_ops = 0, copy_ops = 0, replace_ops = 0, zero_ops = 0; uint64_t xor_ops = 0, copy_ops = 0, replace_ops = 0, zero_ops = 0;
while (!iter->Done()) { while (!iter->AtEnd()) {
const CowOperation& op = iter->Get(); const CowOperation& op = iter->Get();
if (!opt.silent && opt.show_ops) std::cout << op << "\n"; if (!opt.silent && opt.show_ops) std::cout << op << "\n";
@ -186,9 +190,11 @@ static bool Inspect(const std::string& path, Options opt) {
if (!opt.silent) { if (!opt.silent) {
auto total_ops = replace_ops + zero_ops + copy_ops + xor_ops; auto total_ops = replace_ops + zero_ops + copy_ops + xor_ops;
std::cout << "Total-data-ops: " << total_ops << "Replace-ops: " << replace_ops std::cout << "Data ops: " << total_ops << "\n";
<< " Zero-ops: " << zero_ops << " Copy-ops: " << copy_ops std::cout << "Replace ops: " << replace_ops << "\n";
<< " Xor_ops: " << xor_ops << std::endl; std::cout << "Zero ops: " << zero_ops << "\n";
std::cout << "Copy ops: " << copy_ops << "\n";
std::cout << "Xor ops: " << xor_ops << "\n";
} }
return success; return success;
@ -237,15 +243,17 @@ int main(int argc, char** argv) {
break; break;
default: default:
android::snapshot::usage(); android::snapshot::usage();
return 1;
} }
} }
android::base::InitLogging(argv, android::snapshot::MyLogger);
if (argc < optind + 1) { if (argc < optind + 1) {
android::snapshot::usage(); android::snapshot::usage();
return 1; return 1;
} }
android::base::InitLogging(argv, android::snapshot::MyLogger);
if (!android::snapshot::Inspect(argv[optind], opt)) { if (!android::snapshot::Inspect(argv[optind], opt)) {
return 1; return 1;
} }

View file

@ -80,15 +80,12 @@ bool ReadFdFileDescriptor::Flush() {
bool CompressedSnapshotReader::SetCow(std::unique_ptr<CowReader>&& cow) { bool CompressedSnapshotReader::SetCow(std::unique_ptr<CowReader>&& cow) {
cow_ = std::move(cow); cow_ = std::move(cow);
CowHeader header; const auto& header = cow_->GetHeader();
if (!cow_->GetHeader(&header)) {
return false;
}
block_size_ = header.block_size; block_size_ = header.block_size;
// Populate the operation map. // Populate the operation map.
op_iter_ = cow_->GetOpIter(); op_iter_ = cow_->GetOpIter();
while (!op_iter_->Done()) { while (!op_iter_->AtEnd()) {
const CowOperation* op = &op_iter_->Get(); const CowOperation* op = &op_iter_->Get();
if (IsMetadataOp(*op)) { if (IsMetadataOp(*op)) {
op_iter_->Next(); op_iter_->Next();

View file

@ -347,7 +347,6 @@ void Snapuserd::CheckMergeCompletionStatus() {
*/ */
bool Snapuserd::ReadMetadata() { bool Snapuserd::ReadMetadata() {
reader_ = std::make_unique<CowReader>(); reader_ = std::make_unique<CowReader>();
CowHeader header;
CowOptions options; CowOptions options;
bool metadata_found = false; bool metadata_found = false;
int replace_ops = 0, zero_ops = 0, copy_ops = 0; int replace_ops = 0, zero_ops = 0, copy_ops = 0;
@ -359,11 +358,7 @@ bool Snapuserd::ReadMetadata() {
return false; return false;
} }
if (!reader_->GetHeader(&header)) { const auto& header = reader_->GetHeader();
SNAP_LOG(ERROR) << "Failed to get header";
return false;
}
if (!(header.block_size == BLOCK_SZ)) { if (!(header.block_size == BLOCK_SZ)) {
SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size; SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size;
return false; return false;
@ -395,7 +390,7 @@ bool Snapuserd::ReadMetadata() {
// this memset will ensure that metadata read is completed. // this memset will ensure that metadata read is completed.
memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception))); memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception)));
while (!cowop_rm_iter->Done()) { while (!cowop_rm_iter->AtEnd()) {
const CowOperation* cow_op = &cowop_rm_iter->Get(); const CowOperation* cow_op = &cowop_rm_iter->Get();
struct disk_exception* de = struct disk_exception* de =
reinterpret_cast<struct disk_exception*>((char*)de_ptr.get() + offset); reinterpret_cast<struct disk_exception*>((char*)de_ptr.get() + offset);
@ -442,7 +437,7 @@ bool Snapuserd::ReadMetadata() {
sizeof(struct disk_exception)); sizeof(struct disk_exception));
memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception))); memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception)));
if (cowop_rm_iter->Done()) { if (cowop_rm_iter->AtEnd()) {
vec_.push_back(std::move(de_ptr)); vec_.push_back(std::move(de_ptr));
} }
} }
@ -462,7 +457,7 @@ bool Snapuserd::ReadMetadata() {
<< " Number of replace/zero ops completed in this area: " << num_ops << " Number of replace/zero ops completed in this area: " << num_ops
<< " Pending copy ops for this area: " << pending_ordered_ops; << " Pending copy ops for this area: " << pending_ordered_ops;
while (!cowop_rm_iter->Done()) { while (!cowop_rm_iter->AtEnd()) {
do { do {
const CowOperation* cow_op = &cowop_rm_iter->Get(); const CowOperation* cow_op = &cowop_rm_iter->Get();
@ -531,7 +526,7 @@ bool Snapuserd::ReadMetadata() {
source_blocks.insert(cow_op->new_block); source_blocks.insert(cow_op->new_block);
prev_id = cow_op->new_block; prev_id = cow_op->new_block;
cowop_rm_iter->Next(); cowop_rm_iter->Next();
} while (!cowop_rm_iter->Done() && pending_ordered_ops); } while (!cowop_rm_iter->AtEnd() && pending_ordered_ops);
data_chunk_id = GetNextAllocatableChunkId(data_chunk_id); data_chunk_id = GetNextAllocatableChunkId(data_chunk_id);
SNAP_LOG(DEBUG) << "Batch Merge copy-ops of size: " << vec.size() SNAP_LOG(DEBUG) << "Batch Merge copy-ops of size: " << vec.size()
@ -574,7 +569,7 @@ bool Snapuserd::ReadMetadata() {
sizeof(struct disk_exception)); sizeof(struct disk_exception));
memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception))); memset(de_ptr.get(), 0, (exceptions_per_area_ * sizeof(struct disk_exception)));
if (cowop_rm_iter->Done()) { if (cowop_rm_iter->AtEnd()) {
vec_.push_back(std::move(de_ptr)); vec_.push_back(std::move(de_ptr));
SNAP_LOG(DEBUG) << "ReadMetadata() completed; Number of Areas: " << vec_.size(); SNAP_LOG(DEBUG) << "ReadMetadata() completed; Number of Areas: " << vec_.size();
} }
@ -636,8 +631,7 @@ bool Snapuserd::ReadMetadata() {
} }
bool Snapuserd::MmapMetadata() { bool Snapuserd::MmapMetadata() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
if (header.major_version >= 2 && header.buffer_size > 0) { if (header.major_version >= 2 && header.buffer_size > 0) {
total_mapped_addr_length_ = header.header_size + BUFFER_REGION_DEFAULT_SIZE; total_mapped_addr_length_ = header.header_size + BUFFER_REGION_DEFAULT_SIZE;
@ -832,8 +826,7 @@ bool Snapuserd::Start() {
} }
uint64_t Snapuserd::GetBufferMetadataOffset() { uint64_t Snapuserd::GetBufferMetadataOffset() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
size_t size = header.header_size + sizeof(BufferState); size_t size = header.header_size + sizeof(BufferState);
return size; return size;
@ -848,16 +841,14 @@ uint64_t Snapuserd::GetBufferMetadataOffset() {
* *
*/ */
size_t Snapuserd::GetBufferMetadataSize() { size_t Snapuserd::GetBufferMetadataSize() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
size_t metadata_bytes = (header.buffer_size * sizeof(struct ScratchMetadata)) / BLOCK_SZ; size_t metadata_bytes = (header.buffer_size * sizeof(struct ScratchMetadata)) / BLOCK_SZ;
return metadata_bytes; return metadata_bytes;
} }
size_t Snapuserd::GetBufferDataOffset() { size_t Snapuserd::GetBufferDataOffset() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
return (header.header_size + GetBufferMetadataSize()); return (header.header_size + GetBufferMetadataSize());
} }
@ -866,16 +857,14 @@ size_t Snapuserd::GetBufferDataOffset() {
* (2MB - 8K = 2088960 bytes) will be the buffer region to hold the data. * (2MB - 8K = 2088960 bytes) will be the buffer region to hold the data.
*/ */
size_t Snapuserd::GetBufferDataSize() { size_t Snapuserd::GetBufferDataSize() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
size_t size = header.buffer_size - GetBufferMetadataSize(); size_t size = header.buffer_size - GetBufferMetadataSize();
return size; return size;
} }
struct BufferState* Snapuserd::GetBufferState() { struct BufferState* Snapuserd::GetBufferState() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
struct BufferState* ra_state = struct BufferState* ra_state =
reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.header_size); reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.header_size);

View file

@ -98,8 +98,7 @@ bool SnapshotHandler::CommitMerge(int num_merge_ops) {
} }
} else { } else {
reader_->UpdateMergeOpsCompleted(num_merge_ops); reader_->UpdateMergeOpsCompleted(num_merge_ops);
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
if (lseek(cow_fd_.get(), 0, SEEK_SET) < 0) { if (lseek(cow_fd_.get(), 0, SEEK_SET) < 0) {
SNAP_PLOG(ERROR) << "lseek failed"; SNAP_PLOG(ERROR) << "lseek failed";
@ -154,7 +153,6 @@ bool SnapshotHandler::CheckMergeCompletionStatus() {
bool SnapshotHandler::ReadMetadata() { bool SnapshotHandler::ReadMetadata() {
reader_ = std::make_unique<CowReader>(CowReader::ReaderFlags::USERSPACE_MERGE, true); reader_ = std::make_unique<CowReader>(CowReader::ReaderFlags::USERSPACE_MERGE, true);
CowHeader header;
CowOptions options; CowOptions options;
SNAP_LOG(DEBUG) << "ReadMetadata: Parsing cow file"; SNAP_LOG(DEBUG) << "ReadMetadata: Parsing cow file";
@ -164,11 +162,7 @@ bool SnapshotHandler::ReadMetadata() {
return false; return false;
} }
if (!reader_->GetHeader(&header)) { const auto& header = reader_->GetHeader();
SNAP_LOG(ERROR) << "Failed to get header";
return false;
}
if (!(header.block_size == BLOCK_SZ)) { if (!(header.block_size == BLOCK_SZ)) {
SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size; SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size;
return false; return false;
@ -191,7 +185,7 @@ bool SnapshotHandler::ReadMetadata() {
size_t copy_ops = 0, replace_ops = 0, zero_ops = 0, xor_ops = 0; size_t copy_ops = 0, replace_ops = 0, zero_ops = 0, xor_ops = 0;
while (!cowop_iter->Done()) { while (!cowop_iter->AtEnd()) {
const CowOperation* cow_op = &cowop_iter->Get(); const CowOperation* cow_op = &cowop_iter->Get();
if (cow_op->type == kCowCopyOp) { if (cow_op->type == kCowCopyOp) {
@ -244,8 +238,7 @@ bool SnapshotHandler::ReadMetadata() {
} }
bool SnapshotHandler::MmapMetadata() { bool SnapshotHandler::MmapMetadata() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
total_mapped_addr_length_ = header.header_size + BUFFER_REGION_DEFAULT_SIZE; total_mapped_addr_length_ = header.header_size + BUFFER_REGION_DEFAULT_SIZE;
@ -367,8 +360,7 @@ bool SnapshotHandler::Start() {
} }
uint64_t SnapshotHandler::GetBufferMetadataOffset() { uint64_t SnapshotHandler::GetBufferMetadataOffset() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
return (header.header_size + sizeof(BufferState)); return (header.header_size + sizeof(BufferState));
} }
@ -383,8 +375,7 @@ uint64_t SnapshotHandler::GetBufferMetadataOffset() {
* *
*/ */
size_t SnapshotHandler::GetBufferMetadataSize() { size_t SnapshotHandler::GetBufferMetadataSize() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
size_t buffer_size = header.buffer_size; size_t buffer_size = header.buffer_size;
// If there is no scratch space, then just use the // If there is no scratch space, then just use the
@ -397,8 +388,7 @@ size_t SnapshotHandler::GetBufferMetadataSize() {
} }
size_t SnapshotHandler::GetBufferDataOffset() { size_t SnapshotHandler::GetBufferDataOffset() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
return (header.header_size + GetBufferMetadataSize()); return (header.header_size + GetBufferMetadataSize());
} }
@ -407,8 +397,7 @@ size_t SnapshotHandler::GetBufferDataOffset() {
* (2MB - 8K = 2088960 bytes) will be the buffer region to hold the data. * (2MB - 8K = 2088960 bytes) will be the buffer region to hold the data.
*/ */
size_t SnapshotHandler::GetBufferDataSize() { size_t SnapshotHandler::GetBufferDataSize() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
size_t buffer_size = header.buffer_size; size_t buffer_size = header.buffer_size;
// If there is no scratch space, then just use the // If there is no scratch space, then just use the
@ -421,8 +410,7 @@ size_t SnapshotHandler::GetBufferDataSize() {
} }
struct BufferState* SnapshotHandler::GetBufferState() { struct BufferState* SnapshotHandler::GetBufferState() {
CowHeader header; const auto& header = reader_->GetHeader();
reader_->GetHeader(&header);
struct BufferState* ra_state = struct BufferState* ra_state =
reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.header_size); reinterpret_cast<struct BufferState*>((char*)mapped_addr_ + header.header_size);

View file

@ -30,7 +30,7 @@ int Worker::PrepareMerge(uint64_t* source_offset, int* pending_ops,
bool checkOrderedOp = (replace_zero_vec == nullptr); bool checkOrderedOp = (replace_zero_vec == nullptr);
do { do {
if (!cowop_iter_->Done() && num_ops) { if (!cowop_iter_->AtEnd() && num_ops) {
const CowOperation* cow_op = &cowop_iter_->Get(); const CowOperation* cow_op = &cowop_iter_->Get();
if (checkOrderedOp && !IsOrderedOp(*cow_op)) { if (checkOrderedOp && !IsOrderedOp(*cow_op)) {
break; break;
@ -45,7 +45,7 @@ int Worker::PrepareMerge(uint64_t* source_offset, int* pending_ops,
num_ops -= 1; num_ops -= 1;
nr_consecutive = 1; nr_consecutive = 1;
while (!cowop_iter_->Done() && num_ops) { while (!cowop_iter_->AtEnd() && num_ops) {
const CowOperation* op = &cowop_iter_->Get(); const CowOperation* op = &cowop_iter_->Get();
if (checkOrderedOp && !IsOrderedOp(*op)) { if (checkOrderedOp && !IsOrderedOp(*op)) {
break; break;
@ -85,7 +85,7 @@ bool Worker::MergeReplaceZeroOps() {
SNAP_LOG(INFO) << "MergeReplaceZeroOps started...."; SNAP_LOG(INFO) << "MergeReplaceZeroOps started....";
while (!cowop_iter_->Done()) { while (!cowop_iter_->AtEnd()) {
int num_ops = PAYLOAD_BUFFER_SZ / BLOCK_SZ; int num_ops = PAYLOAD_BUFFER_SZ / BLOCK_SZ;
std::vector<const CowOperation*> replace_zero_vec; std::vector<const CowOperation*> replace_zero_vec;
uint64_t source_offset; uint64_t source_offset;
@ -93,7 +93,7 @@ bool Worker::MergeReplaceZeroOps() {
int linear_blocks = PrepareMerge(&source_offset, &num_ops, &replace_zero_vec); int linear_blocks = PrepareMerge(&source_offset, &num_ops, &replace_zero_vec);
if (linear_blocks == 0) { if (linear_blocks == 0) {
// Merge complete // Merge complete
CHECK(cowop_iter_->Done()); CHECK(cowop_iter_->AtEnd());
break; break;
} }
@ -180,7 +180,7 @@ bool Worker::MergeOrderedOpsAsync() {
SNAP_LOG(INFO) << "MergeOrderedOpsAsync started...."; SNAP_LOG(INFO) << "MergeOrderedOpsAsync started....";
while (!cowop_iter_->Done()) { while (!cowop_iter_->AtEnd()) {
const CowOperation* cow_op = &cowop_iter_->Get(); const CowOperation* cow_op = &cowop_iter_->Get();
if (!IsOrderedOp(*cow_op)) { if (!IsOrderedOp(*cow_op)) {
break; break;
@ -361,7 +361,7 @@ bool Worker::MergeOrderedOps() {
SNAP_LOG(INFO) << "MergeOrderedOps started...."; SNAP_LOG(INFO) << "MergeOrderedOps started....";
while (!cowop_iter_->Done()) { while (!cowop_iter_->AtEnd()) {
const CowOperation* cow_op = &cowop_iter_->Get(); const CowOperation* cow_op = &cowop_iter_->Get();
if (!IsOrderedOp(*cow_op)) { if (!IsOrderedOp(*cow_op)) {
break; break;
@ -443,7 +443,7 @@ bool Worker::AsyncMerge() {
if (!MergeOrderedOpsAsync()) { if (!MergeOrderedOpsAsync()) {
SNAP_LOG(ERROR) << "MergeOrderedOpsAsync failed - Falling back to synchronous I/O"; SNAP_LOG(ERROR) << "MergeOrderedOpsAsync failed - Falling back to synchronous I/O";
// Reset the iter so that we retry the merge // Reset the iter so that we retry the merge
while (blocks_merged_in_group_ && !cowop_iter_->RDone()) { while (blocks_merged_in_group_ && !cowop_iter_->AtBegin()) {
cowop_iter_->Prev(); cowop_iter_->Prev();
blocks_merged_in_group_ -= 1; blocks_merged_in_group_ -= 1;
} }

View file

@ -809,7 +809,7 @@ void ReadAhead::InitializeRAIter() {
} }
bool ReadAhead::RAIterDone() { bool ReadAhead::RAIterDone() {
if (cowop_iter_->Done()) { if (cowop_iter_->AtEnd()) {
return true; return true;
} }
@ -827,7 +827,7 @@ void ReadAhead::RAIterNext() {
} }
void ReadAhead::RAResetIter(uint64_t num_blocks) { void ReadAhead::RAResetIter(uint64_t num_blocks) {
while (num_blocks && !cowop_iter_->RDone()) { while (num_blocks && !cowop_iter_->AtBegin()) {
cowop_iter_->Prev(); cowop_iter_->Prev();
num_blocks -= 1; num_blocks -= 1;
} }