Merge changes from topic "revert-2781730-YHMBOJWFHT" into main
* changes: Revert "libsnapshot: Add Parser base class" Revert "libsnapshot: Add Parser v3 + stub"
This commit is contained in:
commit
77aa824423
11 changed files with 73 additions and 253 deletions
|
@ -198,7 +198,6 @@ cc_library_static {
|
|||
"libsnapshot_cow/cow_format.cpp",
|
||||
"libsnapshot_cow/cow_reader.cpp",
|
||||
"libsnapshot_cow/parser_v2.cpp",
|
||||
"libsnapshot_cow/parser_v3.cpp",
|
||||
"libsnapshot_cow/snapshot_reader.cpp",
|
||||
"libsnapshot_cow/writer_base.cpp",
|
||||
"libsnapshot_cow/writer_v2.cpp",
|
||||
|
|
|
@ -185,6 +185,7 @@ class CowReader final : public ICowReader {
|
|||
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_;
|
||||
ReaderFlags reader_flag_;
|
||||
bool is_merge_{};
|
||||
uint8_t compression_type_ = kCowCompressNone;
|
||||
};
|
||||
|
||||
// Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader.
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <zlib.h>
|
||||
|
||||
#include "cow_decompress.h"
|
||||
#include "libsnapshot/cow_format.h"
|
||||
#include "parser_v2.h"
|
||||
|
||||
namespace android {
|
||||
|
@ -84,6 +85,7 @@ std::unique_ptr<CowReader> CowReader::CloneCowReader() {
|
|||
cow->data_loc_ = data_loc_;
|
||||
cow->block_pos_index_ = block_pos_index_;
|
||||
cow->is_merge_ = is_merge_;
|
||||
cow->compression_type_ = compression_type_;
|
||||
return cow;
|
||||
}
|
||||
|
||||
|
@ -102,14 +104,11 @@ bool CowReader::InitForMerge(android::base::unique_fd&& fd) {
|
|||
PLOG(ERROR) << "lseek header failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_GE(header_.prefix.header_size, sizeof(CowHeader));
|
||||
CHECK_LE(header_.prefix.header_size, sizeof(header_));
|
||||
|
||||
if (!android::base::ReadFully(fd_, &header_, header_.prefix.header_size)) {
|
||||
if (!android::base::ReadFully(fd_, &header_, sizeof(header_))) {
|
||||
PLOG(ERROR) << "read header failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -125,35 +124,52 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> lab
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<CowParserBase> parser;
|
||||
switch (header_.prefix.major_version) {
|
||||
case 1:
|
||||
case 2:
|
||||
parser = std::make_unique<CowParserV2>();
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown version: " << header_.prefix.major_version;
|
||||
CowParserV2 parser;
|
||||
if (!parser.Parse(fd, header_, label)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
footer_ = parser.footer();
|
||||
fd_size_ = parser.fd_size();
|
||||
last_label_ = parser.last_label();
|
||||
data_loc_ = parser.data_loc();
|
||||
ops_ = std::make_shared<std::vector<CowOperation>>(parser.ops()->size());
|
||||
|
||||
// Translate the operation buffer from on disk to in memory
|
||||
for (size_t i = 0; i < parser.ops()->size(); i++) {
|
||||
const auto& v2_op = parser.ops()->at(i);
|
||||
|
||||
auto& new_op = ops_->at(i);
|
||||
new_op.type = v2_op.type;
|
||||
new_op.data_length = v2_op.data_length;
|
||||
|
||||
if (v2_op.new_block > std::numeric_limits<uint32_t>::max()) {
|
||||
LOG(ERROR) << "Out-of-range new block in COW op: " << v2_op;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
new_op.new_block = v2_op.new_block;
|
||||
|
||||
if (!parser->Parse(fd, header_, label)) {
|
||||
return false;
|
||||
uint64_t source_info = v2_op.source;
|
||||
if (new_op.type != kCowLabelOp) {
|
||||
source_info &= kCowOpSourceInfoDataMask;
|
||||
if (source_info != v2_op.source) {
|
||||
LOG(ERROR) << "Out-of-range source value in COW op: " << v2_op;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (v2_op.compression != kCowCompressNone) {
|
||||
if (compression_type_ == kCowCompressNone) {
|
||||
compression_type_ = v2_op.compression;
|
||||
} else if (compression_type_ != v2_op.compression) {
|
||||
LOG(ERROR) << "COW has mixed compression types which is not supported;"
|
||||
<< " previously saw " << compression_type_ << ", got "
|
||||
<< v2_op.compression << ", op: " << v2_op;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
new_op.source_info = source_info;
|
||||
}
|
||||
|
||||
TranslatedCowOps ops_info;
|
||||
if (!parser->Translate(&ops_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
header_ = ops_info.header;
|
||||
ops_ = std::move(ops_info.ops);
|
||||
footer_ = parser->footer();
|
||||
fd_size_ = parser->fd_size();
|
||||
last_label_ = parser->last_label();
|
||||
data_loc_ = parser->data_loc();
|
||||
|
||||
// If we're resuming a write, we're not ready to merge
|
||||
if (label.has_value()) return true;
|
||||
return PrepMergeOps();
|
||||
|
@ -648,7 +664,7 @@ class CowDataStream final : public IByteStream {
|
|||
};
|
||||
|
||||
uint8_t CowReader::GetCompressionType() {
|
||||
return header_.compression_algorithm;
|
||||
return compression_type_;
|
||||
}
|
||||
|
||||
ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
|
||||
|
|
|
@ -74,13 +74,13 @@ static void ShowBad(CowReader& reader, const CowOperation* op) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeaderV3& header) {
|
||||
static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) {
|
||||
CowParserV2 parser;
|
||||
if (!parser.Parse(fd, header)) {
|
||||
LOG(ERROR) << "v2 parser failed";
|
||||
return false;
|
||||
}
|
||||
for (const auto& op : *parser.get_v2ops()) {
|
||||
for (const auto& op : *parser.ops()) {
|
||||
std::cout << op << "\n";
|
||||
if (auto iter = parser.data_loc()->find(op.new_block); iter != parser.data_loc()->end()) {
|
||||
std::cout << " data loc: " << iter->second << "\n";
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
//
|
||||
// Copyright (C) 2023 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <libsnapshot/cow_format.h>
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
struct TranslatedCowOps {
|
||||
CowHeaderV3 header;
|
||||
std::shared_ptr<std::vector<CowOperationV3>> ops;
|
||||
};
|
||||
|
||||
class CowParserBase {
|
||||
public:
|
||||
virtual ~CowParserBase() = default;
|
||||
|
||||
virtual bool Parse(android::base::borrowed_fd fd, const CowHeaderV3& header,
|
||||
std::optional<uint64_t> label = {}) = 0;
|
||||
virtual bool Translate(TranslatedCowOps* out) = 0;
|
||||
virtual std::optional<CowFooter> footer() const { return std::nullopt; }
|
||||
virtual std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc() const = 0;
|
||||
|
||||
uint64_t fd_size() const { return fd_size_; }
|
||||
const std::optional<uint64_t>& last_label() const { return last_label_; }
|
||||
|
||||
protected:
|
||||
CowHeaderV3 header_ = {};
|
||||
uint64_t fd_size_;
|
||||
std::optional<uint64_t> last_label_;
|
||||
};
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
|
@ -17,14 +17,13 @@
|
|||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include "libsnapshot/cow_format.h"
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
using android::base::borrowed_fd;
|
||||
|
||||
bool CowParserV2::Parse(borrowed_fd fd, const CowHeaderV3& header, std::optional<uint64_t> label) {
|
||||
bool CowParserV2::Parse(borrowed_fd fd, const CowHeader& header, std::optional<uint64_t> label) {
|
||||
auto pos = lseek(fd.get(), 0, SEEK_END);
|
||||
if (pos < 0) {
|
||||
PLOG(ERROR) << "lseek end failed";
|
||||
|
@ -48,7 +47,8 @@ bool CowParserV2::Parse(borrowed_fd fd, const CowHeaderV3& header, std::optional
|
|||
return false;
|
||||
}
|
||||
|
||||
if (header_.prefix.major_version > 2 || header_.prefix.minor_version != 0) {
|
||||
if ((header_.prefix.major_version > kCowVersionMajor) ||
|
||||
(header_.prefix.minor_version != kCowVersionMinor)) {
|
||||
LOG(ERROR) << "Header version mismatch, "
|
||||
<< "major version: " << header_.prefix.major_version
|
||||
<< ", expected: " << kCowVersionMajor
|
||||
|
@ -190,57 +190,11 @@ bool CowParserV2::ParseOps(borrowed_fd fd, std::optional<uint64_t> label) {
|
|||
}
|
||||
}
|
||||
|
||||
v2_ops_ = ops_buffer;
|
||||
v2_ops_->shrink_to_fit();
|
||||
ops_ = ops_buffer;
|
||||
ops_->shrink_to_fit();
|
||||
data_loc_ = data_loc;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CowParserV2::Translate(TranslatedCowOps* out) {
|
||||
out->ops = std::make_shared<std::vector<CowOperationV3>>(v2_ops_->size());
|
||||
|
||||
// Translate the operation buffer from on disk to in memory
|
||||
for (size_t i = 0; i < out->ops->size(); i++) {
|
||||
const auto& v2_op = v2_ops_->at(i);
|
||||
|
||||
auto& new_op = out->ops->at(i);
|
||||
new_op.type = v2_op.type;
|
||||
new_op.data_length = v2_op.data_length;
|
||||
|
||||
if (v2_op.new_block > std::numeric_limits<uint32_t>::max()) {
|
||||
LOG(ERROR) << "Out-of-range new block in COW op: " << v2_op;
|
||||
return false;
|
||||
}
|
||||
new_op.new_block = v2_op.new_block;
|
||||
|
||||
uint64_t source_info = v2_op.source;
|
||||
if (new_op.type != kCowLabelOp) {
|
||||
source_info &= kCowOpSourceInfoDataMask;
|
||||
if (source_info != v2_op.source) {
|
||||
LOG(ERROR) << "Out-of-range source value in COW op: " << v2_op;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (v2_op.compression != kCowCompressNone) {
|
||||
if (header_.compression_algorithm == kCowCompressNone) {
|
||||
header_.compression_algorithm = v2_op.compression;
|
||||
} else if (header_.compression_algorithm != v2_op.compression) {
|
||||
LOG(ERROR) << "COW has mixed compression types which is not supported;"
|
||||
<< " previously saw " << header_.compression_algorithm << ", got "
|
||||
<< v2_op.compression << ", op: " << v2_op;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
new_op.source_info = source_info;
|
||||
}
|
||||
|
||||
out->header = header_;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> CowParserV2::data_loc() const {
|
||||
return data_loc_;
|
||||
}
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
||||
|
|
|
@ -17,31 +17,36 @@
|
|||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <libsnapshot/cow_format.h>
|
||||
#include <libsnapshot_cow/parser_base.h>
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
class CowParserV2 final : public CowParserBase {
|
||||
class CowParserV2 {
|
||||
public:
|
||||
bool Parse(android::base::borrowed_fd fd, const CowHeaderV3& header,
|
||||
std::optional<uint64_t> label = {}) override;
|
||||
bool Translate(TranslatedCowOps* out) override;
|
||||
std::optional<CowFooter> footer() const override { return footer_; }
|
||||
bool Parse(android::base::borrowed_fd fd, const CowHeader& header,
|
||||
std::optional<uint64_t> label = {});
|
||||
|
||||
const CowHeader& header() const { return header_; }
|
||||
std::shared_ptr<std::vector<CowOperationV2>> get_v2ops() { return v2_ops_; }
|
||||
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc() const override;
|
||||
const std::optional<CowFooter>& footer() const { return footer_; }
|
||||
std::shared_ptr<std::vector<CowOperationV2>> ops() { return ops_; }
|
||||
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc() const { return data_loc_; }
|
||||
uint64_t fd_size() const { return fd_size_; }
|
||||
const std::optional<uint64_t>& last_label() const { return last_label_; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_;
|
||||
bool ParseOps(android::base::borrowed_fd fd, std::optional<uint64_t> label);
|
||||
std::shared_ptr<std::vector<CowOperationV2>> v2_ops_;
|
||||
|
||||
CowHeader header_ = {};
|
||||
std::optional<CowFooter> footer_;
|
||||
std::shared_ptr<std::vector<CowOperationV2>> ops_;
|
||||
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_;
|
||||
uint64_t fd_size_;
|
||||
std::optional<uint64_t> last_label_;
|
||||
};
|
||||
|
||||
} // namespace snapshot
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright (C) 2023 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "parser_v3.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include "libsnapshot/cow_format.h"
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
using android::base::borrowed_fd;
|
||||
|
||||
bool CowParserV3::Parse(borrowed_fd fd, const CowHeaderV3& header, std::optional<uint64_t> label) {
|
||||
LOG(ERROR) << "this function should never be called";
|
||||
if (fd.get() || sizeof(header) > 0 || label) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CowParserV3::ParseOps(android::base::borrowed_fd fd, std::optional<uint64_t> label) {
|
||||
LOG(ERROR) << "this function should never be called";
|
||||
if (fd.get() || label) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CowParserV3::Translate(TranslatedCowOps* out) {
|
||||
out->ops = ops_;
|
||||
out->header = header_;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (C) 2023 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright (C) 2023 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <libsnapshot/cow_format.h>
|
||||
#include <libsnapshot_cow/parser_base.h>
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
class CowParserV3 final : public CowParserBase {
|
||||
public:
|
||||
bool Parse(android::base::borrowed_fd fd, const CowHeaderV3& header,
|
||||
std::optional<uint64_t> label = {}) override;
|
||||
bool Translate(TranslatedCowOps* out) override;
|
||||
|
||||
private:
|
||||
bool ParseOps(android::base::borrowed_fd fd, std::optional<uint64_t> label);
|
||||
|
||||
CowHeaderV3 header_ = {};
|
||||
std::shared_ptr<std::vector<CowOperationV3>> ops_;
|
||||
};
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
|
@ -273,11 +273,10 @@ bool CowWriterV2::OpenForAppend(uint64_t label) {
|
|||
if (!ReadCowHeader(fd_, &header_v3)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
header_ = header_v3;
|
||||
|
||||
CowParserV2 parser;
|
||||
if (!parser.Parse(fd_, header_v3, {label})) {
|
||||
if (!parser.Parse(fd_, header_, {label})) {
|
||||
return false;
|
||||
}
|
||||
if (header_.prefix.major_version > 2) {
|
||||
|
@ -293,7 +292,7 @@ bool CowWriterV2::OpenForAppend(uint64_t label) {
|
|||
footer_.op.num_ops = 0;
|
||||
InitPos();
|
||||
|
||||
for (const auto& op : *parser.get_v2ops()) {
|
||||
for (const auto& op : *parser.ops()) {
|
||||
AddOperation(op);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ bool SnapshotHandler::CommitMerge(int num_merge_ops) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!android::base::WriteFully(cow_fd_, &header, header.prefix.header_size)) {
|
||||
if (!android::base::WriteFully(cow_fd_, &header, sizeof(CowHeader))) {
|
||||
SNAP_PLOG(ERROR) << "Write to header failed";
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue