1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <future>
18 #include "writer_base.h"
19 
20 namespace android {
21 namespace snapshot {
22 
23 class CowWriterV2 : public CowWriterBase {
24   public:
25     explicit CowWriterV2(const CowOptions& options, android::base::unique_fd&& fd);
26     ~CowWriterV2() override;
27 
28     bool Initialize(std::optional<uint64_t> label = {}) override;
29     bool Finalize() override;
30     CowSizeInfo GetCowSizeInfo() const override;
31 
32   protected:
33     virtual bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
34     virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
35     virtual bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size,
36                                uint32_t old_block, uint16_t offset) override;
37     virtual bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
38     virtual bool EmitLabel(uint64_t label) override;
39     virtual bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
40 
41   private:
42     bool EmitCluster();
43     bool EmitClusterIfNeeded();
44     bool EmitBlocks(uint64_t new_block_start, const void* data, size_t size, uint64_t old_block,
45                     uint16_t offset, CowOperationType type);
46     void SetupHeaders();
47     void SetupWriteOptions();
48     bool ParseOptions();
49     bool OpenForWrite();
50     bool OpenForAppend(uint64_t label);
51     bool GetDataPos(uint64_t* pos);
52     bool WriteRawData(const void* data, size_t size);
53     bool WriteOperation(const CowOperationV2& op, const void* data = nullptr, size_t size = 0);
54     void AddOperation(const CowOperationV2& op);
55     void InitPos();
56     void InitBatchWrites();
57     void InitWorkers();
58     bool FlushCluster();
59 
60     bool CompressBlocks(size_t num_blocks, const void* data);
61     bool Truncate(off_t length);
62     bool EnsureSpaceAvailable(const uint64_t bytes_needed) const;
63 
64   private:
65     CowFooter footer_{};
66     CowHeader header_{};
67     CowCompression compression_;
68     // in the case that we are using one thread for compression, we can store and re-use the same
69     // compressor
70     std::unique_ptr<ICompressor> compressor_;
71     uint64_t current_op_pos_ = 0;
72     uint64_t next_op_pos_ = 0;
73     uint64_t next_data_pos_ = 0;
74     uint64_t current_data_pos_ = 0;
75     ssize_t total_data_written_ = 0;
76     uint32_t cluster_size_ = 0;
77     uint32_t current_cluster_size_ = 0;
78     uint64_t current_data_size_ = 0;
79     bool merge_in_progress_ = false;
80 
81     int num_compress_threads_ = 1;
82     std::vector<std::unique_ptr<CompressWorker>> compress_threads_;
83     std::vector<std::future<bool>> threads_;
84     std::vector<std::vector<uint8_t>> compressed_buf_;
85     std::vector<std::vector<uint8_t>>::iterator buf_iter_;
86 
87     std::vector<std::unique_ptr<CowOperationV2>> opbuffer_vec_;
88     std::vector<std::unique_ptr<uint8_t[]>> databuffer_vec_;
89     std::unique_ptr<struct iovec[]> cowop_vec_;
90     int op_vec_index_ = 0;
91 
92     std::unique_ptr<struct iovec[]> data_vec_;
93     int data_vec_index_ = 0;
94     bool batch_write_ = false;
95 };
96 
97 }  // namespace snapshot
98 }  // namespace android
99