blob: 883507a45d238b36d7adf7dc467865c7440e4a2f [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
Andrew de los Reyes80061062010-02-04 14:25:00 -080012#include "update_engine/update_metadata.pb.h"
13#include "update_engine/utils.h"
14
15// ExtentWriter is an abstract class which synchronously writes to a given
16// file descriptor at the extents given.
17
18namespace chromeos_update_engine {
19
Andrew de los Reyes80061062010-02-04 14:25:00 -080020class ExtentWriter {
21 public:
22 ExtentWriter() : end_called_(false) {}
23 virtual ~ExtentWriter() {
24 LOG_IF(ERROR, !end_called_) << "End() not called on ExtentWriter.";
25 }
26
27 // Returns true on success.
28 virtual bool Init(int fd,
29 const std::vector<Extent>& extents,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070030 uint32_t block_size) = 0;
Andrew de los Reyes80061062010-02-04 14:25:00 -080031
32 // Returns true on success.
33 virtual bool Write(const void* bytes, size_t count) = 0;
34
35 // Should be called when all writing is complete. Returns true on success.
36 // The fd is not closed. Caller is responsible for closing it.
37 bool End() {
38 end_called_ = true;
39 return EndImpl();
40 }
41 virtual bool EndImpl() = 0;
42 private:
43 bool end_called_;
44};
45
46// DirectExtentWriter is probably the simplest ExtentWriter implementation.
47// It writes the data directly into the extents.
48
49class DirectExtentWriter : public ExtentWriter {
50 public:
51 DirectExtentWriter()
52 : fd_(-1),
53 block_size_(0),
54 extent_bytes_written_(0),
55 next_extent_index_(0) {}
56 ~DirectExtentWriter() {}
57
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070058 bool Init(int fd, const std::vector<Extent>& extents, uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -080059 fd_ = fd;
60 block_size_ = block_size;
61 extents_ = extents;
62 return true;
63 }
64 bool Write(const void* bytes, size_t count);
65 bool EndImpl() {
66 return true;
67 }
68
69 private:
70 int fd_;
Chris Masone4dc2ada2010-09-23 12:43:03 -070071
Andrew de los Reyes80061062010-02-04 14:25:00 -080072 size_t block_size_;
73 // Bytes written into next_extent_index_ thus far
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070074 uint64_t extent_bytes_written_;
Andrew de los Reyes80061062010-02-04 14:25:00 -080075 std::vector<Extent> extents_;
76 // The next call to write should correspond to extents_[next_extent_index_]
77 std::vector<Extent>::size_type next_extent_index_;
78};
79
80// Takes an underlying ExtentWriter to which all operations are delegated.
81// When End() is called, ZeroPadExtentWriter ensures that the total number
82// of bytes written is a multiple of block_size_. If not, it writes zeros
83// to pad as needed.
84
85class ZeroPadExtentWriter : public ExtentWriter {
86 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -070087 explicit ZeroPadExtentWriter(ExtentWriter* underlying_extent_writer)
Andrew de los Reyes80061062010-02-04 14:25:00 -080088 : underlying_extent_writer_(underlying_extent_writer),
89 block_size_(0),
90 bytes_written_mod_block_size_(0) {}
91 ~ZeroPadExtentWriter() {}
92
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070093 bool Init(int fd, const std::vector<Extent>& extents, uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -080094 block_size_ = block_size;
95 return underlying_extent_writer_->Init(fd, extents, block_size);
96 }
97 bool Write(const void* bytes, size_t count) {
98 if (underlying_extent_writer_->Write(bytes, count)) {
99 bytes_written_mod_block_size_ += count;
100 bytes_written_mod_block_size_ %= block_size_;
101 return true;
102 }
103 return false;
104 }
105 bool EndImpl() {
106 if (bytes_written_mod_block_size_) {
107 const size_t write_size = block_size_ - bytes_written_mod_block_size_;
108 std::vector<char> zeros(write_size, 0);
109 TEST_AND_RETURN_FALSE(underlying_extent_writer_->Write(&zeros[0],
110 write_size));
111 }
112 return underlying_extent_writer_->End();
113 }
114
115 private:
116 ExtentWriter* underlying_extent_writer_; // The underlying ExtentWriter.
117 size_t block_size_;
118 size_t bytes_written_mod_block_size_;
119};
120
121} // namespace chromeos_update_engine
122
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700123#endif // UPDATE_ENGINE_EXTENT_WRITER_H_