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

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

Issue 13839011: Asynchronous initialization in Simple Index. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: egor's change is in Created 7 years, 8 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
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/simple/simple_index.h" 5 #include "net/disk_cache/simple/simple_index.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/task_runner.h" 10 #include "base/task_runner.h"
(...skipping 19 matching lines...) Expand all
30 return true; 30 return true;
31 } 31 }
32 32
33 bool CheckHeader(disk_cache::SimpleIndexFile::Header header) { 33 bool CheckHeader(disk_cache::SimpleIndexFile::Header header) {
34 return header.number_of_entries <= kMaxEntiresInIndex && 34 return header.number_of_entries <= kMaxEntiresInIndex &&
35 header.initial_magic_number == 35 header.initial_magic_number ==
36 disk_cache::kSimpleIndexInitialMagicNumber && 36 disk_cache::kSimpleIndexInitialMagicNumber &&
37 header.version == disk_cache::kSimpleVersion; 37 header.version == disk_cache::kSimpleVersion;
38 } 38 }
39 39
40 class FileAutoCloser {
41 public:
42 explicit FileAutoCloser(base::PlatformFile* file) : file_(file) { }
gavinp 2013/04/11 09:56:32 No need for base::PlatformFile*. You can just use
felipeg 2013/04/11 11:25:45 Done.
felipeg 2013/04/11 11:25:45 Done.
43 ~FileAutoCloser() {
44 if (file_)
gavinp 2013/04/11 09:56:32 Can this ever be null?
felipeg 2013/04/11 11:25:45 Done.
45 base::ClosePlatformFile(*file_);
gavinp 2013/04/11 09:56:32 No error checking?
felipeg 2013/04/11 11:25:45 Nope the only error that can happen is that the fi
46 }
47 private:
gavinp 2013/04/11 09:56:32 DISALLOW_COPY_AND_ASSIGN(FileAutoCloser);
48 base::PlatformFile* file_;
49 };
50
40 } // namespace 51 } // namespace
41 52
42 namespace disk_cache { 53 namespace disk_cache {
43 54
44 SimpleIndex::SimpleIndex( 55 SimpleIndex::SimpleIndex(
45 const scoped_refptr<base::TaskRunner>& cache_thread, 56 const scoped_refptr<base::TaskRunner>& cache_thread,
57 const scoped_refptr<base::TaskRunner>& io_thread,
46 const base::FilePath& path) 58 const base::FilePath& path)
47 : path_(path), 59 : cache_size_(0),
48 cache_thread_(cache_thread) { 60 initialized_(false),
49 index_filename_ = path_.AppendASCII("index"); 61 index_filename_(path.AppendASCII("simple-index")),
62 cache_thread_(cache_thread),
63 io_thread_(io_thread) {}
64
65 void SimpleIndex::Initialize() {
66 MergeCallback merge_callback = base::Bind(&SimpleIndex::MergeInitializingSet,
67 this->AsWeakPtr());
68 base::WorkerPool::PostTask(FROM_HERE,
69 base::Bind(&SimpleIndex::LoadFromDisk,
70 index_filename_,
71 io_thread_,
72 merge_callback),
73 true);
50 } 74 }
51 75
52 bool SimpleIndex::Initialize() { 76 // static
53 if (!OpenIndexFile()) 77 void SimpleIndex::LoadFromDisk(
54 return RestoreFromDisk(); 78 const base::FilePath& index_filename,
79 const scoped_refptr<base::TaskRunner>& io_thread,
80 const MergeCallback& merge_callback) {
81 // Open the index file.
82 base::PlatformFileError error;
83 base::PlatformFile index_file = base::CreatePlatformFile(
84 index_filename,
85 base::PLATFORM_FILE_OPEN_ALWAYS |
86 base::PLATFORM_FILE_READ |
87 base::PLATFORM_FILE_WRITE,
88 NULL,
89 &error);
90 scoped_ptr<FileAutoCloser> auto_close_index_file(
gavinp 2013/04/11 09:56:32 Why is this a scoped_ptr?
felipeg 2013/04/11 11:25:45 Done.
felipeg 2013/04/11 11:25:45 Done.
91 new FileAutoCloser(&index_file));
92 if (error != base::PLATFORM_FILE_OK) {
93 LOG(ERROR) << "Error opening file " << index_filename.value();
94 return RestoreFromDisk(index_filename, io_thread, merge_callback);
95 }
96
55 uLong incremental_crc = crc32(0L, Z_NULL, 0); 97 uLong incremental_crc = crc32(0L, Z_NULL, 0);
56 int64 index_file_offset = 0; 98 int64 index_file_offset = 0;
57 SimpleIndexFile::Header header; 99 SimpleIndexFile::Header header;
58 if (base::ReadPlatformFile(index_file_, 100 if (base::ReadPlatformFile(index_file,
59 index_file_offset, 101 index_file_offset,
60 reinterpret_cast<char*>(&header), 102 reinterpret_cast<char*>(&header),
61 sizeof(header)) != sizeof(header)) { 103 sizeof(header)) != sizeof(header)) {
62 return RestoreFromDisk(); 104 return RestoreFromDisk(index_filename, io_thread, merge_callback);
gavinp 2013/04/11 09:56:32 Should we delete the index file here, too?
felipeg 2013/04/11 11:25:45 we don't need to. RestoreFromDisk and Merge will t
63 } 105 }
64 index_file_offset += sizeof(header); 106 index_file_offset += sizeof(header);
65 incremental_crc = crc32(incremental_crc, 107 incremental_crc = crc32(incremental_crc,
66 reinterpret_cast<const Bytef*>(&header), 108 reinterpret_cast<const Bytef*>(&header),
67 implicit_cast<uInt>(sizeof(header))); 109 implicit_cast<uInt>(sizeof(header)));
68 110
69 if (!CheckHeader(header)) { 111 if (!CheckHeader(header)) {
70 LOG(ERROR) << "Invalid header on Simple Cache Index."; 112 LOG(ERROR) << "Invalid header on Simple Cache Index.";
71 return RestoreFromDisk(); 113 return RestoreFromDisk(index_filename, io_thread, merge_callback);
72 } 114 }
73 115
74 const int entries_buffer_size = 116 const int entries_buffer_size =
75 header.number_of_entries * SimpleIndexFile::kEntryMetadataSize; 117 header.number_of_entries * SimpleIndexFile::kEntryMetadataSize;
76 118
77 scoped_ptr<char[]> entries_buffer(new char[entries_buffer_size]); 119 scoped_ptr<char[]> entries_buffer(new char[entries_buffer_size]);
78 if (base::ReadPlatformFile(index_file_, 120 if (base::ReadPlatformFile(index_file,
79 index_file_offset, 121 index_file_offset,
80 entries_buffer.get(), 122 entries_buffer.get(),
81 entries_buffer_size) != entries_buffer_size) { 123 entries_buffer_size) != entries_buffer_size) {
82 return RestoreFromDisk(); 124 return RestoreFromDisk(index_filename, io_thread, merge_callback);
83 } 125 }
84 index_file_offset += entries_buffer_size; 126 index_file_offset += entries_buffer_size;
85 incremental_crc = crc32(incremental_crc, 127 incremental_crc = crc32(incremental_crc,
86 reinterpret_cast<const Bytef*>(entries_buffer.get()), 128 reinterpret_cast<const Bytef*>(entries_buffer.get()),
87 implicit_cast<uInt>(entries_buffer_size)); 129 implicit_cast<uInt>(entries_buffer_size));
88 130
89 SimpleIndexFile::Footer footer; 131 SimpleIndexFile::Footer footer;
90 if (base::ReadPlatformFile(index_file_, 132 if (base::ReadPlatformFile(index_file,
91 index_file_offset, 133 index_file_offset,
92 reinterpret_cast<char*>(&footer), 134 reinterpret_cast<char*>(&footer),
93 sizeof(footer)) != sizeof(footer)) { 135 sizeof(footer)) != sizeof(footer)) {
94 return RestoreFromDisk(); 136 return RestoreFromDisk(index_filename, io_thread, merge_callback);
95 } 137 }
96 const uint32 crc_read = footer.crc; 138 const uint32 crc_read = footer.crc;
97 const uint32 crc_calculated = incremental_crc; 139 const uint32 crc_calculated = incremental_crc;
98 if (crc_read != crc_calculated) 140 if (crc_read != crc_calculated)
99 return RestoreFromDisk(); 141 return RestoreFromDisk(index_filename, io_thread, merge_callback);
100 142
143 scoped_ptr<EntrySet> initializing_set(new EntrySet());
gavinp 2013/04/11 09:56:32 This name is a bit confusing to me. How about inde
felipeg 2013/04/11 11:25:45 Done.
gavinp 2013/04/11 11:35:39 Done?
101 int entries_buffer_offset = 0; 144 int entries_buffer_offset = 0;
102 while(entries_buffer_offset < entries_buffer_size) { 145 while(entries_buffer_offset < entries_buffer_size) {
103 SimpleIndexFile::EntryMetadata entry_metadata; 146 SimpleIndexFile::EntryMetadata entry_metadata;
104 SimpleIndexFile::EntryMetadata::DeSerialize( 147 SimpleIndexFile::EntryMetadata::DeSerialize(
105 &entries_buffer.get()[entries_buffer_offset], &entry_metadata); 148 &entries_buffer.get()[entries_buffer_offset], &entry_metadata);
106 InsertInternal(entry_metadata); 149 InsertInternal(initializing_set.get(), entry_metadata);
107 entries_buffer_offset += SimpleIndexFile::kEntryMetadataSize; 150 entries_buffer_offset += SimpleIndexFile::kEntryMetadataSize;
108 } 151 }
109 DCHECK_EQ(header.number_of_entries, entries_set_.size()); 152 DCHECK_EQ(header.number_of_entries, initializing_set->size());
110 CloseIndexFile(); 153
111 return true; 154 io_thread->PostTask(FROM_HERE,
155 base::Bind(merge_callback,
156 base::Passed(&initializing_set)));
112 } 157 }
113 158
114 void SimpleIndex::Insert(const std::string& key) { 159 void SimpleIndex::Insert(const std::string& key) {
115 // Upon insert we don't know yet the size of the entry. 160 // Upon insert we don't know yet the size of the entry.
116 // It will be updated later when the SimpleEntryImpl finishes opening or 161 // It will be updated later when the SynchronousEntryImpl finish and the
117 // creating the new entry, and then UpdateEntrySize will be called. 162 // UpdateEntrySize will be called.
gavinp 2013/04/11 09:56:32 I liked this comment better when it was: // It
felipeg 2013/04/11 11:25:45 Done.
118 InsertInternal(SimpleIndexFile::EntryMetadata(GetEntryHashForKey(key), 163 const std::string hash_key = GetEntryHashForKey(key);
119 base::Time::Now(), 0)); 164 InsertInternal(&entries_set_, SimpleIndexFile::EntryMetadata(
165 hash_key,
166 base::Time::Now(), 0));
167 if (!initialized_)
168 removals_set_.erase(hash_key);
120 } 169 }
121 170
122 void SimpleIndex::Remove(const std::string& key) { 171 void SimpleIndex::Remove(const std::string& key) {
123 UpdateEntrySize(key, 0); 172 UpdateEntrySize(key, 0);
124 entries_set_.erase(GetEntryHashForKey(key)); 173 const std::string hash_key = GetEntryHashForKey(key);
174 entries_set_.erase(hash_key);
175
176 if (!initialized_)
177 removals_set_.insert(hash_key);
125 } 178 }
126 179
127 bool SimpleIndex::Has(const std::string& key) const { 180 bool SimpleIndex::Has(const std::string& key) const {
128 return entries_set_.count(GetEntryHashForKey(key)) != 0; 181 // If not initialized, always return true, forcing it to go to the disk.
182 return !initialized_ || entries_set_.count(GetEntryHashForKey(key)) != 0;
129 } 183 }
130 184
131 bool SimpleIndex::UseIfExists(const std::string& key) { 185 bool SimpleIndex::UseIfExists(const std::string& key) {
186 // Always update the last used time, even if it is during initialization.
187 // It will be merged later.
132 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key)); 188 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key));
133 if (it == entries_set_.end()) 189 if (it == entries_set_.end())
134 return false; 190 // If not initialized, always return true, forcing it to go to the disk.
191 return !initialized_;
135 it->second.SetLastUsedTime(base::Time::Now()); 192 it->second.SetLastUsedTime(base::Time::Now());
136 return true; 193 return true;
137 } 194 }
138 195
139 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) { 196 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) {
140 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key)); 197 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key));
141 if (it == entries_set_.end()) 198 if (it == entries_set_.end())
142 return false; 199 return false;
143 200
144 // Update the total cache size with the new entry size. 201 // Update the total cache size with the new entry size.
145 cache_size_ -= it->second.entry_size; 202 cache_size_ -= it->second.entry_size;
146 cache_size_ += entry_size; 203 cache_size_ += entry_size;
147 it->second.entry_size = entry_size; 204 it->second.entry_size = entry_size;
148 205
149 return true; 206 return true;
150 } 207 }
151 208
209 // static
152 void SimpleIndex::InsertInternal( 210 void SimpleIndex::InsertInternal(
gavinp 2013/04/11 09:56:32 Do we really want this? Just call insert maybe?
felipeg 2013/04/11 11:25:45 I want to avoid having this long line through the
211 EntrySet* entry_set,
153 const SimpleIndexFile::EntryMetadata& entry_metadata) { 212 const SimpleIndexFile::EntryMetadata& entry_metadata) {
154 entries_set_.insert(make_pair(entry_metadata.GetHashKey(), entry_metadata)); 213 DCHECK(entry_set);
214 entry_set->insert(make_pair(entry_metadata.GetHashKey(), entry_metadata));
155 } 215 }
156 216
157 bool SimpleIndex::RestoreFromDisk() { 217 // static
218 void SimpleIndex::RestoreFromDisk(
219 const base::FilePath& index_filename,
220 const scoped_refptr<base::TaskRunner>& io_thread,
221 const MergeCallback& merge_callback) {
158 using file_util::FileEnumerator; 222 using file_util::FileEnumerator;
159 LOG(INFO) << "Simple Cache Index is being restored from disk."; 223 LOG(INFO) << "Simple Cache Index is being restored from disk.";
160 CloseIndexFile(); 224
161 file_util::Delete(index_filename_, /* recursive = */ false); 225 file_util::Delete(index_filename, /* recursive = */ false);
162 entries_set_.clear(); 226 scoped_ptr<EntrySet> initializing_set(new EntrySet());
163 227
164 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. 228 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format.
165 COMPILE_ASSERT(kSimpleEntryFileCount == 3, 229 COMPILE_ASSERT(kSimpleEntryFileCount == 3,
166 file_pattern_must_match_file_count); 230 file_pattern_must_match_file_count);
167 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); 231 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]");
168 FileEnumerator enumerator(path_, 232 FileEnumerator enumerator(index_filename.DirName(),
169 false /* recursive */, 233 false /* recursive */,
170 FileEnumerator::FILES, 234 FileEnumerator::FILES,
171 file_pattern); 235 file_pattern);
172
173 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); 236 for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
174 file_path = enumerator.Next()) { 237 file_path = enumerator.Next()) {
175 const base::FilePath::StringType base_name = file_path.BaseName().value(); 238 const base::FilePath::StringType base_name = file_path.BaseName().value();
176 // Converting to std::string is OK since we never use UTF8 wide chars in our 239 // Converting to std::string is OK since we never use UTF8 wide chars in our
177 // file names. 240 // file names.
178 const std::string hash_name(base_name.begin(), base_name.end()); 241 const std::string hash_name(base_name.begin(), base_name.end());
179 const std::string hash_key = hash_name.substr(0, kEntryHashKeySize); 242 const std::string hash_key = hash_name.substr(0, kEntryHashKeySize);
180 243
181 FileEnumerator::FindInfo find_info = {}; 244 FileEnumerator::FindInfo find_info = {};
182 enumerator.GetFindInfo(&find_info); 245 enumerator.GetFindInfo(&find_info);
183 base::Time last_used_time; 246 base::Time last_used_time;
184 #if defined(OS_POSIX) 247 #if defined(OS_POSIX)
185 // For POSIX systems, a last access time is available. However, it's not 248 // For POSIX systems, a last access time is available. However, it's not
186 // guaranteed to be more accurate than mtime. It is no worse though. 249 // guaranteed to be more accurate than mtime. It is no worse though.
187 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); 250 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime);
188 #endif 251 #endif
189 if (last_used_time.is_null()) 252 if (last_used_time.is_null())
190 last_used_time = FileEnumerator::GetLastModifiedTime(find_info); 253 last_used_time = FileEnumerator::GetLastModifiedTime(find_info);
191 254
192 int64 file_size = FileEnumerator::GetFilesize(find_info); 255 int64 file_size = FileEnumerator::GetFilesize(find_info);
193 EntrySet::iterator it = entries_set_.find(hash_key); 256 EntrySet::iterator it = initializing_set->find(hash_key);
194 if (it == entries_set_.end()) { 257 if (it == initializing_set->end()) {
195 InsertInternal(SimpleIndexFile::EntryMetadata( 258 InsertInternal(initializing_set.get(), SimpleIndexFile::EntryMetadata(
196 hash_key, last_used_time, file_size)); 259 hash_key, last_used_time, file_size));
197 } else { 260 } else {
198 // Summing up the total size of the entry through all the *_[0-2] files 261 // Summing up the total size of the entry through all the *_[0-2] files
199 it->second.entry_size += file_size; 262 it->second.entry_size += file_size;
200 } 263 }
201 } 264 }
202 265
203 // TODO(felipeg): Detect unrecoverable problems and return false here. 266 io_thread->PostTask(FROM_HERE,
204 return true; 267 base::Bind(merge_callback,
268 base::Passed(&initializing_set)));
269 }
270
271 void SimpleIndex::MergeInitializingSet(scoped_ptr<EntrySet> initializing_set) {
272 DCHECK(io_thread_checker_.CalledOnValidThread());
273 // First, remove the entries that are in the |removals_set_| from both sets.
274 for (base::hash_set<std::string>::const_iterator it = removals_set_.begin();
275 it != removals_set_.end(); ++it) {
276 entries_set_.erase(*it);
277 initializing_set->erase(*it);
278 }
279
280 // Recalculate the cache size while merging the two sets.
281 cache_size_ = 0;
282 for (EntrySet::const_iterator it = initializing_set->begin();
283 it != initializing_set->end(); ++it) {
284 // If there is already an entry in the current entries_set_, we need to
285 // merge the new data there with the data loaded in the initialization.
286 EntrySet::iterator current_entry = entries_set_.find(it->first);
287 if (current_entry != entries_set_.end()) {
gavinp 2013/04/11 09:56:32 Why handle the case of inserting and merging diffe
felipeg 2013/04/11 11:25:45 Done.
288 // When Merging, existing valid data in the |current_entry| will prevail.
289 SimpleIndexFile::EntryMetadata::Merge(
290 it->second, &(current_entry->second));
291 cache_size_ += current_entry->second.entry_size;
292 } else {
293 InsertInternal(&entries_set_, it->second);
294 cache_size_ += it->second.entry_size;
295 }
296 }
297
298 initialized_ = true;
205 } 299 }
206 300
207 void SimpleIndex::Serialize(std::string* out_buffer) { 301 void SimpleIndex::Serialize(std::string* out_buffer) {
208 DCHECK(out_buffer); 302 DCHECK(out_buffer);
209 SimpleIndexFile::Header header; 303 SimpleIndexFile::Header header;
210 SimpleIndexFile::Footer footer; 304 SimpleIndexFile::Footer footer;
211 305
212 header.initial_magic_number = kSimpleIndexInitialMagicNumber; 306 header.initial_magic_number = kSimpleIndexInitialMagicNumber;
213 header.version = kSimpleVersion; 307 header.version = kSimpleVersion;
214 header.number_of_entries = entries_set_.size(); 308 header.number_of_entries = entries_set_.size();
(...skipping 13 matching lines...) Expand all
228 } 322 }
229 323
230 // Then, CRC. 324 // Then, CRC.
231 footer.crc = crc32(crc32(0, Z_NULL, 0), 325 footer.crc = crc32(crc32(0, Z_NULL, 0),
232 reinterpret_cast<const Bytef*>(out_buffer->data()), 326 reinterpret_cast<const Bytef*>(out_buffer->data()),
233 implicit_cast<uInt>(out_buffer->size())); 327 implicit_cast<uInt>(out_buffer->size()));
234 328
235 out_buffer->append(reinterpret_cast<const char*>(&footer), sizeof(footer)); 329 out_buffer->append(reinterpret_cast<const char*>(&footer), sizeof(footer));
236 } 330 }
237 331
238 void SimpleIndex::Cleanup() { 332 void SimpleIndex::WriteToDisk() {
gavinp 2013/04/11 09:56:32 Can you add a thread checker call on EVERY method?
felipeg 2013/04/11 11:25:45 Done.
gavinp 2013/04/11 11:35:39 Done?
239 scoped_ptr<std::string> buffer(new std::string()); 333 scoped_ptr<std::string> buffer(new std::string());
240 Serialize(buffer.get()); 334 Serialize(buffer.get());
241 cache_thread_->PostTask(FROM_HERE, 335 cache_thread_->PostTask(FROM_HERE, base::Bind(
242 base::Bind(&SimpleIndex::UpdateFile, 336 &SimpleIndex::UpdateFile,
243 index_filename_, 337 index_filename_,
244 path_.AppendASCII("index_temp"), 338 index_filename_.DirName().AppendASCII("index_temp"),
245 base::Passed(&buffer))); 339 base::Passed(&buffer)));
246 } 340 }
247 341
248 SimpleIndex::~SimpleIndex() { 342 SimpleIndex::~SimpleIndex() {
249 CloseIndexFile();
250 }
251
252 bool SimpleIndex::OpenIndexFile() {
253 base::PlatformFileError error;
254 index_file_ = base::CreatePlatformFile(index_filename_,
255 base::PLATFORM_FILE_OPEN_ALWAYS |
256 base::PLATFORM_FILE_READ |
257 base::PLATFORM_FILE_WRITE,
258 NULL,
259 &error);
260 if (error != base::PLATFORM_FILE_OK) {
261 LOG(ERROR) << "Error opening file " << index_filename_.value();
262 return false;
263 }
264 return true;
265 }
266
267 bool SimpleIndex::CloseIndexFile() {
268 return base::ClosePlatformFile(index_file_);
269 } 343 }
270 344
271 // static 345 // static
272 void SimpleIndex::UpdateFile(const base::FilePath& index_filename, 346 void SimpleIndex::UpdateFile(const base::FilePath& index_filename,
273 const base::FilePath& temp_filename, 347 const base::FilePath& temp_filename,
274 scoped_ptr<std::string> buffer) { 348 scoped_ptr<std::string> buffer) {
275 int bytes_written = file_util::WriteFile( 349 int bytes_written = file_util::WriteFile(
276 temp_filename, buffer->data(), buffer->size()); 350 temp_filename, buffer->data(), buffer->size());
277 DCHECK_EQ(bytes_written, implicit_cast<int>(buffer->size())); 351 DCHECK_EQ(bytes_written, implicit_cast<int>(buffer->size()));
278 if (bytes_written != static_cast<int>(buffer->size())) { 352 if (bytes_written != static_cast<int>(buffer->size())) {
279 // TODO(felipeg): Add better error handling. 353 // TODO(felipeg): Add better error handling.
280 LOG(ERROR) << "Could not write Simple Cache index to temporary file: " 354 LOG(ERROR) << "Could not write Simple Cache index to temporary file: "
281 << temp_filename.value(); 355 << temp_filename.value();
282 file_util::Delete(temp_filename, /* recursive = */ false); 356 file_util::Delete(temp_filename, /* recursive = */ false);
283 return; 357 return;
284 } 358 }
285 // Swap temp and index_file. 359 // Swap temp and index_file.
286 bool result = file_util::ReplaceFile(temp_filename, index_filename); 360 bool result = file_util::ReplaceFile(temp_filename, index_filename);
287 DCHECK(result); 361 DCHECK(result);
288 } 362 }
289 363
290 } // namespace disk_cache 364 } // namespace disk_cache
OLDNEW
« net/disk_cache/simple/simple_index.h ('K') | « net/disk_cache/simple/simple_index.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698