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() {}
// Return the file header.
virtual bool GetHeader(CowHeader* header) = 0;
virtual CowHeader& GetHeader() = 0;
// Return the file footer.
@ -68,13 +67,14 @@ class ICowReader {
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 {
public:
virtual ~ICowOpIter() {}
// True if there are no more items to read forward, false otherwise.
virtual bool Done() = 0;
// Returns true if the iterator is at the end of the operation list.
// If true, Get() and Next() must not be called.
virtual bool AtEnd() = 0;
// Read the current operation.
virtual const CowOperation& Get() = 0;
@ -82,11 +82,13 @@ class ICowOpIter {
// Advance to the next item.
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.
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 {
@ -107,7 +109,6 @@ class CowReader final : public ICowReader {
bool InitForMerge(android::base::unique_fd&& fd);
bool VerifyMergeOps() override;
bool GetHeader(CowHeader* header) override;
bool GetFooter(CowFooter* footer) 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);
CowReader reader;
CowHeader header;
CowFooter footer;
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.major_version, kCowVersionMajor);
ASSERT_EQ(header.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size);
CowFooter footer;
ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 100);
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
size_t i = 0;
while (!iter->Done()) {
while (!iter->AtEnd()) {
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
ASSERT_EQ(op->compression, kCowCompressNone);
@ -110,20 +111,21 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader;
CowHeader header;
CowFooter footer;
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.major_version, kCowVersionMajor);
ASSERT_EQ(header.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size);
CowFooter footer;
ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 4);
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
@ -135,7 +137,7 @@ TEST_F(CowTest, ReadWrite) {
std::string sink(data.size(), '\0');
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
@ -146,7 +148,7 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(sink, data);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
// Note: the zero operation gets split into two blocks.
@ -157,7 +159,7 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(op->source, 0);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
@ -167,7 +169,7 @@ TEST_F(CowTest, ReadWrite) {
ASSERT_EQ(op->source, 0);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, ReadWriteXor) {
@ -188,20 +190,21 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
CowReader reader;
CowHeader header;
CowFooter footer;
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.major_version, kCowVersionMajor);
ASSERT_EQ(header.minor_version, kCowVersionMinor);
ASSERT_EQ(header.block_size, options.block_size);
CowFooter footer;
ASSERT_TRUE(reader.GetFooter(&footer));
ASSERT_EQ(footer.op.num_ops, 4);
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
@ -213,7 +216,7 @@ TEST_F(CowTest, ReadWriteXor) {
std::string sink(data.size(), '\0');
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowXorOp);
@ -225,7 +228,7 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(sink, data);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
// Note: the zero operation gets split into two blocks.
@ -236,7 +239,7 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(op->source, 0);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
@ -246,7 +249,7 @@ TEST_F(CowTest, ReadWriteXor) {
ASSERT_EQ(op->source, 0);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, CompressGz) {
@ -270,7 +273,7 @@ TEST_F(CowTest, CompressGz) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
std::string sink(data.size(), '\0');
@ -283,7 +286,7 @@ TEST_F(CowTest, CompressGz) {
ASSERT_EQ(sink, data);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
class CompressionTest : public CowTest, public testing::WithParamInterface<const char*> {};
@ -325,7 +328,7 @@ TEST_P(CompressionTest, ThreadedBatchWrites) {
ASSERT_NE(iter, nullptr);
int total_blocks = 0;
while (!iter->Done()) {
while (!iter->AtEnd()) {
auto op = &iter->Get();
if (op->type == kCowXorOp) {
@ -399,7 +402,7 @@ TEST_P(CompressionTest, NoBatchWrites) {
ASSERT_NE(iter, nullptr);
int total_blocks = 0;
while (!iter->Done()) {
while (!iter->AtEnd()) {
auto op = &iter->Get();
if (op->type == kCowReplaceOp) {
@ -515,7 +518,7 @@ TEST_F(CowTest, ClusterCompressGz) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
std::string sink(data.size(), '\0');
@ -528,13 +531,13 @@ TEST_F(CowTest, ClusterCompressGz) {
ASSERT_EQ(sink, data);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
sink = {};
@ -546,13 +549,13 @@ TEST_F(CowTest, ClusterCompressGz) {
ASSERT_EQ(sink, data2);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, CompressTwoBlocks) {
@ -576,9 +579,9 @@ TEST_F(CowTest, CompressTwoBlocks) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
std::string sink(options.block_size, '\0');
@ -655,7 +658,7 @@ TEST_F(CowTest, AppendLabelSmall) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -665,21 +668,21 @@ TEST_F(CowTest, AppendLabelSmall) {
sink = {};
sink.resize(data2.size(), '\0');
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 3);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
ASSERT_EQ(sink, data2);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, AppendLabelMissing) {
@ -718,20 +721,20 @@ TEST_F(CowTest, AppendLabelMissing) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 0);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, AppendExtendedCorrupted) {
@ -776,13 +779,13 @@ TEST_F(CowTest, AppendExtendedCorrupted) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, AppendbyLabel) {
@ -827,7 +830,7 @@ TEST_F(CowTest, AppendbyLabel) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -837,7 +840,7 @@ TEST_F(CowTest, AppendbyLabel) {
sink = {};
sink.resize(options.block_size, '\0');
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -845,32 +848,32 @@ TEST_F(CowTest, AppendbyLabel) {
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 4);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, ClusterTest) {
@ -908,7 +911,7 @@ TEST_F(CowTest, ClusterTest) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -916,58 +919,58 @@ TEST_F(CowTest, ClusterTest) {
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 4);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowZeroOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 5);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowCopyOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 6);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, ClusterAppendTest) {
@ -1007,14 +1010,14 @@ TEST_F(CowTest, ClusterAppendTest) {
auto iter = reader.GetOpIter();
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
auto op = &iter->Get();
ASSERT_EQ(op->type, kCowLabelOp);
ASSERT_EQ(op->source, 50);
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowReplaceOp);
ASSERT_TRUE(ReadData(reader, *op, sink.data(), sink.size()));
@ -1022,13 +1025,13 @@ TEST_F(CowTest, ClusterAppendTest) {
iter->Next();
ASSERT_FALSE(iter->Done());
ASSERT_FALSE(iter->AtEnd());
op = &iter->Get();
ASSERT_EQ(op->type, kCowClusterOp);
iter->Next();
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
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,
const std::string& data) {
CowHeader header;
reader->GetHeader(&header);
const auto& header = reader->GetHeader();
std::string cmp = data;
cmp.resize(header.block_size, '\0');
@ -1116,7 +1118,7 @@ TEST_F(CowTest, ResumeMidCluster) {
size_t max_in_cluster = 0;
size_t num_in_cluster = 0;
size_t num_clusters = 0;
while (!iter->Done()) {
while (!iter->AtEnd()) {
const auto& op = iter->Get();
num_in_cluster++;
@ -1177,7 +1179,7 @@ TEST_F(CowTest, ResumeEndCluster) {
size_t max_in_cluster = 0;
size_t num_in_cluster = 0;
size_t num_clusters = 0;
while (!iter->Done()) {
while (!iter->AtEnd()) {
const auto& op = iter->Get();
num_in_cluster++;
@ -1229,7 +1231,7 @@ TEST_F(CowTest, DeleteMidCluster) {
size_t max_in_cluster = 0;
size_t num_in_cluster = 0;
size_t num_clusters = 0;
while (!iter->Done()) {
while (!iter->AtEnd()) {
const auto& op = iter->Get();
num_in_cluster++;
@ -1273,14 +1275,14 @@ TEST_F(CowTest, BigSeqOp) {
auto iter = reader.GetRevMergeOpIter();
for (int i = 0; i < seq_len; i++) {
ASSERT_TRUE(!iter->Done());
ASSERT_TRUE(!iter->AtEnd());
const auto& op = iter->Get();
ASSERT_EQ(op.new_block, seq_len - i);
iter->Next();
}
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, MissingSeqOp) {
@ -1324,7 +1326,7 @@ TEST_F(CowTest, ResumeSeqOp) {
auto reader = std::make_unique<CowReader>();
ASSERT_TRUE(reader->Parse(cow_->fd, 1));
auto itr = reader->GetRevMergeOpIter();
ASSERT_TRUE(itr->Done());
ASSERT_TRUE(itr->AtEnd());
writer = std::make_unique<CowWriter>(options);
ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
@ -1339,8 +1341,8 @@ TEST_F(CowTest, ResumeSeqOp) {
auto iter = reader->GetRevMergeOpIter();
uint64_t expected_block = 10;
while (!iter->Done() && expected_block > 0) {
ASSERT_FALSE(iter->Done());
while (!iter->AtEnd() && expected_block > 0) {
ASSERT_FALSE(iter->AtEnd());
const auto& op = iter->Get();
ASSERT_EQ(op.new_block, expected_block);
@ -1349,7 +1351,7 @@ TEST_F(CowTest, ResumeSeqOp) {
expected_block--;
}
ASSERT_EQ(expected_block, 0);
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, RevMergeOpItrTest) {
@ -1390,7 +1392,7 @@ TEST_F(CowTest, RevMergeOpItrTest) {
auto iter = reader.GetRevMergeOpIter();
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();
ASSERT_EQ(op.new_block, *expected_new_block);
@ -1399,7 +1401,7 @@ TEST_F(CowTest, RevMergeOpItrTest) {
expected_new_block++;
}
ASSERT_EQ(expected_new_block, revMergeOpSequence.end());
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, LegacyRevMergeOpItrTest) {
@ -1439,7 +1441,7 @@ TEST_F(CowTest, LegacyRevMergeOpItrTest) {
auto iter = reader.GetRevMergeOpIter();
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();
ASSERT_EQ(op.new_block, *expected_new_block);
@ -1448,7 +1450,7 @@ TEST_F(CowTest, LegacyRevMergeOpItrTest) {
expected_new_block++;
}
ASSERT_EQ(expected_new_block, revMergeOpSequence.end());
ASSERT_TRUE(iter->Done());
ASSERT_TRUE(iter->AtEnd());
}
TEST_F(CowTest, InvalidMergeOrderTest) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -98,8 +98,7 @@ bool SnapshotHandler::CommitMerge(int num_merge_ops) {
}
} else {
reader_->UpdateMergeOpsCompleted(num_merge_ops);
CowHeader header;
reader_->GetHeader(&header);
const auto& header = reader_->GetHeader();
if (lseek(cow_fd_.get(), 0, SEEK_SET) < 0) {
SNAP_PLOG(ERROR) << "lseek failed";
@ -154,7 +153,6 @@ bool SnapshotHandler::CheckMergeCompletionStatus() {
bool SnapshotHandler::ReadMetadata() {
reader_ = std::make_unique<CowReader>(CowReader::ReaderFlags::USERSPACE_MERGE, true);
CowHeader header;
CowOptions options;
SNAP_LOG(DEBUG) << "ReadMetadata: Parsing cow file";
@ -164,11 +162,7 @@ bool SnapshotHandler::ReadMetadata() {
return false;
}
if (!reader_->GetHeader(&header)) {
SNAP_LOG(ERROR) << "Failed to get header";
return false;
}
const auto& header = reader_->GetHeader();
if (!(header.block_size == BLOCK_SZ)) {
SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size;
return false;
@ -191,7 +185,7 @@ bool SnapshotHandler::ReadMetadata() {
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();
if (cow_op->type == kCowCopyOp) {
@ -244,8 +238,7 @@ bool SnapshotHandler::ReadMetadata() {
}
bool SnapshotHandler::MmapMetadata() {
CowHeader header;
reader_->GetHeader(&header);
const auto& header = reader_->GetHeader();
total_mapped_addr_length_ = header.header_size + BUFFER_REGION_DEFAULT_SIZE;
@ -367,8 +360,7 @@ bool SnapshotHandler::Start() {
}
uint64_t SnapshotHandler::GetBufferMetadataOffset() {
CowHeader header;
reader_->GetHeader(&header);
const auto& header = reader_->GetHeader();
return (header.header_size + sizeof(BufferState));
}
@ -383,8 +375,7 @@ uint64_t SnapshotHandler::GetBufferMetadataOffset() {
*
*/
size_t SnapshotHandler::GetBufferMetadataSize() {
CowHeader header;
reader_->GetHeader(&header);
const auto& header = reader_->GetHeader();
size_t buffer_size = header.buffer_size;
// If there is no scratch space, then just use the
@ -397,8 +388,7 @@ size_t SnapshotHandler::GetBufferMetadataSize() {
}
size_t SnapshotHandler::GetBufferDataOffset() {
CowHeader header;
reader_->GetHeader(&header);
const auto& header = reader_->GetHeader();
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.
*/
size_t SnapshotHandler::GetBufferDataSize() {
CowHeader header;
reader_->GetHeader(&header);
const auto& header = reader_->GetHeader();
size_t buffer_size = header.buffer_size;
// If there is no scratch space, then just use the
@ -421,8 +410,7 @@ size_t SnapshotHandler::GetBufferDataSize() {
}
struct BufferState* SnapshotHandler::GetBufferState() {
CowHeader header;
reader_->GetHeader(&header);
const auto& header = reader_->GetHeader();
struct BufferState* ra_state =
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);
do {
if (!cowop_iter_->Done() && num_ops) {
if (!cowop_iter_->AtEnd() && num_ops) {
const CowOperation* cow_op = &cowop_iter_->Get();
if (checkOrderedOp && !IsOrderedOp(*cow_op)) {
break;
@ -45,7 +45,7 @@ int Worker::PrepareMerge(uint64_t* source_offset, int* pending_ops,
num_ops -= 1;
nr_consecutive = 1;
while (!cowop_iter_->Done() && num_ops) {
while (!cowop_iter_->AtEnd() && num_ops) {
const CowOperation* op = &cowop_iter_->Get();
if (checkOrderedOp && !IsOrderedOp(*op)) {
break;
@ -85,7 +85,7 @@ bool Worker::MergeReplaceZeroOps() {
SNAP_LOG(INFO) << "MergeReplaceZeroOps started....";
while (!cowop_iter_->Done()) {
while (!cowop_iter_->AtEnd()) {
int num_ops = PAYLOAD_BUFFER_SZ / BLOCK_SZ;
std::vector<const CowOperation*> replace_zero_vec;
uint64_t source_offset;
@ -93,7 +93,7 @@ bool Worker::MergeReplaceZeroOps() {
int linear_blocks = PrepareMerge(&source_offset, &num_ops, &replace_zero_vec);
if (linear_blocks == 0) {
// Merge complete
CHECK(cowop_iter_->Done());
CHECK(cowop_iter_->AtEnd());
break;
}
@ -180,7 +180,7 @@ bool Worker::MergeOrderedOpsAsync() {
SNAP_LOG(INFO) << "MergeOrderedOpsAsync started....";
while (!cowop_iter_->Done()) {
while (!cowop_iter_->AtEnd()) {
const CowOperation* cow_op = &cowop_iter_->Get();
if (!IsOrderedOp(*cow_op)) {
break;
@ -361,7 +361,7 @@ bool Worker::MergeOrderedOps() {
SNAP_LOG(INFO) << "MergeOrderedOps started....";
while (!cowop_iter_->Done()) {
while (!cowop_iter_->AtEnd()) {
const CowOperation* cow_op = &cowop_iter_->Get();
if (!IsOrderedOp(*cow_op)) {
break;
@ -443,7 +443,7 @@ bool Worker::AsyncMerge() {
if (!MergeOrderedOpsAsync()) {
SNAP_LOG(ERROR) << "MergeOrderedOpsAsync failed - Falling back to synchronous I/O";
// 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();
blocks_merged_in_group_ -= 1;
}

View file

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