libsnapshot: Don't PrepMergeOps on resume

If we're reading up to a label, we're resuming setting up the file, and
there is no reason to expect the ops we require for sequence ops to be
present. In that case, skip prepping for merge, and return an empty
merge iterator if it is mistakenly requested.

Test: cow_api_test CowTest.ResumeSeqOp
Change-Id: Idd93bd4c4209197b9728fcb21a7191aae971b62d
This commit is contained in:
Daniel Rosenberg 2021-07-30 20:39:20 -07:00
parent e278cee742
commit a7573c7b90
2 changed files with 55 additions and 1 deletions

View file

@ -1113,6 +1113,54 @@ TEST_F(CowTest, MissingSeqOp) {
ASSERT_FALSE(reader.Parse(cow_->fd));
}
TEST_F(CowTest, ResumeSeqOp) {
CowOptions options;
auto writer = std::make_unique<CowWriter>(options);
const int seq_len = 10;
uint32_t sequence[seq_len];
for (int i = 0; i < seq_len; i++) {
sequence[i] = i + 1;
}
ASSERT_TRUE(writer->Initialize(cow_->fd));
ASSERT_TRUE(writer->AddSequenceData(seq_len, sequence));
ASSERT_TRUE(writer->AddZeroBlocks(1, seq_len / 2));
ASSERT_TRUE(writer->AddLabel(1));
ASSERT_TRUE(writer->AddZeroBlocks(1 + seq_len / 2, 1));
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
auto reader = std::make_unique<CowReader>();
ASSERT_TRUE(reader->Parse(cow_->fd, 1));
auto itr = reader->GetRevMergeOpIter();
ASSERT_TRUE(itr->Done());
writer = std::make_unique<CowWriter>(options);
ASSERT_TRUE(writer->InitializeAppend(cow_->fd, 1));
ASSERT_TRUE(writer->AddZeroBlocks(1 + seq_len / 2, seq_len / 2));
ASSERT_TRUE(writer->Finalize());
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
reader = std::make_unique<CowReader>();
ASSERT_TRUE(reader->Parse(cow_->fd));
auto iter = reader->GetRevMergeOpIter();
uint64_t expected_block = 10;
while (!iter->Done() && expected_block > 0) {
ASSERT_FALSE(iter->Done());
const auto& op = iter->Get();
ASSERT_EQ(op.new_block, expected_block);
iter->Next();
expected_block--;
}
ASSERT_EQ(expected_block, 0);
ASSERT_TRUE(iter->Done());
}
TEST_F(CowTest, RevMergeOpItrTest) {
CowOptions options;
options.cluster_ops = 5;

View file

@ -34,7 +34,11 @@
namespace android {
namespace snapshot {
CowReader::CowReader() : fd_(-1), header_(), fd_size_(0) {}
CowReader::CowReader()
: fd_(-1),
header_(),
fd_size_(0),
merge_op_blocks_(std::make_shared<std::vector<uint32_t>>()) {}
static void SHA256(const void*, size_t, uint8_t[]) {
#if 0
@ -150,6 +154,8 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> lab
if (!ParseOps(label)) {
return false;
}
// If we're resuming a write, we're not ready to merge
if (label.has_value()) return true;
return PrepMergeOps();
}