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/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 virtual ~FileWorkerPool() {}
30 base::LazyInstance
<FileWorkerPool
>::Leaky s_worker_pool
=
31 LAZY_INSTANCE_INITIALIZER
;
35 namespace disk_cache
{
37 File::File(base::PlatformFile file
)
41 sync_platform_file_(base::kInvalidPlatformFileValue
) {
44 bool File::Init(const base::FilePath
& name
) {
48 int flags
= base::PLATFORM_FILE_OPEN
|
49 base::PLATFORM_FILE_READ
|
50 base::PLATFORM_FILE_WRITE
;
51 platform_file_
= base::CreatePlatformFile(name
, flags
, NULL
, NULL
);
52 if (platform_file_
< 0) {
61 base::PlatformFile
File::platform_file() const {
62 return platform_file_
;
65 bool File::IsValid() const {
68 return (base::kInvalidPlatformFileValue
!= platform_file_
);
71 bool File::Read(void* buffer
, size_t buffer_len
, size_t offset
) {
73 if (buffer_len
> static_cast<size_t>(kint32max
) ||
74 offset
> static_cast<size_t>(kint32max
)) {
78 int ret
= base::ReadPlatformFile(platform_file_
, offset
,
79 static_cast<char*>(buffer
), buffer_len
);
80 return (static_cast<size_t>(ret
) == buffer_len
);
83 bool File::Write(const void* buffer
, size_t buffer_len
, size_t offset
) {
85 if (buffer_len
> static_cast<size_t>(kint32max
) ||
86 offset
> static_cast<size_t>(kint32max
)) {
90 int ret
= base::WritePlatformFile(platform_file_
, offset
,
91 static_cast<const char*>(buffer
),
93 return (static_cast<size_t>(ret
) == buffer_len
);
96 bool File::Read(void* buffer
, size_t buffer_len
, size_t offset
,
97 FileIOCallback
* callback
, bool* completed
) {
102 return Read(buffer
, buffer_len
, offset
);
105 if (buffer_len
> static_cast<size_t>(kint32max
) ||
106 offset
> static_cast<size_t>(kint32max
)) {
110 base::PostTaskAndReplyWithResult(
111 s_worker_pool
.Pointer(), FROM_HERE
,
112 base::Bind(&File::DoRead
, this, buffer
, buffer_len
, offset
),
113 base::Bind(&File::OnOperationComplete
, this, callback
));
119 bool File::Write(const void* buffer
, size_t buffer_len
, size_t offset
,
120 FileIOCallback
* callback
, bool* completed
) {
125 return Write(buffer
, buffer_len
, offset
);
128 if (buffer_len
> static_cast<size_t>(kint32max
) ||
129 offset
> static_cast<size_t>(kint32max
)) {
133 base::PostTaskAndReplyWithResult(
134 s_worker_pool
.Pointer(), FROM_HERE
,
135 base::Bind(&File::DoWrite
, this, buffer
, buffer_len
, offset
),
136 base::Bind(&File::OnOperationComplete
, this, callback
));
142 bool File::SetLength(size_t length
) {
144 if (length
> kuint32max
)
147 return base::TruncatePlatformFile(platform_file_
, length
);
150 size_t File::GetLength() {
152 int64 len
= base::SeekPlatformFile(platform_file_
,
153 base::PLATFORM_FILE_FROM_END
, 0);
155 if (len
> static_cast<int64
>(kuint32max
))
158 return static_cast<size_t>(len
);
162 void File::WaitForPendingIO(int* num_pending_io
) {
163 // We are running unit tests so we should wait for all callbacks. Sadly, the
164 // worker pool only waits for tasks on the worker pool, not the "Reply" tasks
165 // so we have to let the current message loop to run.
166 s_worker_pool
.Get().FlushForTesting();
167 base::RunLoop().RunUntilIdle();
171 void File::DropPendingIO() {
177 base::ClosePlatformFile(platform_file_
);
180 // Runs on a worker thread.
181 int File::DoRead(void* buffer
, size_t buffer_len
, size_t offset
) {
182 if (Read(const_cast<void*>(buffer
), buffer_len
, offset
))
183 return static_cast<int>(buffer_len
);
185 return net::ERR_CACHE_READ_FAILURE
;
188 // Runs on a worker thread.
189 int File::DoWrite(const void* buffer
, size_t buffer_len
, size_t offset
) {
190 if (Write(const_cast<void*>(buffer
), buffer_len
, offset
))
191 return static_cast<int>(buffer_len
);
193 return net::ERR_CACHE_WRITE_FAILURE
;
196 // This method actually makes sure that the last reference to the file doesn't
197 // go away on the worker pool.
198 void File::OnOperationComplete(FileIOCallback
* callback
, int result
) {
199 callback
->OnFileIOComplete(result
);
202 } // namespace disk_cache