Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: net/disk_cache/simple/simple_synchronous_entry.cc

Issue 12192005: Add new simple disk cache backend. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remediation to review Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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.
4
5 #include "net/disk_cache/simple/simple_synchronous_entry.h"
6
7 #include <algorithm>
8 #include <cstring>
9
10 #include "base/basictypes.h"
11 #include "base/file_util.h"
12 #include "base/hash.h"
13 #include "base/location.h"
14 #include "base/message_loop_proxy.h"
15 #include "base/sha1.h"
16 #include "base/stringprintf.h"
17 #include "base/task_runner.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/net_errors.h"
20 #include "net/disk_cache/simple/simple_disk_format.h"
21
22 using base::ClosePlatformFile;
23 using base::GetPlatformFileInfo;
24 using base::PlatformFileError;
25 using base::PlatformFileInfo;
26 using base::PLATFORM_FILE_CREATE_ALWAYS;
27 using base::PLATFORM_FILE_OK;
28 using base::PLATFORM_FILE_OPEN;
29 using base::PLATFORM_FILE_READ;
30 using base::PLATFORM_FILE_WRITE;
31 using base::ReadPlatformFile;
32 using base::TaskRunner;
33 using base::Time;
34 using base::TruncatePlatformFile;
35 using base::WritePlatformFile;
36
37 namespace {
38
39 std::string GetFilenameForKeyAndIndex(const std::string& key, int index) {
40 const std::string sha_hash = base::SHA1HashString(key);
41 return StringPrintf("%02x%02x%02x%02x%02x_%1d",
42 implicit_cast<unsigned char>(sha_hash[0]),
43 implicit_cast<unsigned char>(sha_hash[1]),
44 implicit_cast<unsigned char>(sha_hash[2]),
45 implicit_cast<unsigned char>(sha_hash[3]),
46 implicit_cast<unsigned char>(sha_hash[4]), index);
47 }
48
49 int32 DataSizeFromKeyAndFileSize(size_t key_size, int64 file_size) {
50 return file_size - key_size - sizeof(disk_cache::SimpleFileHeader);
51 }
52
53 int64 FileOffsetFromDataOffset(size_t key_size, int offset) {
54 const int64 headers_size = sizeof(disk_cache::SimpleFileHeader) +
55 key_size;
56 return headers_size + offset;
57 }
58
59 } // namespace
60
61 namespace disk_cache {
62
63 // static
64 void SimpleSynchronousEntry::OpenEntry(
65 const FilePath& path,
66 const std::string& key,
67 const scoped_refptr<TaskRunner>& callback_runner,
68 const SynchronousEntryCallback& callback) {
69 SimpleSynchronousEntry* sync_entry =
70 new SimpleSynchronousEntry(callback_runner, path, key);
71
72 if (!sync_entry->InitializeForOpen()) {
73 delete sync_entry;
74 sync_entry = NULL;
75 }
76 callback_runner->PostTask(FROM_HERE,
77 base::Bind(callback, sync_entry,
78 sync_entry ? net::OK : net::ERR_FAILED));
79 }
80
81 // static
82 void SimpleSynchronousEntry::CreateEntry(
83 const FilePath& path,
84 const std::string& key,
85 const scoped_refptr<TaskRunner>& callback_runner,
86 const SynchronousEntryCallback& callback) {
87 SimpleSynchronousEntry* sync_entry =
88 new SimpleSynchronousEntry(callback_runner, path, key);
89
90 if (!sync_entry->InitializeForCreate()) {
91 delete sync_entry;
92 sync_entry = NULL;
93 }
94 callback_runner->PostTask(FROM_HERE,
95 base::Bind(callback, sync_entry,
96 sync_entry ? net::OK : net::ERR_FAILED));
97 }
98
99 // static
100 void SimpleSynchronousEntry::DoomEntry(
101 const FilePath& path,
102 const std::string& key,
103 scoped_refptr<TaskRunner> callback_runner,
104 const net::CompletionCallback& callback) {
105 for (int i = 0; i < kIndexCount; ++i) {
106 bool delete_result =
107 file_util::Delete(path.AppendASCII(GetFilenameForKeyAndIndex(key, i)),
108 false);
109 DCHECK(delete_result);
110 }
111 if (!callback.is_null())
112 callback_runner->PostTask(FROM_HERE, base::Bind(callback, net::OK));
113 }
114
115 void SimpleSynchronousEntry::DoomAndClose() {
116 scoped_refptr<TaskRunner> callback_runner = callback_runner_;
117 FilePath path = path_;
118 std::string key = key_;
119
120 Close();
121 // |this| is now deleted.
122
123 DoomEntry(path, key, callback_runner, net::CompletionCallback());
124 }
125
126 void SimpleSynchronousEntry::Close() {
127 for (int i = 0; i < kIndexCount; ++i) {
128 bool result = ClosePlatformFile(files_[i]);
129 DCHECK(result);
130 }
131 delete this;
132 }
133
134 void SimpleSynchronousEntry::ReadData(
135 int index,
136 int offset,
137 net::IOBuffer* buf,
138 int buf_len,
139 const SynchronousEntryCallback& callback) {
140 DCHECK(initialized_);
141 if (status_[index].mode != EntryStatus::ENTRY_READER)
142 status_[index].data_offset = 0;
143 DCHECK_EQ(status_[index].data_offset, offset);
144 status_[index].mode = EntryStatus::ENTRY_READER;
145
146 int64 file_offset = FileOffsetFromDataOffset(key_.size(), offset);
147 int bytes_read = ReadPlatformFile(files_[index], file_offset,
148 buf->data(), buf_len);
149 if (bytes_read > 0) {
150 last_used_ = Time::Now();
151 status_[index].data_offset += bytes_read;
152 }
153 int result = (bytes_read >= 0) ? bytes_read : net::ERR_FAILED;
154 callback_runner_->PostTask(FROM_HERE, base::Bind(callback, this, result));
155 }
156
157 void SimpleSynchronousEntry::WriteData(
158 int index,
159 int offset,
160 net::IOBuffer* buf,
161 int buf_len,
162 const SynchronousEntryCallback& callback,
163 bool truncate) {
164 DCHECK(initialized_);
165 if (status_[index].mode != EntryStatus::ENTRY_WRITER)
166 status_[index].data_offset = 0;
167 DCHECK_EQ(status_[index].data_offset, offset);
168 status_[index].mode = EntryStatus::ENTRY_WRITER;
169
170 int64 file_offset = FileOffsetFromDataOffset(key_.size(), offset);
171 if (buf_len > 0) {
172 if (WritePlatformFile(files_[index], file_offset, buf->data(), buf_len) !=
173 buf_len) {
174 callback_runner_->PostTask(FROM_HERE,
175 base::Bind(callback, this, net::ERR_FAILED));
pasko-google - do not use 2013/02/11 13:59:25 I am wondering why some errors are logged and some
gavinp 2013/02/11 17:55:50 The rule is that there's logging in code that has
176 return;
177 }
178 data_size_[index] = std::max(data_size_[index], offset + buf_len);
179 status_[index].data_offset += buf_len;
180 }
181 if (truncate) {
182 data_size_[index] = offset + buf_len;
183 if (!TruncatePlatformFile(files_[index], file_offset + buf_len)) {
184 callback_runner_->PostTask(FROM_HERE,
185 base::Bind(callback, this, net::ERR_FAILED));
186 return;
187 }
188 }
189 last_modified_ = Time::Now();
190 callback_runner_->PostTask(FROM_HERE, base::Bind(callback, this, buf_len));
191 }
192
193 SimpleSynchronousEntry::EntryStatus::EntryStatus()
194 : mode(ENTRY_UNINITIALIZED),
195 data_offset(0) {
196 }
197
198 SimpleSynchronousEntry::SimpleSynchronousEntry(
199 const scoped_refptr<TaskRunner>& callback_runner,
200 const FilePath& path,
201 const std::string& key) : callback_runner_(callback_runner),
202 path_(path),
203 key_(key),
204 initialized_(false) {
205 }
206
207 SimpleSynchronousEntry::~SimpleSynchronousEntry() {
208 }
209
210 bool SimpleSynchronousEntry::OpenOrCreateFiles(bool create) {
211 for (int i = 0; i < kIndexCount; ++i) {
212 FilePath filename = path_.AppendASCII(GetFilenameForKeyAndIndex(key_, i));
213 int flags = PLATFORM_FILE_READ | PLATFORM_FILE_WRITE;
214 if (create)
215 flags |= PLATFORM_FILE_CREATE_ALWAYS;
216 else
217 flags |= PLATFORM_FILE_OPEN;
218 PlatformFileError error;
219 files_[i] = CreatePlatformFile(filename, flags, NULL, &error);
220 if (error != PLATFORM_FILE_OK) {
221 while (--i >= 0) {
222 bool did_close = ClosePlatformFile(files_[i]);
223 DCHECK(did_close);
224 }
225 return false;
226 }
227 }
228
229 for (int i = 0; i < kIndexCount; ++i) {
230 PlatformFileInfo file_info;
231 CHECK(GetPlatformFileInfo(files_[i], &file_info));
232 last_used_ = std::max(last_used_, file_info.last_accessed);
pasko-google - do not use 2013/02/11 13:59:25 I am wondering how last_used is actually used. Her
gavinp 2013/02/11 17:55:50 Yeah. Tricky. Could force this issue with filesyst
233 last_modified_ = std::max(last_modified_, file_info.last_modified);
234 data_size_[i] = DataSizeFromKeyAndFileSize(key_.size(), file_info.size);
235 }
236
237 return true;
238 }
239
240 bool SimpleSynchronousEntry::InitializeForOpen() {
241 DCHECK(!initialized_);
242 if (!OpenOrCreateFiles(false))
243 return false;
244
245 for (int i = 0; i < kIndexCount; ++i) {
246 SimpleFileHeader header;
247 if (ReadPlatformFile(files_[i], 0, reinterpret_cast<char*>(&header),
248 sizeof(header)) != sizeof(header)) {
249 return false;
250 }
251 if (header.initial_magic_number != kSimpleInitialMagicNumber ||
252 header.version != kSimpleVersion) {
253 DVLOG(6) << "Error: No magic number.";
pasko-google - do not use 2013/02/11 13:59:25 This is a pretty serious error, so sounds rather L
gavinp 2013/02/11 17:55:50 I'll leave it LOG(WARNING) for now with a TODO. We
254 return false;
255 }
256
257 char key[1024];
258 DCHECK_LE(header.key_length, sizeof(key));
259 if (ReadPlatformFile(files_[i], sizeof(header), key, header.key_length) !=
260 implicit_cast<int>(header.key_length)) {
261 DVLOG(6) << "Error: No key.";
262 return false;
263 }
264 if (std::memcmp(static_cast<const void*>(key_.data()),
265 static_cast<const void*>(key),
266 key_.size()) != 0) {
267 DVLOG(6) << "Error: Bad key.";
268 return false;
269 }
270
271 if (base::Hash(key, header.key_length) == header.key_hash) {
272 DVLOG(6) << "Error: Bad key hash.";
273 return false;
274 }
275 }
276
277 initialized_ = true;
278 return true;
279 }
280
281 bool SimpleSynchronousEntry::InitializeForCreate() {
282 DCHECK(!initialized_);
283 if (!OpenOrCreateFiles(true))
284 return false;
285
286 for (int i = 0; i < kIndexCount; ++i) {
287 SimpleFileHeader header;
288 header.initial_magic_number = kSimpleInitialMagicNumber;
289 header.version = kSimpleVersion;
290
291 header.key_length = key_.size();
292 header.key_hash = base::Hash(key_);
293
294 if (WritePlatformFile(files_[i], 0, reinterpret_cast<char*>(&header),
295 sizeof(header)) != sizeof(header)) {
pasko-google - do not use 2013/02/11 13:59:25 would be helpful: LOG(WARNING) or explanation wher
gavinp 2013/02/11 17:55:50 Done.
296 return false;
297 }
298
299 if (WritePlatformFile(files_[i], sizeof(header), key_.data(),
300 key_.size()) != implicit_cast<int>(key_.size())) {
301 return false;
302 }
303 }
304
305 initialized_ = true;
306 return true;
307 }
308
309 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698