blob: b250babc87a812ad29816a4560efcdc34506c98d [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
5#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_WRITER_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_WRITER_H__
7
8#include <vector>
9#include "chromeos/obsolete_logging.h"
10#include "update_engine/update_metadata.pb.h"
11#include "update_engine/utils.h"
12
13// ExtentWriter is an abstract class which synchronously writes to a given
14// file descriptor at the extents given.
15
16namespace chromeos_update_engine {
17
18// When an extent's start block is kSparseHole, that data written for that
19// extent will be dropped rather than written to the unerlying fd.
20const uint64 kSparseHole = kuint64max;
21
22class ExtentWriter {
23 public:
24 ExtentWriter() : end_called_(false) {}
25 virtual ~ExtentWriter() {
26 LOG_IF(ERROR, !end_called_) << "End() not called on ExtentWriter.";
27 }
28
29 // Returns true on success.
30 virtual bool Init(int fd,
31 const std::vector<Extent>& extents,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070032 uint32_t block_size) = 0;
Andrew de los Reyes80061062010-02-04 14:25:00 -080033
34 // Returns true on success.
35 virtual bool Write(const void* bytes, size_t count) = 0;
36
37 // Should be called when all writing is complete. Returns true on success.
38 // The fd is not closed. Caller is responsible for closing it.
39 bool End() {
40 end_called_ = true;
41 return EndImpl();
42 }
43 virtual bool EndImpl() = 0;
44 private:
45 bool end_called_;
46};
47
48// DirectExtentWriter is probably the simplest ExtentWriter implementation.
49// It writes the data directly into the extents.
50
51class DirectExtentWriter : public ExtentWriter {
52 public:
53 DirectExtentWriter()
54 : fd_(-1),
55 block_size_(0),
56 extent_bytes_written_(0),
57 next_extent_index_(0) {}
58 ~DirectExtentWriter() {}
59
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070060 bool Init(int fd, const std::vector<Extent>& extents, uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -080061 fd_ = fd;
62 block_size_ = block_size;
63 extents_ = extents;
64 return true;
65 }
66 bool Write(const void* bytes, size_t count);
67 bool EndImpl() {
68 return true;
69 }
70
71 private:
72 int fd_;
73
74 size_t block_size_;
75 // Bytes written into next_extent_index_ thus far
76 uint64 extent_bytes_written_;
77 std::vector<Extent> extents_;
78 // The next call to write should correspond to extents_[next_extent_index_]
79 std::vector<Extent>::size_type next_extent_index_;
80};
81
82// Takes an underlying ExtentWriter to which all operations are delegated.
83// When End() is called, ZeroPadExtentWriter ensures that the total number
84// of bytes written is a multiple of block_size_. If not, it writes zeros
85// to pad as needed.
86
87class ZeroPadExtentWriter : public ExtentWriter {
88 public:
89 ZeroPadExtentWriter(ExtentWriter* underlying_extent_writer)
90 : underlying_extent_writer_(underlying_extent_writer),
91 block_size_(0),
92 bytes_written_mod_block_size_(0) {}
93 ~ZeroPadExtentWriter() {}
94
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070095 bool Init(int fd, const std::vector<Extent>& extents, uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -080096 block_size_ = block_size;
97 return underlying_extent_writer_->Init(fd, extents, block_size);
98 }
99 bool Write(const void* bytes, size_t count) {
100 if (underlying_extent_writer_->Write(bytes, count)) {
101 bytes_written_mod_block_size_ += count;
102 bytes_written_mod_block_size_ %= block_size_;
103 return true;
104 }
105 return false;
106 }
107 bool EndImpl() {
108 if (bytes_written_mod_block_size_) {
109 const size_t write_size = block_size_ - bytes_written_mod_block_size_;
110 std::vector<char> zeros(write_size, 0);
111 TEST_AND_RETURN_FALSE(underlying_extent_writer_->Write(&zeros[0],
112 write_size));
113 }
114 return underlying_extent_writer_->End();
115 }
116
117 private:
118 ExtentWriter* underlying_extent_writer_; // The underlying ExtentWriter.
119 size_t block_size_;
120 size_t bytes_written_mod_block_size_;
121};
122
123} // namespace chromeos_update_engine
124
125#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_WRITER_H__