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

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: 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 25 matching lines...) Expand all
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 } // namespace 40 } // namespace
41 41
42 namespace disk_cache { 42 namespace disk_cache {
43 43
44 SimpleIndex::SimpleIndex( 44 SimpleIndex::SimpleIndex(
45 const scoped_refptr<base::TaskRunner>& cache_thread, 45 const scoped_refptr<base::TaskRunner>& cache_thread,
46 const scoped_refptr<base::TaskRunner>& io_thread,
46 const base::FilePath& path) 47 const base::FilePath& path)
47 : path_(path), 48 : path_(path),
48 cache_thread_(cache_thread) { 49 cache_size_(0),
49 index_filename_ = path_.AppendASCII("simple-index"); 50 initialized_(false),
51 index_filename_(path_.AppendASCII("simple-index")),
52 cache_thread_(cache_thread),
53 io_thread_(io_thread) { }
gavinp 2013/04/10 10:51:56 I think I'm more used to {} or { } A quick grepfi
felipeg 2013/04/10 14:21:45 Done.
54
55 void SimpleIndex::Initialize() {
56 base::WorkerPool::PostTask(FROM_HERE,
57 base::Bind(&SimpleIndex::LoadFromDisk,
58 base::Unretained(this)),
59 true);
50 } 60 }
51 61
52 bool SimpleIndex::Initialize() { 62 void SimpleIndex::LoadFromDisk() {
gavinp 2013/04/10 10:51:56 Method ordering in the .cc file should match the .
53 if (!OpenIndexFile()) 63 if (!OpenIndexFile())
54 return RestoreFromDisk(); 64 return RestoreFromDisk();
55 uLong incremental_crc = crc32(0L, Z_NULL, 0); 65 uLong incremental_crc = crc32(0L, Z_NULL, 0);
56 int64 index_file_offset = 0; 66 int64 index_file_offset = 0;
57 SimpleIndexFile::Header header; 67 SimpleIndexFile::Header header;
58 if (base::ReadPlatformFile(index_file_, 68 if (base::ReadPlatformFile(index_file_,
59 index_file_offset, 69 index_file_offset,
60 reinterpret_cast<char*>(&header), 70 reinterpret_cast<char*>(&header),
61 sizeof(header)) != sizeof(header)) { 71 sizeof(header)) != sizeof(header)) {
62 return RestoreFromDisk(); 72 return RestoreFromDisk();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 const uint32 crc_read = footer.crc; 106 const uint32 crc_read = footer.crc;
97 const uint32 crc_calculated = incremental_crc; 107 const uint32 crc_calculated = incremental_crc;
98 if (crc_read != crc_calculated) 108 if (crc_read != crc_calculated)
99 return RestoreFromDisk(); 109 return RestoreFromDisk();
100 110
101 int entries_buffer_offset = 0; 111 int entries_buffer_offset = 0;
102 while(entries_buffer_offset < entries_buffer_size) { 112 while(entries_buffer_offset < entries_buffer_size) {
103 SimpleIndexFile::EntryMetadata entry_metadata; 113 SimpleIndexFile::EntryMetadata entry_metadata;
104 SimpleIndexFile::EntryMetadata::DeSerialize( 114 SimpleIndexFile::EntryMetadata::DeSerialize(
105 &entries_buffer.get()[entries_buffer_offset], &entry_metadata); 115 &entries_buffer.get()[entries_buffer_offset], &entry_metadata);
106 InsertInternal(entry_metadata); 116 InsertInternal(&initializing_set_, entry_metadata);
107 entries_buffer_offset += SimpleIndexFile::kEntryMetadataSize; 117 entries_buffer_offset += SimpleIndexFile::kEntryMetadataSize;
108 } 118 }
109 DCHECK_EQ(header.number_of_entries, entries_set_.size()); 119 DCHECK_EQ(header.number_of_entries, initializing_set_.size());
110 CloseIndexFile(); 120 CloseIndexFile();
111 return true; 121
122 io_thread_->PostTask(FROM_HERE,
123 base::Bind(&SimpleIndex::MergeInitializingSet,
124 base::Unretained(this)));
112 } 125 }
113 126
114 void SimpleIndex::Insert(const std::string& key) { 127 void SimpleIndex::Insert(const std::string& key) {
115 // Upon insert we don't know yet the size of the entry. 128 // Upon insert we don't know yet the size of the entry.
116 // It will be updated later when the SynchronousEntryImpl finish and the 129 // It will be updated later when the SynchronousEntryImpl finish and the
117 // UpdateEntrySize will be called. 130 // UpdateEntrySize will be called.
118 InsertInternal(SimpleIndexFile::EntryMetadata(GetEntryHashForKey(key), 131 const std::string hash_key = GetEntryHashForKey(key);
132 InsertInternal(&entries_set_, SimpleIndexFile::EntryMetadata(hash_key,
119 base::Time::Now(), 0)); 133 base::Time::Now(), 0));
gavinp 2013/04/10 10:51:56 indent.
felipeg 2013/04/10 14:21:45 Done.
134 if (!initialized_)
135 removals_set_.erase(hash_key);
120 } 136 }
121 137
122 void SimpleIndex::Remove(const std::string& key) { 138 void SimpleIndex::Remove(const std::string& key) {
123 UpdateEntrySize(key, 0); 139 UpdateEntrySize(key, 0);
124 entries_set_.erase(GetEntryHashForKey(key)); 140 const std::string hash_key = GetEntryHashForKey(key);
141 entries_set_.erase(hash_key);
142
143 if (!initialized_)
144 removals_set_.insert(hash_key);
125 } 145 }
126 146
127 bool SimpleIndex::Has(const std::string& key) const { 147 bool SimpleIndex::Has(const std::string& key) const {
128 return entries_set_.count(GetEntryHashForKey(key)) != 0; 148 // If not initialized, always return true, forcing it to go to the disk.
149 return !initialized_ || entries_set_.count(GetEntryHashForKey(key)) != 0;
129 } 150 }
130 151
131 bool SimpleIndex::UseIfExists(const std::string& key) { 152 bool SimpleIndex::UseIfExists(const std::string& key) {
153 // Always update the last used time, even if it is during initialization.
154 // It will be merged later.
132 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key)); 155 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key));
133 if (it == entries_set_.end()) 156 if (it == entries_set_.end())
134 return false; 157 // If not initialized, always return true, forcing it to go to the disk.
158 return !initialized_;
135 it->second.SetLastUsedTime(base::Time::Now()); 159 it->second.SetLastUsedTime(base::Time::Now());
136 return true; 160 return true;
137 } 161 }
138 162
139 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) { 163 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) {
140 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key)); 164 EntrySet::iterator it = entries_set_.find(GetEntryHashForKey(key));
141 if (it == entries_set_.end()) 165 if (it == entries_set_.end())
142 return false; 166 return false;
143 167
144 // Update the total cache size with the new entry size. 168 // Update the total cache size with the new entry size.
145 cache_size_ -= it->second.entry_size; 169 cache_size_ -= it->second.entry_size;
146 cache_size_ += entry_size; 170 cache_size_ += entry_size;
147 it->second.entry_size = entry_size; 171 it->second.entry_size = entry_size;
148 172
149 return true; 173 return true;
150 } 174 }
151 175
176 // static
152 void SimpleIndex::InsertInternal( 177 void SimpleIndex::InsertInternal(
178 EntrySet* entry_set,
153 const SimpleIndexFile::EntryMetadata& entry_metadata) { 179 const SimpleIndexFile::EntryMetadata& entry_metadata) {
154 entries_set_.insert(make_pair(entry_metadata.GetHashKey(), entry_metadata)); 180 DCHECK(entry_set);
181 entry_set->insert(make_pair(entry_metadata.GetHashKey(), entry_metadata));
155 } 182 }
156 183
157 bool SimpleIndex::RestoreFromDisk() { 184 void SimpleIndex::RestoreFromDisk() {
158 using file_util::FileEnumerator; 185 using file_util::FileEnumerator;
159 LOG(INFO) << "Simple Cache Index is being restored from disk."; 186 LOG(INFO) << "Simple Cache Index is being restored from disk.";
160 CloseIndexFile(); 187 CloseIndexFile();
161 file_util::Delete(index_filename_, /* recursive = */ false); 188 file_util::Delete(index_filename_, /* recursive = */ false);
162 entries_set_.clear(); 189 DCHECK_EQ(0U, initializing_set_.size());
190
163 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); 191 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]");
164 FileEnumerator enumerator(path_, 192 FileEnumerator enumerator(path_,
165 false /* recursive */, 193 false /* recursive */,
166 FileEnumerator::FILES, 194 FileEnumerator::FILES,
167 file_pattern); 195 file_pattern);
168 196
169 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); 197 for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
170 file_path = enumerator.Next()) { 198 file_path = enumerator.Next()) {
171 const base::FilePath::StringType base_name = file_path.BaseName().value(); 199 const base::FilePath::StringType base_name = file_path.BaseName().value();
172 // Converting to std::string is OK since we never use UTF8 wide chars in our 200 // Converting to std::string is OK since we never use UTF8 wide chars in our
173 // file names. 201 // file names.
174 const std::string hash_name(base_name.begin(), base_name.end()); 202 const std::string hash_name(base_name.begin(), base_name.end());
175 const std::string hash_key = hash_name.substr(0, kEntryHashKeySize); 203 const std::string hash_key = hash_name.substr(0, kEntryHashKeySize);
176 204
177 FileEnumerator::FindInfo find_info = {}; 205 FileEnumerator::FindInfo find_info = {};
178 enumerator.GetFindInfo(&find_info); 206 enumerator.GetFindInfo(&find_info);
179 base::Time last_used_time; 207 base::Time last_used_time;
180 #if defined(OS_POSIX) 208 #if defined(OS_POSIX)
181 // For POSIX systems, a last access time is available. However, it's not 209 // For POSIX systems, a last access time is available. However, it's not
182 // guaranteed to be more accurate than mtime. It is no worse though. 210 // guaranteed to be more accurate than mtime. It is no worse though.
183 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); 211 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime);
184 #endif 212 #endif
185 if (last_used_time.is_null()) 213 if (last_used_time.is_null())
186 last_used_time = FileEnumerator::GetLastModifiedTime(find_info); 214 last_used_time = FileEnumerator::GetLastModifiedTime(find_info);
187 215
188 int64 file_size = FileEnumerator::GetFilesize(find_info); 216 int64 file_size = FileEnumerator::GetFilesize(find_info);
189 EntrySet::iterator it = entries_set_.find(hash_key); 217 EntrySet::iterator it = initializing_set_.find(hash_key);
190 if (it == entries_set_.end()) { 218 if (it == initializing_set_.end()) {
191 InsertInternal(SimpleIndexFile::EntryMetadata( 219 InsertInternal(&initializing_set_, SimpleIndexFile::EntryMetadata(
192 hash_key, last_used_time, file_size)); 220 hash_key, last_used_time, file_size));
193 } else { 221 } else {
194 // Summing up the total size of the entry through all the *_[0-2] files 222 // Summing up the total size of the entry through all the *_[0-2] files
195 it->second.entry_size += file_size; 223 it->second.entry_size += file_size;
196 } 224 }
197 } 225 }
198 226
199 // TODO(felipeg): Detect unrecoverable problems and return false here. 227 io_thread_->PostTask(FROM_HERE,
200 return true; 228 base::Bind(&SimpleIndex::MergeInitializingSet,
229 base::Unretained(this)));
230 }
231
232 void SimpleIndex::MergeInitializingSet() {
233 // First, remove the entries that are in the |removals_set_| from both sets.
234 for (base::hash_set<std::string>::const_iterator it = removals_set_.begin();
235 it != removals_set_.end(); ++it) {
236 entries_set_.erase(*it);
237 initializing_set_.erase(*it);
238 }
239
240 // Recalculate the cache size while merging the two sets.
241 cache_size_ = 0;
242 for (EntrySet::const_iterator it = initializing_set_.begin();
243 it != initializing_set_.end(); ++it) {
244 // If there is already an entry in the current entries_set_, we need to
245 // merge the new data there with the data loaded in the initialization.
246 EntrySet::iterator current_entry = entries_set_.find(it->first);
247 if (current_entry != entries_set_.end()) {
248 // When Merging, existing valid data in the |current_entry| will prevail.
249 SimpleIndexFile::EntryMetadata::Merge(
250 it->second, &(current_entry->second));
251 cache_size_ += current_entry->second.entry_size;
252 } else {
253 InsertInternal(&entries_set_, it->second);
254 cache_size_ += it->second.entry_size;
255 }
256 }
257 initializing_set_.clear();
258
259 initialized_ = true;
201 } 260 }
202 261
203 void SimpleIndex::Serialize(std::string* out_buffer) { 262 void SimpleIndex::Serialize(std::string* out_buffer) {
204 DCHECK(out_buffer); 263 DCHECK(out_buffer);
205 SimpleIndexFile::Header header; 264 SimpleIndexFile::Header header;
206 SimpleIndexFile::Footer footer; 265 SimpleIndexFile::Footer footer;
207 266
208 header.initial_magic_number = kSimpleIndexInitialMagicNumber; 267 header.initial_magic_number = kSimpleIndexInitialMagicNumber;
209 header.version = kSimpleVersion; 268 header.version = kSimpleVersion;
210 header.number_of_entries = entries_set_.size(); 269 header.number_of_entries = entries_set_.size();
(...skipping 13 matching lines...) Expand all
224 } 283 }
225 284
226 // Then, CRC. 285 // Then, CRC.
227 footer.crc = crc32(crc32(0, Z_NULL, 0), 286 footer.crc = crc32(crc32(0, Z_NULL, 0),
228 reinterpret_cast<const Bytef*>(out_buffer->data()), 287 reinterpret_cast<const Bytef*>(out_buffer->data()),
229 implicit_cast<uInt>(out_buffer->size())); 288 implicit_cast<uInt>(out_buffer->size()));
230 289
231 out_buffer->append(reinterpret_cast<const char*>(&footer), sizeof(footer)); 290 out_buffer->append(reinterpret_cast<const char*>(&footer), sizeof(footer));
232 } 291 }
233 292
234 void SimpleIndex::Cleanup() { 293 void SimpleIndex::WriteToDisk() {
235 scoped_ptr<std::string> buffer(new std::string()); 294 scoped_ptr<std::string> buffer(new std::string());
236 Serialize(buffer.get()); 295 Serialize(buffer.get());
237 cache_thread_->PostTask(FROM_HERE, 296 cache_thread_->PostTask(FROM_HERE,
238 base::Bind(&SimpleIndex::UpdateFile, 297 base::Bind(&SimpleIndex::UpdateFile,
239 index_filename_, 298 index_filename_,
240 path_.AppendASCII("index_temp"), 299 path_.AppendASCII("index_temp"),
241 base::Passed(&buffer))); 300 base::Passed(&buffer)));
242 } 301 }
243 302
244 SimpleIndex::~SimpleIndex() { 303 SimpleIndex::~SimpleIndex() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 << temp_filename.value(); 336 << temp_filename.value();
278 file_util::Delete(temp_filename, /* recursive = */ false); 337 file_util::Delete(temp_filename, /* recursive = */ false);
279 return; 338 return;
280 } 339 }
281 // Swap temp and index_file. 340 // Swap temp and index_file.
282 bool result = file_util::ReplaceFile(temp_filename, index_filename); 341 bool result = file_util::ReplaceFile(temp_filename, index_filename);
283 DCHECK(result); 342 DCHECK(result);
284 } 343 }
285 344
286 } // namespace disk_cache 345 } // 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