7 #include "packager/file/threaded_io_file.h" 9 #include "packager/base/bind.h" 10 #include "packager/base/bind_helpers.h" 11 #include "packager/base/location.h" 12 #include "packager/base/threading/worker_pool.h" 16 using base::subtle::NoBarrier_Load;
17 using base::subtle::NoBarrier_Store;
19 ThreadedIoFile::ThreadedIoFile(std::unique_ptr<File, FileCloser> internal_file,
21 uint64_t io_cache_size,
22 uint64_t io_block_size)
23 : File(internal_file->file_name()),
24 internal_file_(
std::move(internal_file)),
26 cache_(io_cache_size),
27 io_buffer_(io_block_size),
32 flush_complete_event_(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
33 base::WaitableEvent::InitialState::NOT_SIGNALED),
34 internal_file_error_(0),
35 task_exit_event_(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
36 base::WaitableEvent::InitialState::NOT_SIGNALED) {
37 DCHECK(internal_file_);
40 ThreadedIoFile::~ThreadedIoFile() {}
43 DCHECK(internal_file_);
45 if (!internal_file_->Open())
49 size_ = internal_file_->Size();
51 base::WorkerPool::PostTask(
53 base::Bind(&ThreadedIoFile::TaskHandler, base::Unretained(
this)),
59 DCHECK(internal_file_);
62 if (mode_ == kOutputMode)
66 task_exit_event_.Wait();
68 result &= internal_file_.release()->Close();
74 DCHECK(internal_file_);
75 DCHECK_EQ(kInputMode, mode_);
77 if (NoBarrier_Load(&eof_) && !cache_.BytesCached())
80 if (NoBarrier_Load(&internal_file_error_))
81 return NoBarrier_Load(&internal_file_error_);
83 uint64_t bytes_read = cache_.Read(buffer, length);
84 position_ += bytes_read;
90 DCHECK(internal_file_);
91 DCHECK_EQ(kOutputMode, mode_);
93 if (NoBarrier_Load(&internal_file_error_))
94 return NoBarrier_Load(&internal_file_error_);
96 uint64_t bytes_written = cache_.Write(buffer, length);
97 position_ += bytes_written;
98 if (position_ > size_)
101 return bytes_written;
105 DCHECK(internal_file_);
111 DCHECK(internal_file_);
112 DCHECK_EQ(kOutputMode, mode_);
114 if (NoBarrier_Load(&internal_file_error_))
119 flush_complete_event_.Wait();
120 return internal_file_->Flush();
124 if (mode_ == kOutputMode) {
128 if (!internal_file_->Seek(position))
134 task_exit_event_.Wait();
135 bool result = internal_file_->Seek(position);
138 if (!internal_file_->Seek(position_) && (position != position_)) {
139 LOG(WARNING) <<
"Seek failed. ThreadedIoFile left in invalid state.";
144 base::WorkerPool::PostTask(
146 base::Bind(&ThreadedIoFile::TaskHandler, base::Unretained(
this)),
151 position_ = position;
158 *position = position_;
162 void ThreadedIoFile::TaskHandler() {
163 if (mode_ == kInputMode)
167 task_exit_event_.Signal();
170 void ThreadedIoFile::RunInInputMode() {
171 DCHECK(internal_file_);
172 DCHECK_EQ(kInputMode, mode_);
175 int64_t read_result =
176 internal_file_->Read(&io_buffer_[0], io_buffer_.size());
177 if (read_result <= 0) {
178 NoBarrier_Store(&eof_, read_result == 0);
179 NoBarrier_Store(&internal_file_error_, read_result);
183 if (cache_.Write(&io_buffer_[0], read_result) == 0) {
189 void ThreadedIoFile::RunInOutputMode() {
190 DCHECK(internal_file_);
191 DCHECK_EQ(kOutputMode, mode_);
194 uint64_t write_bytes = cache_.Read(&io_buffer_[0], io_buffer_.size());
195 if (write_bytes == 0) {
199 flush_complete_event_.Signal();
204 uint64_t bytes_written(0);
205 while (bytes_written < write_bytes) {
206 int64_t write_result = internal_file_->Write(
207 &io_buffer_[bytes_written], write_bytes - bytes_written);
208 if (write_result < 0) {
209 NoBarrier_Store(&internal_file_error_, write_result);
213 flush_complete_event_.Signal();
217 bytes_written += write_result;
int64_t Write(const void *buffer, uint64_t length) override
All the methods that are virtual are virtual for mocking.
bool Open() override
Internal open. Should not be used directly.
bool Seek(uint64_t position) override
bool Tell(uint64_t *position) override
int64_t Read(void *buffer, uint64_t length) override