OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/chromeos/drive/file_cache.h" | 5 #include "chrome/browser/chromeos/drive/file_cache.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 AssertOnSequencedWorkerPool(); | 75 AssertOnSequencedWorkerPool(); |
76 | 76 |
77 // Do nothing and return if we have enough space. | 77 // Do nothing and return if we have enough space. |
78 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_)) | 78 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_)) |
79 return true; | 79 return true; |
80 | 80 |
81 // Otherwise, try to free up the disk space. | 81 // Otherwise, try to free up the disk space. |
82 DVLOG(1) << "Freeing up disk space for " << num_bytes; | 82 DVLOG(1) << "Freeing up disk space for " << num_bytes; |
83 | 83 |
84 // Remove all entries unless specially marked. | 84 // Remove all entries unless specially marked. |
85 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = | 85 scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator(); |
86 storage_->GetCacheEntryIterator(); | |
87 for (; !it->IsAtEnd(); it->Advance()) { | 86 for (; !it->IsAtEnd(); it->Advance()) { |
88 const FileCacheEntry& entry = it->GetValue(); | 87 if (it->GetValue().file_specific_info().has_cache_state() && |
89 if (!entry.is_pinned() && | 88 !it->GetValue().file_specific_info().cache_state().is_pinned() && |
90 !entry.is_dirty() && | 89 !it->GetValue().file_specific_info().cache_state().is_dirty() && |
91 !mounted_files_.count(it->GetID())) | 90 !mounted_files_.count(it->GetID())) { |
92 storage_->RemoveCacheEntry(it->GetID()); | 91 ResourceEntry entry(it->GetValue()); |
| 92 entry.mutable_file_specific_info()->clear_cache_state(); |
| 93 storage_->PutEntry(entry); |
| 94 } |
93 } | 95 } |
94 if (it->HasError()) | 96 if (it->HasError()) |
95 return false; | 97 return false; |
96 | 98 |
97 // Remove all files which have no corresponding cache entries. | 99 // Remove all files which have no corresponding cache entries. |
98 base::FileEnumerator enumerator(cache_file_directory_, | 100 base::FileEnumerator enumerator(cache_file_directory_, |
99 false, // not recursive | 101 false, // not recursive |
100 base::FileEnumerator::FILES); | 102 base::FileEnumerator::FILES); |
101 FileCacheEntry entry; | 103 ResourceEntry entry; |
102 for (base::FilePath current = enumerator.Next(); !current.empty(); | 104 for (base::FilePath current = enumerator.Next(); !current.empty(); |
103 current = enumerator.Next()) { | 105 current = enumerator.Next()) { |
104 std::string id = GetIdFromPath(current); | 106 std::string id = GetIdFromPath(current); |
105 FileError error = storage_->GetCacheEntry(id, &entry); | 107 FileError error = storage_->GetEntry(id, &entry); |
106 if (error == FILE_ERROR_NOT_FOUND) | 108 if (error == FILE_ERROR_NOT_FOUND || |
| 109 (error == FILE_ERROR_OK && |
| 110 !entry.file_specific_info().cache_state().is_present())) |
107 base::DeleteFile(current, false /* recursive */); | 111 base::DeleteFile(current, false /* recursive */); |
108 else if (error != FILE_ERROR_OK) | 112 else if (error != FILE_ERROR_OK) |
109 return false; | 113 return false; |
110 } | 114 } |
111 | 115 |
112 // Check the disk space again. | 116 // Check the disk space again. |
113 return HasEnoughSpaceFor(num_bytes, cache_file_directory_); | 117 return HasEnoughSpaceFor(num_bytes, cache_file_directory_); |
114 } | 118 } |
115 | 119 |
116 FileError FileCache::GetFile(const std::string& id, | 120 FileError FileCache::GetFile(const std::string& id, |
117 base::FilePath* cache_file_path) { | 121 base::FilePath* cache_file_path) { |
118 AssertOnSequencedWorkerPool(); | 122 AssertOnSequencedWorkerPool(); |
119 DCHECK(cache_file_path); | 123 DCHECK(cache_file_path); |
120 | 124 |
121 FileCacheEntry cache_entry; | 125 ResourceEntry entry; |
122 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 126 FileError error = storage_->GetEntry(id, &entry); |
123 if (error != FILE_ERROR_OK) | 127 if (error != FILE_ERROR_OK) |
124 return error; | 128 return error; |
125 if (!cache_entry.is_present()) | 129 if (!entry.file_specific_info().cache_state().is_present()) |
126 return FILE_ERROR_NOT_FOUND; | 130 return FILE_ERROR_NOT_FOUND; |
127 | 131 |
128 *cache_file_path = GetCacheFilePath(id); | 132 *cache_file_path = GetCacheFilePath(id); |
129 return FILE_ERROR_OK; | 133 return FILE_ERROR_OK; |
130 } | 134 } |
131 | 135 |
132 FileError FileCache::Store(const std::string& id, | 136 FileError FileCache::Store(const std::string& id, |
133 const std::string& md5, | 137 const std::string& md5, |
134 const base::FilePath& source_path, | 138 const base::FilePath& source_path, |
135 FileOperationType file_operation_type) { | 139 FileOperationType file_operation_type) { |
136 AssertOnSequencedWorkerPool(); | 140 AssertOnSequencedWorkerPool(); |
137 | 141 |
| 142 ResourceEntry entry; |
| 143 FileError error = storage_->GetEntry(id, &entry); |
| 144 if (error != FILE_ERROR_OK) |
| 145 return error; |
| 146 |
138 int64 file_size = 0; | 147 int64 file_size = 0; |
139 if (file_operation_type == FILE_OPERATION_COPY) { | 148 if (file_operation_type == FILE_OPERATION_COPY) { |
140 if (!base::GetFileSize(source_path, &file_size)) { | 149 if (!base::GetFileSize(source_path, &file_size)) { |
141 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); | 150 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); |
142 return FILE_ERROR_FAILED; | 151 return FILE_ERROR_FAILED; |
143 } | 152 } |
144 } | 153 } |
145 if (!FreeDiskSpaceIfNeededFor(file_size)) | 154 if (!FreeDiskSpaceIfNeededFor(file_size)) |
146 return FILE_ERROR_NO_LOCAL_SPACE; | 155 return FILE_ERROR_NO_LOCAL_SPACE; |
147 | 156 |
(...skipping 16 matching lines...) Expand all Loading... |
164 | 173 |
165 if (!success) { | 174 if (!success) { |
166 LOG(ERROR) << "Failed to store: " | 175 LOG(ERROR) << "Failed to store: " |
167 << "source_path = " << source_path.value() << ", " | 176 << "source_path = " << source_path.value() << ", " |
168 << "dest_path = " << dest_path.value() << ", " | 177 << "dest_path = " << dest_path.value() << ", " |
169 << "file_operation_type = " << file_operation_type; | 178 << "file_operation_type = " << file_operation_type; |
170 return FILE_ERROR_FAILED; | 179 return FILE_ERROR_FAILED; |
171 } | 180 } |
172 | 181 |
173 // Now that file operations have completed, update metadata. | 182 // Now that file operations have completed, update metadata. |
174 FileCacheEntry cache_entry; | 183 FileCacheEntry* cache_state = |
175 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 184 entry.mutable_file_specific_info()->mutable_cache_state(); |
176 if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND) | 185 cache_state->set_md5(md5); |
177 return error; | 186 cache_state->set_is_present(true); |
178 cache_entry.set_md5(md5); | |
179 cache_entry.set_is_present(true); | |
180 if (md5.empty()) | 187 if (md5.empty()) |
181 cache_entry.set_is_dirty(true); | 188 cache_state->set_is_dirty(true); |
182 return storage_->PutCacheEntry(id, cache_entry); | 189 return storage_->PutEntry(entry); |
183 } | 190 } |
184 | 191 |
185 FileError FileCache::Pin(const std::string& id) { | 192 FileError FileCache::Pin(const std::string& id) { |
186 AssertOnSequencedWorkerPool(); | 193 AssertOnSequencedWorkerPool(); |
187 | 194 |
188 FileCacheEntry cache_entry; | 195 ResourceEntry entry; |
189 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 196 FileError error = storage_->GetEntry(id, &entry); |
190 if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND) | 197 if (error != FILE_ERROR_OK) |
191 return error; | 198 return error; |
192 cache_entry.set_is_pinned(true); | 199 entry.mutable_file_specific_info()->mutable_cache_state()->set_is_pinned( |
193 return storage_->PutCacheEntry(id, cache_entry); | 200 true); |
| 201 return storage_->PutEntry(entry); |
194 } | 202 } |
195 | 203 |
196 FileError FileCache::Unpin(const std::string& id) { | 204 FileError FileCache::Unpin(const std::string& id) { |
197 AssertOnSequencedWorkerPool(); | 205 AssertOnSequencedWorkerPool(); |
198 | 206 |
199 // Unpinning a file means its entry must exist in cache. | 207 // Unpinning a file means its entry must exist in cache. |
200 FileCacheEntry cache_entry; | 208 ResourceEntry entry; |
201 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 209 FileError error = storage_->GetEntry(id, &entry); |
202 if (error != FILE_ERROR_OK) | 210 if (error != FILE_ERROR_OK) |
203 return error; | 211 return error; |
204 | 212 |
205 // Now that file operations have completed, update metadata. | 213 // Now that file operations have completed, update metadata. |
206 if (cache_entry.is_present()) { | 214 if (entry.file_specific_info().cache_state().is_present()) { |
207 cache_entry.set_is_pinned(false); | 215 entry.mutable_file_specific_info()->mutable_cache_state()->set_is_pinned( |
208 error = storage_->PutCacheEntry(id, cache_entry); | 216 false); |
209 if (error != FILE_ERROR_OK) | |
210 return error; | |
211 } else { | 217 } else { |
212 // Remove the existing entry if we are unpinning a non-present file. | 218 // Remove the existing entry if we are unpinning a non-present file. |
213 error = storage_->RemoveCacheEntry(id); | 219 entry.mutable_file_specific_info()->clear_cache_state(); |
214 if (error != FILE_ERROR_OK) | |
215 return error; | |
216 } | 220 } |
| 221 error = storage_->PutEntry(entry); |
| 222 if (error != FILE_ERROR_OK) |
| 223 return error; |
217 | 224 |
218 // Now it's a chance to free up space if needed. | 225 // Now it's a chance to free up space if needed. |
219 FreeDiskSpaceIfNeededFor(0); | 226 FreeDiskSpaceIfNeededFor(0); |
220 | 227 |
221 return FILE_ERROR_OK; | 228 return FILE_ERROR_OK; |
222 } | 229 } |
223 | 230 |
224 FileError FileCache::MarkAsMounted(const std::string& id, | 231 FileError FileCache::MarkAsMounted(const std::string& id, |
225 base::FilePath* cache_file_path) { | 232 base::FilePath* cache_file_path) { |
226 AssertOnSequencedWorkerPool(); | 233 AssertOnSequencedWorkerPool(); |
227 DCHECK(cache_file_path); | 234 DCHECK(cache_file_path); |
228 | 235 |
229 // Get cache entry associated with the id and md5 | 236 // Get cache entry associated with the id and md5 |
230 FileCacheEntry cache_entry; | 237 ResourceEntry entry; |
231 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 238 FileError error = storage_->GetEntry(id, &entry); |
232 if (error != FILE_ERROR_OK) | 239 if (error != FILE_ERROR_OK) |
233 return error; | 240 return error; |
| 241 if (!entry.file_specific_info().cache_state().is_present()) |
| 242 return FILE_ERROR_NOT_FOUND; |
234 | 243 |
235 if (mounted_files_.count(id)) | 244 if (mounted_files_.count(id)) |
236 return FILE_ERROR_INVALID_OPERATION; | 245 return FILE_ERROR_INVALID_OPERATION; |
237 | 246 |
238 // Ensure the file is readable to cros_disks. See crbug.com/236994. | 247 // Ensure the file is readable to cros_disks. See crbug.com/236994. |
239 base::FilePath path = GetCacheFilePath(id); | 248 base::FilePath path = GetCacheFilePath(id); |
240 if (!base::SetPosixFilePermissions( | 249 if (!base::SetPosixFilePermissions( |
241 path, | 250 path, |
242 base::FILE_PERMISSION_READ_BY_USER | | 251 base::FILE_PERMISSION_READ_BY_USER | |
243 base::FILE_PERMISSION_WRITE_BY_USER | | 252 base::FILE_PERMISSION_WRITE_BY_USER | |
244 base::FILE_PERMISSION_READ_BY_GROUP | | 253 base::FILE_PERMISSION_READ_BY_GROUP | |
245 base::FILE_PERMISSION_READ_BY_OTHERS)) | 254 base::FILE_PERMISSION_READ_BY_OTHERS)) |
246 return FILE_ERROR_FAILED; | 255 return FILE_ERROR_FAILED; |
247 | 256 |
248 mounted_files_.insert(id); | 257 mounted_files_.insert(id); |
249 | 258 |
250 *cache_file_path = path; | 259 *cache_file_path = path; |
251 return FILE_ERROR_OK; | 260 return FILE_ERROR_OK; |
252 } | 261 } |
253 | 262 |
254 FileError FileCache::OpenForWrite( | 263 FileError FileCache::OpenForWrite( |
255 const std::string& id, | 264 const std::string& id, |
256 scoped_ptr<base::ScopedClosureRunner>* file_closer) { | 265 scoped_ptr<base::ScopedClosureRunner>* file_closer) { |
257 AssertOnSequencedWorkerPool(); | 266 AssertOnSequencedWorkerPool(); |
258 | 267 |
259 // Marking a file dirty means its entry and actual file blob must exist in | 268 // Marking a file dirty means its entry and actual file blob must exist in |
260 // cache. | 269 // cache. |
261 FileCacheEntry cache_entry; | 270 ResourceEntry entry; |
262 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 271 FileError error = storage_->GetEntry(id, &entry); |
263 if (error != FILE_ERROR_OK) | 272 if (error != FILE_ERROR_OK) |
264 return error; | 273 return error; |
265 if (!cache_entry.is_present()) { | 274 if (!entry.file_specific_info().cache_state().is_present()) { |
266 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id; | 275 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id; |
267 return FILE_ERROR_NOT_FOUND; | 276 return FILE_ERROR_NOT_FOUND; |
268 } | 277 } |
269 | 278 |
270 cache_entry.set_is_dirty(true); | 279 entry.mutable_file_specific_info()->mutable_cache_state()->set_is_dirty(true); |
271 cache_entry.clear_md5(); | 280 entry.mutable_file_specific_info()->mutable_cache_state()->clear_md5(); |
272 error = storage_->PutCacheEntry(id, cache_entry); | 281 error = storage_->PutEntry(entry); |
273 if (error != FILE_ERROR_OK) | 282 if (error != FILE_ERROR_OK) |
274 return error; | 283 return error; |
275 | 284 |
276 write_opened_files_[id]++; | 285 write_opened_files_[id]++; |
277 file_closer->reset(new base::ScopedClosureRunner( | 286 file_closer->reset(new base::ScopedClosureRunner( |
278 base::Bind(&google_apis::RunTaskOnThread, | 287 base::Bind(&google_apis::RunTaskOnThread, |
279 blocking_task_runner_, | 288 blocking_task_runner_, |
280 base::Bind(&FileCache::CloseForWrite, | 289 base::Bind(&FileCache::CloseForWrite, |
281 weak_ptr_factory_.GetWeakPtr(), | 290 weak_ptr_factory_.GetWeakPtr(), |
282 id)))); | 291 id)))); |
283 return FILE_ERROR_OK; | 292 return FILE_ERROR_OK; |
284 } | 293 } |
285 | 294 |
286 bool FileCache::IsOpenedForWrite(const std::string& id) { | 295 bool FileCache::IsOpenedForWrite(const std::string& id) { |
287 AssertOnSequencedWorkerPool(); | 296 AssertOnSequencedWorkerPool(); |
288 return write_opened_files_.count(id); | 297 return write_opened_files_.count(id); |
289 } | 298 } |
290 | 299 |
291 FileError FileCache::UpdateMd5(const std::string& id) { | 300 FileError FileCache::UpdateMd5(const std::string& id) { |
292 AssertOnSequencedWorkerPool(); | 301 AssertOnSequencedWorkerPool(); |
293 | 302 |
294 if (IsOpenedForWrite(id)) | 303 if (IsOpenedForWrite(id)) |
295 return FILE_ERROR_IN_USE; | 304 return FILE_ERROR_IN_USE; |
296 | 305 |
297 FileCacheEntry cache_entry; | 306 ResourceEntry entry; |
298 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 307 FileError error = storage_->GetEntry(id, &entry); |
299 if (error != FILE_ERROR_OK) | 308 if (error != FILE_ERROR_OK) |
300 return error; | 309 return error; |
301 if (!cache_entry.is_present()) | 310 if (!entry.file_specific_info().cache_state().is_present()) |
302 return FILE_ERROR_NOT_FOUND; | 311 return FILE_ERROR_NOT_FOUND; |
303 | 312 |
304 const std::string& md5 = util::GetMd5Digest(GetCacheFilePath(id)); | 313 const std::string& md5 = util::GetMd5Digest(GetCacheFilePath(id)); |
305 if (md5.empty()) | 314 if (md5.empty()) |
306 return FILE_ERROR_NOT_FOUND; | 315 return FILE_ERROR_NOT_FOUND; |
307 | 316 |
308 cache_entry.set_md5(md5); | 317 entry.mutable_file_specific_info()->mutable_cache_state()->set_md5(md5); |
309 return storage_->PutCacheEntry(id, cache_entry); | 318 return storage_->PutEntry(entry); |
310 } | 319 } |
311 | 320 |
312 FileError FileCache::ClearDirty(const std::string& id) { | 321 FileError FileCache::ClearDirty(const std::string& id) { |
313 AssertOnSequencedWorkerPool(); | 322 AssertOnSequencedWorkerPool(); |
314 | 323 |
315 if (IsOpenedForWrite(id)) | 324 if (IsOpenedForWrite(id)) |
316 return FILE_ERROR_IN_USE; | 325 return FILE_ERROR_IN_USE; |
317 | 326 |
318 // Clearing a dirty file means its entry and actual file blob must exist in | 327 // Clearing a dirty file means its entry and actual file blob must exist in |
319 // cache. | 328 // cache. |
320 FileCacheEntry cache_entry; | 329 ResourceEntry entry; |
321 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 330 FileError error = storage_->GetEntry(id, &entry); |
322 if (error != FILE_ERROR_OK) | 331 if (error != FILE_ERROR_OK) |
323 return error; | 332 return error; |
324 if (!cache_entry.is_present()) { | 333 if (!entry.file_specific_info().cache_state().is_present()) { |
325 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " | 334 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " |
326 << id; | 335 << id; |
327 return FILE_ERROR_NOT_FOUND; | 336 return FILE_ERROR_NOT_FOUND; |
328 } | 337 } |
329 | 338 |
330 // If a file is not dirty (it should have been marked dirty via OpenForWrite), | 339 // If a file is not dirty (it should have been marked dirty via OpenForWrite), |
331 // clearing its dirty state is an invalid operation. | 340 // clearing its dirty state is an invalid operation. |
332 if (!cache_entry.is_dirty()) { | 341 if (!entry.file_specific_info().cache_state().is_dirty()) { |
333 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: " << id; | 342 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: " << id; |
334 return FILE_ERROR_INVALID_OPERATION; | 343 return FILE_ERROR_INVALID_OPERATION; |
335 } | 344 } |
336 | 345 |
337 cache_entry.set_is_dirty(false); | 346 entry.mutable_file_specific_info()->mutable_cache_state()->set_is_dirty( |
338 return storage_->PutCacheEntry(id, cache_entry); | 347 false); |
| 348 return storage_->PutEntry(entry); |
339 } | 349 } |
340 | 350 |
341 FileError FileCache::Remove(const std::string& id) { | 351 FileError FileCache::Remove(const std::string& id) { |
342 AssertOnSequencedWorkerPool(); | 352 AssertOnSequencedWorkerPool(); |
343 | 353 |
344 FileCacheEntry cache_entry; | 354 ResourceEntry entry; |
345 | 355 |
346 // If entry doesn't exist, nothing to do. | 356 // If entry doesn't exist, nothing to do. |
347 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 357 FileError error = storage_->GetEntry(id, &entry); |
348 if (error == FILE_ERROR_NOT_FOUND) | 358 if (error == FILE_ERROR_NOT_FOUND) |
349 return FILE_ERROR_OK; | 359 return FILE_ERROR_OK; |
350 if (error != FILE_ERROR_OK) | 360 if (error != FILE_ERROR_OK) |
351 return error; | 361 return error; |
| 362 if (!entry.file_specific_info().has_cache_state()) |
| 363 return FILE_ERROR_OK; |
352 | 364 |
353 // Cannot delete a mounted file. | 365 // Cannot delete a mounted file. |
354 if (mounted_files_.count(id)) | 366 if (mounted_files_.count(id)) |
355 return FILE_ERROR_IN_USE; | 367 return FILE_ERROR_IN_USE; |
356 | 368 |
357 // Delete the file. | 369 // Delete the file. |
358 base::FilePath path = GetCacheFilePath(id); | 370 base::FilePath path = GetCacheFilePath(id); |
359 if (!base::DeleteFile(path, false /* recursive */)) | 371 if (!base::DeleteFile(path, false /* recursive */)) |
360 return FILE_ERROR_FAILED; | 372 return FILE_ERROR_FAILED; |
361 | 373 |
362 // Now that all file operations have completed, remove from metadata. | 374 // Now that all file operations have completed, remove from metadata. |
363 return storage_->RemoveCacheEntry(id); | 375 entry.mutable_file_specific_info()->clear_cache_state(); |
| 376 return storage_->PutEntry(entry); |
364 } | 377 } |
365 | 378 |
366 bool FileCache::ClearAll() { | 379 bool FileCache::ClearAll() { |
367 AssertOnSequencedWorkerPool(); | 380 AssertOnSequencedWorkerPool(); |
368 | 381 |
369 // Remove entries on the metadata. | |
370 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = | |
371 storage_->GetCacheEntryIterator(); | |
372 for (; !it->IsAtEnd(); it->Advance()) { | |
373 if (storage_->RemoveCacheEntry(it->GetID()) != FILE_ERROR_OK) | |
374 return false; | |
375 } | |
376 | |
377 if (it->HasError()) | |
378 return false; | |
379 | |
380 // Remove files. | 382 // Remove files. |
381 base::FileEnumerator enumerator(cache_file_directory_, | 383 base::FileEnumerator enumerator(cache_file_directory_, |
382 false, // not recursive | 384 false, // not recursive |
383 base::FileEnumerator::FILES); | 385 base::FileEnumerator::FILES); |
384 for (base::FilePath file = enumerator.Next(); !file.empty(); | 386 for (base::FilePath file = enumerator.Next(); !file.empty(); |
385 file = enumerator.Next()) | 387 file = enumerator.Next()) |
386 base::DeleteFile(file, false /* recursive */); | 388 base::DeleteFile(file, false /* recursive */); |
387 | 389 |
388 return true; | 390 return true; |
389 } | 391 } |
390 | 392 |
391 bool FileCache::Initialize() { | 393 bool FileCache::Initialize() { |
392 AssertOnSequencedWorkerPool(); | 394 AssertOnSequencedWorkerPool(); |
393 | 395 |
394 // Older versions do not clear MD5 when marking entries dirty. | 396 // Older versions do not clear MD5 when marking entries dirty. |
395 // Clear MD5 of all dirty entries to deal with old data. | 397 // Clear MD5 of all dirty entries to deal with old data. |
396 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = | 398 scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator(); |
397 storage_->GetCacheEntryIterator(); | |
398 for (; !it->IsAtEnd(); it->Advance()) { | 399 for (; !it->IsAtEnd(); it->Advance()) { |
399 if (it->GetValue().is_dirty()) { | 400 if (it->GetValue().file_specific_info().cache_state().is_dirty()) { |
400 FileCacheEntry new_entry(it->GetValue()); | 401 ResourceEntry new_entry(it->GetValue()); |
401 new_entry.clear_md5(); | 402 new_entry.mutable_file_specific_info()->mutable_cache_state()-> |
402 if (storage_->PutCacheEntry(it->GetID(), new_entry) != FILE_ERROR_OK) | 403 clear_md5(); |
| 404 if (storage_->PutEntry(new_entry) != FILE_ERROR_OK) |
403 return false; | 405 return false; |
404 } | 406 } |
405 } | 407 } |
406 if (it->HasError()) | 408 if (it->HasError()) |
407 return false; | 409 return false; |
408 | 410 |
409 if (!RenameCacheFilesToNewFormat()) | 411 if (!RenameCacheFilesToNewFormat()) |
410 return false; | 412 return false; |
411 return true; | 413 return true; |
412 } | 414 } |
(...skipping 19 matching lines...) Expand all Loading... |
432 const ResourceMetadataStorage::RecoveredCacheInfoMap& | 434 const ResourceMetadataStorage::RecoveredCacheInfoMap& |
433 recovered_cache_info) { | 435 recovered_cache_info) { |
434 int file_number = 1; | 436 int file_number = 1; |
435 | 437 |
436 base::FileEnumerator enumerator(cache_file_directory_, | 438 base::FileEnumerator enumerator(cache_file_directory_, |
437 false, // not recursive | 439 false, // not recursive |
438 base::FileEnumerator::FILES); | 440 base::FileEnumerator::FILES); |
439 for (base::FilePath current = enumerator.Next(); !current.empty(); | 441 for (base::FilePath current = enumerator.Next(); !current.empty(); |
440 current = enumerator.Next()) { | 442 current = enumerator.Next()) { |
441 const std::string& id = GetIdFromPath(current); | 443 const std::string& id = GetIdFromPath(current); |
442 FileCacheEntry entry; | 444 ResourceEntry entry; |
443 FileError error = storage_->GetCacheEntry(id, &entry); | 445 FileError error = storage_->GetEntry(id, &entry); |
444 if (error == FILE_ERROR_OK) { | 446 if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND) |
| 447 return false; |
| 448 if (error == FILE_ERROR_OK && |
| 449 entry.file_specific_info().cache_state().is_present()) { |
445 // This file is managed by FileCache, no need to recover it. | 450 // This file is managed by FileCache, no need to recover it. |
446 continue; | 451 continue; |
447 } | 452 } |
448 if (error != FILE_ERROR_NOT_FOUND) | |
449 return false; | |
450 | 453 |
451 // If a cache entry which is non-dirty and has matching MD5 is found in | 454 // If a cache entry which is non-dirty and has matching MD5 is found in |
452 // |recovered_cache_entries|, it means the current file is already uploaded | 455 // |recovered_cache_entries|, it means the current file is already uploaded |
453 // to the server. Just delete it instead of recovering it. | 456 // to the server. Just delete it instead of recovering it. |
454 ResourceMetadataStorage::RecoveredCacheInfoMap::const_iterator it = | 457 ResourceMetadataStorage::RecoveredCacheInfoMap::const_iterator it = |
455 recovered_cache_info.find(id); | 458 recovered_cache_info.find(id); |
456 if (it != recovered_cache_info.end()) { | 459 if (it != recovered_cache_info.end()) { |
457 // Due to the DB corruption, cache info might be recovered from old | 460 // Due to the DB corruption, cache info might be recovered from old |
458 // revision. Perform MD5 check even when is_dirty is false just in case. | 461 // revision. Perform MD5 check even when is_dirty is false just in case. |
459 if (!it->second.is_dirty && | 462 if (!it->second.is_dirty && |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 file_number - 1); | 525 file_number - 1); |
523 return true; | 526 return true; |
524 } | 527 } |
525 | 528 |
526 FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) { | 529 FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) { |
527 AssertOnSequencedWorkerPool(); | 530 AssertOnSequencedWorkerPool(); |
528 DCHECK(IsUnderFileCacheDirectory(file_path)); | 531 DCHECK(IsUnderFileCacheDirectory(file_path)); |
529 | 532 |
530 std::string id = GetIdFromPath(file_path); | 533 std::string id = GetIdFromPath(file_path); |
531 | 534 |
532 // Get cache entry associated with the id and md5 | 535 // Get the entry associated with the id. |
533 FileCacheEntry cache_entry; | 536 ResourceEntry entry; |
534 FileError error = storage_->GetCacheEntry(id, &cache_entry); | 537 FileError error = storage_->GetEntry(id, &entry); |
535 if (error != FILE_ERROR_OK) | 538 if (error != FILE_ERROR_OK) |
536 return error; | 539 return error; |
537 | 540 |
538 std::set<std::string>::iterator it = mounted_files_.find(id); | 541 std::set<std::string>::iterator it = mounted_files_.find(id); |
539 if (it == mounted_files_.end()) | 542 if (it == mounted_files_.end()) |
540 return FILE_ERROR_INVALID_OPERATION; | 543 return FILE_ERROR_INVALID_OPERATION; |
541 | 544 |
542 mounted_files_.erase(it); | 545 mounted_files_.erase(it); |
543 return FILE_ERROR_OK; | 546 return FILE_ERROR_OK; |
544 } | 547 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 return; | 588 return; |
586 | 589 |
587 DCHECK_LT(0, it->second); | 590 DCHECK_LT(0, it->second); |
588 --it->second; | 591 --it->second; |
589 if (it->second == 0) | 592 if (it->second == 0) |
590 write_opened_files_.erase(it); | 593 write_opened_files_.erase(it); |
591 } | 594 } |
592 | 595 |
593 } // namespace internal | 596 } // namespace internal |
594 } // namespace drive | 597 } // namespace drive |
OLD | NEW |