blob: 0ea39fce491afb4a1150d3d19b57e816e2754be1 [file] [log] [blame]
Andrew de los Reyes80061062010-02-04 14:25:00 -08001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gilad Arnoldcf175a02014-07-10 16:48:47 -07005#ifndef UPDATE_ENGINE_EXTENT_WRITER_H_
6#define UPDATE_ENGINE_EXTENT_WRITER_H_
Andrew de los Reyes80061062010-02-04 14:25:00 -08007
8#include <vector>
Alex Deymo8427b4a2014-11-05 14:00:32 -08009
10#include <base/logging.h>
11
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080012#include "update_engine/file_descriptor.h"
Andrew de los Reyes80061062010-02-04 14:25:00 -080013#include "update_engine/update_metadata.pb.h"
14#include "update_engine/utils.h"
15
16// ExtentWriter is an abstract class which synchronously writes to a given
17// file descriptor at the extents given.
18
19namespace chromeos_update_engine {
20
Andrew de los Reyes80061062010-02-04 14:25:00 -080021class ExtentWriter {
22 public:
23 ExtentWriter() : end_called_(false) {}
24 virtual ~ExtentWriter() {
25 LOG_IF(ERROR, !end_called_) << "End() not called on ExtentWriter.";
26 }
27
28 // Returns true on success.
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080029 virtual bool Init(FileDescriptorPtr fd,
Andrew de los Reyes80061062010-02-04 14:25:00 -080030 const std::vector<Extent>& extents,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070031 uint32_t block_size) = 0;
Andrew de los Reyes80061062010-02-04 14:25:00 -080032
33 // Returns true on success.
34 virtual bool Write(const void* bytes, size_t count) = 0;
35
36 // Should be called when all writing is complete. Returns true on success.
37 // The fd is not closed. Caller is responsible for closing it.
38 bool End() {
39 end_called_ = true;
40 return EndImpl();
41 }
42 virtual bool EndImpl() = 0;
43 private:
44 bool end_called_;
45};
46
47// DirectExtentWriter is probably the simplest ExtentWriter implementation.
48// It writes the data directly into the extents.
49
50class DirectExtentWriter : public ExtentWriter {
51 public:
52 DirectExtentWriter()
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080053 : fd_(nullptr),
Andrew de los Reyes80061062010-02-04 14:25:00 -080054 block_size_(0),
55 extent_bytes_written_(0),
56 next_extent_index_(0) {}
57 ~DirectExtentWriter() {}
58
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080059 bool Init(FileDescriptorPtr fd,
60 const std::vector<Extent>& extents,
61 uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -080062 fd_ = fd;
63 block_size_ = block_size;
64 extents_ = extents;
65 return true;
66 }
67 bool Write(const void* bytes, size_t count);
68 bool EndImpl() {
69 return true;
70 }
71
72 private:
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080073 FileDescriptorPtr fd_;
Chris Masone4dc2ada2010-09-23 12:43:03 -070074
Andrew de los Reyes80061062010-02-04 14:25:00 -080075 size_t block_size_;
76 // Bytes written into next_extent_index_ thus far
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070077 uint64_t extent_bytes_written_;
Andrew de los Reyes80061062010-02-04 14:25:00 -080078 std::vector<Extent> extents_;
79 // The next call to write should correspond to extents_[next_extent_index_]
80 std::vector<Extent>::size_type next_extent_index_;
81};
82
83// Takes an underlying ExtentWriter to which all operations are delegated.
84// When End() is called, ZeroPadExtentWriter ensures that the total number
85// of bytes written is a multiple of block_size_. If not, it writes zeros
86// to pad as needed.
87
88class ZeroPadExtentWriter : public ExtentWriter {
89 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -070090 explicit ZeroPadExtentWriter(ExtentWriter* underlying_extent_writer)
Andrew de los Reyes80061062010-02-04 14:25:00 -080091 : underlying_extent_writer_(underlying_extent_writer),
92 block_size_(0),
93 bytes_written_mod_block_size_(0) {}
94 ~ZeroPadExtentWriter() {}
95
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080096 bool Init(FileDescriptorPtr fd,
97 const std::vector<Extent>& extents,
98 uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -080099 block_size_ = block_size;
100 return underlying_extent_writer_->Init(fd, extents, block_size);
101 }
102 bool Write(const void* bytes, size_t count) {
103 if (underlying_extent_writer_->Write(bytes, count)) {
104 bytes_written_mod_block_size_ += count;
105 bytes_written_mod_block_size_ %= block_size_;
106 return true;
107 }
108 return false;
109 }
110 bool EndImpl() {
111 if (bytes_written_mod_block_size_) {
112 const size_t write_size = block_size_ - bytes_written_mod_block_size_;
113 std::vector<char> zeros(write_size, 0);
114 TEST_AND_RETURN_FALSE(underlying_extent_writer_->Write(&zeros[0],
115 write_size));
116 }
117 return underlying_extent_writer_->End();
118 }
119
120 private:
121 ExtentWriter* underlying_extent_writer_; // The underlying ExtentWriter.
122 size_t block_size_;
123 size_t bytes_written_mod_block_size_;
124};
125
126} // namespace chromeos_update_engine
127
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700128#endif // UPDATE_ENGINE_EXTENT_WRITER_H_