1 // Copyright (c) 2012 The Chromium 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.
5 #include "net/disk_cache/blockfile/file.h"
8 #include "base/lazy_instance.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/run_loop.h"
12 #include "base/task_runner_util.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "net/base/net_errors.h"
15 #include "net/disk_cache/disk_cache.h"
19 // The maximum number of threads for this pool.
20 const int kMaxThreads
= 5;
22 class FileWorkerPool
: public base::SequencedWorkerPool
{
24 FileWorkerPool() : base::SequencedWorkerPool(kMaxThreads
, "CachePool") {}
27 ~FileWorkerPool() override
{}
30 base::LazyInstance
<FileWorkerPool
>::Leaky s_worker_pool
=
31 LAZY_INSTANCE_INITIALIZER
;
35 namespace disk_cache
{
37 File::File(base::File file
)
40 base_file_(file
.Pass()) {
43 bool File::Init(const base::FilePath
& name
) {
44 if (base_file_
.IsValid())
47 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
48 base::File::FLAG_WRITE
;
49 base_file_
.Initialize(name
, flags
);
50 return base_file_
.IsValid();
53 bool File::IsValid() const {
54 return base_file_
.IsValid();
57 bool File::Read(void* buffer
, size_t buffer_len
, size_t offset
) {
58 DCHECK(base_file_
.IsValid());
59 if (buffer_len
> static_cast<size_t>(kint32max
) ||
60 offset
> static_cast<size_t>(kint32max
)) {
64 int ret
= base_file_
.Read(offset
, static_cast<char*>(buffer
), buffer_len
);
65 return (static_cast<size_t>(ret
) == buffer_len
);
68 bool File::Write(const void* buffer
, size_t buffer_len
, size_t offset
) {
69 DCHECK(base_file_
.IsValid());
70 if (buffer_len
> static_cast<size_t>(kint32max
) ||
71 offset
> static_cast<size_t>(kint32max
)) {
75 int ret
= base_file_
.Write(offset
, static_cast<const char*>(buffer
),
77 return (static_cast<size_t>(ret
) == buffer_len
);
80 bool File::Read(void* buffer
, size_t buffer_len
, size_t offset
,
81 FileIOCallback
* callback
, bool* completed
) {
82 DCHECK(base_file_
.IsValid());
86 return Read(buffer
, buffer_len
, offset
);
89 if (buffer_len
> static_cast<size_t>(kint32max
) ||
90 offset
> static_cast<size_t>(kint32max
)) {
94 base::PostTaskAndReplyWithResult(
95 s_worker_pool
.Pointer(), FROM_HERE
,
96 base::Bind(&File::DoRead
, this, buffer
, buffer_len
, offset
),
97 base::Bind(&File::OnOperationComplete
, this, callback
));
103 bool File::Write(const void* buffer
, size_t buffer_len
, size_t offset
,
104 FileIOCallback
* callback
, bool* completed
) {
105 DCHECK(base_file_
.IsValid());
109 return Write(buffer
, buffer_len
, offset
);
112 if (buffer_len
> static_cast<size_t>(kint32max
) ||
113 offset
> static_cast<size_t>(kint32max
)) {
117 base::PostTaskAndReplyWithResult(
118 s_worker_pool
.Pointer(), FROM_HERE
,
119 base::Bind(&File::DoWrite
, this, buffer
, buffer_len
, offset
),
120 base::Bind(&File::OnOperationComplete
, this, callback
));
126 bool File::SetLength(size_t length
) {
127 DCHECK(base_file_
.IsValid());
128 if (length
> kuint32max
)
131 return base_file_
.SetLength(length
);
134 size_t File::GetLength() {
135 DCHECK(base_file_
.IsValid());
136 int64 len
= base_file_
.GetLength();
138 if (len
> static_cast<int64
>(kuint32max
))
141 return static_cast<size_t>(len
);
145 void File::WaitForPendingIO(int* num_pending_io
) {
146 // We are running unit tests so we should wait for all callbacks. Sadly, the
147 // worker pool only waits for tasks on the worker pool, not the "Reply" tasks
148 // so we have to let the current message loop to run.
149 s_worker_pool
.Get().FlushForTesting();
150 base::RunLoop().RunUntilIdle();
154 void File::DropPendingIO() {
161 base::PlatformFile
File::platform_file() const {
162 return base_file_
.GetPlatformFile();
165 // Runs on a worker thread.
166 int File::DoRead(void* buffer
, size_t buffer_len
, size_t offset
) {
167 if (Read(const_cast<void*>(buffer
), buffer_len
, offset
))
168 return static_cast<int>(buffer_len
);
170 return net::ERR_CACHE_READ_FAILURE
;
173 // Runs on a worker thread.
174 int File::DoWrite(const void* buffer
, size_t buffer_len
, size_t offset
) {
175 if (Write(const_cast<void*>(buffer
), buffer_len
, offset
))
176 return static_cast<int>(buffer_len
);
178 return net::ERR_CACHE_WRITE_FAILURE
;
181 // This method actually makes sure that the last reference to the file doesn't
182 // go away on the worker pool.
183 void File::OnOperationComplete(FileIOCallback
* callback
, int result
) {
184 callback
->OnFileIOComplete(result
);
187 } // namespace disk_cache