Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "chrome/browser/sync_file_system/local/local_file_change_tracker.h" | 5 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 | 8 |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 num_changes_(0) { | 83 num_changes_(0) { |
| 84 } | 84 } |
| 85 | 85 |
| 86 LocalFileChangeTracker::~LocalFileChangeTracker() { | 86 LocalFileChangeTracker::~LocalFileChangeTracker() { |
| 87 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 87 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 88 tracker_db_.reset(); | 88 tracker_db_.reset(); |
| 89 } | 89 } |
| 90 | 90 |
| 91 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) { | 91 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) { |
| 92 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 92 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 93 if (ContainsKey(changes_, url)) | 93 if (ContainsKey(changes_, url) || ContainsKey(demoted_changes_, url)) |
| 94 return; | 94 return; |
| 95 // TODO(nhiroki): propagate the error code (see http://crbug.com/152127). | 95 // TODO(nhiroki): propagate the error code (see http://crbug.com/152127). |
| 96 MarkDirtyOnDatabase(url); | 96 MarkDirtyOnDatabase(url); |
| 97 } | 97 } |
| 98 | 98 |
| 99 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) {} | 99 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) {} |
| 100 | 100 |
| 101 void LocalFileChangeTracker::OnCreateFile(const FileSystemURL& url) { | 101 void LocalFileChangeTracker::OnCreateFile(const FileSystemURL& url) { |
| 102 RecordChange(url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, | 102 RecordChange(url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
| 103 SYNC_FILE_TYPE_FILE)); | 103 SYNC_FILE_TYPE_FILE)); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 179 } | 179 } |
| 180 | 180 |
| 181 void LocalFileChangeTracker::RemoveMirrorAndCommitChangesForURL( | 181 void LocalFileChangeTracker::RemoveMirrorAndCommitChangesForURL( |
| 182 const fileapi::FileSystemURL& url) { | 182 const fileapi::FileSystemURL& url) { |
| 183 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 183 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 184 FileChangeMap::iterator found = mirror_changes_.find(url); | 184 FileChangeMap::iterator found = mirror_changes_.find(url); |
| 185 if (found == mirror_changes_.end()) | 185 if (found == mirror_changes_.end()) |
| 186 return; | 186 return; |
| 187 mirror_changes_.erase(found); | 187 mirror_changes_.erase(found); |
| 188 | 188 |
| 189 if (ContainsKey(changes_, url)) | 189 if (ContainsKey(changes_, url) || ContainsKey(demoted_changes_, url)) |
| 190 MarkDirtyOnDatabase(url); | 190 MarkDirtyOnDatabase(url); |
| 191 else | 191 else |
| 192 ClearDirtyOnDatabase(url); | 192 ClearDirtyOnDatabase(url); |
| 193 UpdateNumChanges(); | 193 UpdateNumChanges(); |
| 194 } | 194 } |
| 195 | 195 |
| 196 void LocalFileChangeTracker::ResetToMirrorAndCommitChangesForURL( | 196 void LocalFileChangeTracker::ResetToMirrorAndCommitChangesForURL( |
| 197 const fileapi::FileSystemURL& url) { | 197 const fileapi::FileSystemURL& url) { |
| 198 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 198 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 199 FileChangeMap::iterator found = mirror_changes_.find(url); | 199 FileChangeMap::iterator found = mirror_changes_.find(url); |
| 200 if (found == mirror_changes_.end() || found->second.change_list.empty()) { | 200 if (found == mirror_changes_.end() || found->second.change_list.empty()) { |
| 201 ClearChangesForURL(url); | 201 ClearChangesForURL(url); |
| 202 return; | 202 return; |
| 203 } | 203 } |
| 204 const ChangeInfo& info = found->second; | 204 const ChangeInfo& info = found->second; |
| 205 change_seqs_[info.change_seq] = url; | 205 if (ContainsKey(demoted_changes_, url)) { |
| 206 changes_[url] = info; | 206 demoted_changes_[url] = info; |
| 207 } else { | |
| 208 change_seqs_[info.change_seq] = url; | |
| 209 changes_[url] = info; | |
| 210 } | |
| 207 RemoveMirrorAndCommitChangesForURL(url); | 211 RemoveMirrorAndCommitChangesForURL(url); |
| 208 } | 212 } |
| 209 | 213 |
| 210 void LocalFileChangeTracker::DemoteChangesForURL( | 214 void LocalFileChangeTracker::DemoteChangesForURL( |
| 211 const fileapi::FileSystemURL& url) { | 215 const fileapi::FileSystemURL& url) { |
| 212 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 216 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 217 | |
| 213 FileChangeMap::iterator found = changes_.find(url); | 218 FileChangeMap::iterator found = changes_.find(url); |
| 214 if (found == changes_.end()) | 219 if (found == changes_.end()) |
| 215 return; | 220 return; |
| 216 FileChangeList changes = found->second.change_list; | 221 DCHECK(!ContainsKey(demoted_changes_, url)); |
| 217 | |
| 218 mirror_changes_.erase(url); | |
| 219 change_seqs_.erase(found->second.change_seq); | 222 change_seqs_.erase(found->second.change_seq); |
| 223 demoted_changes_.insert(*found); | |
| 220 changes_.erase(found); | 224 changes_.erase(found); |
| 221 | 225 UpdateNumChanges(); |
| 222 FileChangeList::List change_list = changes.list(); | |
| 223 while (!change_list.empty()) { | |
| 224 RecordChangeToChangeMaps(url, change_list.front(), 0, | |
| 225 &demoted_changes_, NULL); | |
| 226 change_list.pop_front(); | |
| 227 } | |
| 228 } | 226 } |
| 229 | 227 |
| 230 void LocalFileChangeTracker::PromoteDemotedChangesForURL( | 228 void LocalFileChangeTracker::PromoteDemotedChangesForURL( |
| 231 const fileapi::FileSystemURL& url) { | 229 const fileapi::FileSystemURL& url) { |
| 232 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 230 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 233 | 231 |
| 234 FileChangeMap::iterator iter = demoted_changes_.find(url); | 232 FileChangeMap::iterator iter = demoted_changes_.find(url); |
| 235 if (iter == demoted_changes_.end()) | 233 if (iter == demoted_changes_.end()) |
| 236 return; | 234 return; |
| 237 | 235 |
| 238 FileChangeList::List change_list = iter->second.change_list.list(); | 236 FileChangeList::List change_list = iter->second.change_list.list(); |
| 239 // Make sure that this URL is in no queues. | 237 // Make sure that this URL is in no queues. |
| 238 DCHECK(!ContainsKey(change_seqs_, iter->second.change_seq)); | |
| 240 DCHECK(!ContainsKey(changes_, url)); | 239 DCHECK(!ContainsKey(changes_, url)); |
| 241 DCHECK(!ContainsKey(mirror_changes_, url)); | |
| 242 | 240 |
| 241 change_seqs_[iter->second.change_seq] = url; | |
| 242 changes_.insert(*iter); | |
| 243 demoted_changes_.erase(iter); | 243 demoted_changes_.erase(iter); |
| 244 | |
| 245 while (!change_list.empty()) { | |
| 246 RecordChange(url, change_list.front()); | |
| 247 change_list.pop_front(); | |
| 248 } | |
| 249 } | 244 } |
| 250 | 245 |
| 251 bool LocalFileChangeTracker::PromoteDemotedChanges() { | 246 bool LocalFileChangeTracker::PromoteDemotedChanges() { |
| 252 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 247 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 253 if (demoted_changes_.empty()) | 248 if (demoted_changes_.empty()) |
| 254 return false; | 249 return false; |
| 255 while (!demoted_changes_.empty()) { | 250 while (!demoted_changes_.empty()) { |
| 256 fileapi::FileSystemURL url = demoted_changes_.begin()->first; | 251 fileapi::FileSystemURL url = demoted_changes_.begin()->first; |
| 257 PromoteDemotedChangesForURL(url); | 252 PromoteDemotedChangesForURL(url); |
| 258 } | 253 } |
| 254 UpdateNumChanges(); | |
| 259 return true; | 255 return true; |
| 260 } | 256 } |
| 261 | 257 |
| 262 SyncStatusCode LocalFileChangeTracker::Initialize( | 258 SyncStatusCode LocalFileChangeTracker::Initialize( |
| 263 FileSystemContext* file_system_context) { | 259 FileSystemContext* file_system_context) { |
| 264 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 260 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 265 DCHECK(!initialized_); | 261 DCHECK(!initialized_); |
| 266 DCHECK(file_system_context); | 262 DCHECK(file_system_context); |
| 267 | 263 |
| 268 SyncStatusCode status = CollectLastDirtyChanges(file_system_context); | 264 SyncStatusCode status = CollectLastDirtyChanges(file_system_context); |
| 269 if (status == SYNC_STATUS_OK) | 265 if (status == SYNC_STATUS_OK) |
| 270 initialized_ = true; | 266 initialized_ = true; |
| 271 return status; | 267 return status; |
| 272 } | 268 } |
| 273 | 269 |
| 274 void LocalFileChangeTracker::ResetForFileSystem( | 270 void LocalFileChangeTracker::ResetForFileSystem( |
| 275 const GURL& origin, | 271 const GURL& origin, |
| 276 fileapi::FileSystemType type) { | 272 fileapi::FileSystemType type) { |
| 277 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 273 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 278 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 274 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
| 279 for (FileChangeMap::iterator iter = changes_.begin(); | 275 for (FileChangeMap::iterator iter = changes_.begin(); |
| 280 iter != changes_.end();) { | 276 iter != changes_.end();) { |
| 281 fileapi::FileSystemURL url = iter->first; | 277 fileapi::FileSystemURL url = iter->first; |
| 282 if (url.origin() != origin || url.type() != type) { | 278 int change_seq = iter->second.change_seq; |
| 283 ++iter; | 279 // Advance |iter| before calling ResetForURL to avoid the iterator |
| 284 continue; | 280 // invalidation in it. |
| 285 } | 281 ++iter; |
| 286 mirror_changes_.erase(url); | 282 if (url.origin() == origin && url.type() == type) |
| 287 demoted_changes_.erase(url); | 283 ResetForURL(url, change_seq, batch.get()); |
| 288 change_seqs_.erase(iter->second.change_seq); | 284 } |
| 289 changes_.erase(iter++); | |
| 290 | 285 |
| 291 std::string serialized_url; | 286 for (FileChangeMap::iterator iter = demoted_changes_.begin(); |
| 292 const bool should_success = | 287 iter != demoted_changes_.end();) { |
| 293 SerializeSyncableFileSystemURL(url, &serialized_url); | 288 fileapi::FileSystemURL url = iter->first; |
| 294 if (!should_success) { | 289 int change_seq = iter->second.change_seq; |
| 295 NOTREACHED() << "Failed to serialize: " << url.DebugString(); | 290 // Advance |iter| before calling ResetForURL to avoid the iterator |
| 296 continue; | 291 // invalidation in it. |
| 297 } | 292 ++iter; |
| 298 batch->Delete(serialized_url); | 293 if (url.origin() == origin && url.type() == type) |
| 294 ResetForURL(url, change_seq, batch.get()); | |
| 299 } | 295 } |
| 296 | |
| 300 // Fail to apply batch to database wouldn't have critical effect, they'll be | 297 // Fail to apply batch to database wouldn't have critical effect, they'll be |
| 301 // just marked deleted on next relaunch. | 298 // just marked deleted on next relaunch. |
| 302 tracker_db_->WriteBatch(batch.Pass()); | 299 tracker_db_->WriteBatch(batch.Pass()); |
| 303 UpdateNumChanges(); | 300 UpdateNumChanges(); |
| 304 } | 301 } |
| 305 | 302 |
| 306 void LocalFileChangeTracker::UpdateNumChanges() { | 303 void LocalFileChangeTracker::UpdateNumChanges() { |
| 307 base::AutoLock lock(num_changes_lock_); | 304 base::AutoLock lock(num_changes_lock_); |
| 308 num_changes_ = static_cast<int64>(change_seqs_.size()); | 305 num_changes_ = static_cast<int64>(change_seqs_.size()); |
| 309 } | 306 } |
| 310 | 307 |
| 311 void LocalFileChangeTracker::GetAllChangedURLs(FileSystemURLSet* urls) { | 308 void LocalFileChangeTracker::GetAllChangedURLs(FileSystemURLSet* urls) { |
| 312 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 309 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 313 std::deque<FileSystemURL> url_deque; | 310 std::deque<FileSystemURL> url_deque; |
| 314 GetNextChangedURLs(&url_deque, 0); | 311 GetNextChangedURLs(&url_deque, 0); |
| 315 urls->clear(); | 312 urls->clear(); |
| 316 urls->insert(url_deque.begin(), url_deque.end()); | 313 urls->insert(url_deque.begin(), url_deque.end()); |
| 317 } | 314 } |
| 318 | 315 |
| 319 void LocalFileChangeTracker::DropAllChanges() { | 316 void LocalFileChangeTracker::DropAllChanges() { |
| 320 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 317 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 321 changes_.clear(); | 318 changes_.clear(); |
| 322 change_seqs_.clear(); | 319 change_seqs_.clear(); |
| 323 mirror_changes_.clear(); | 320 mirror_changes_.clear(); |
| 321 UpdateNumChanges(); | |
| 324 } | 322 } |
| 325 | 323 |
| 326 SyncStatusCode LocalFileChangeTracker::MarkDirtyOnDatabase( | 324 SyncStatusCode LocalFileChangeTracker::MarkDirtyOnDatabase( |
| 327 const FileSystemURL& url) { | 325 const FileSystemURL& url) { |
| 328 std::string serialized_url; | 326 std::string serialized_url; |
| 329 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) | 327 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) |
| 330 return SYNC_FILE_ERROR_INVALID_URL; | 328 return SYNC_FILE_ERROR_INVALID_URL; |
| 331 | 329 |
| 332 return tracker_db_->MarkDirty(serialized_url); | 330 return tracker_db_->MarkDirty(serialized_url); |
| 333 } | 331 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 LOG(WARNING) << "Failed to access local file."; | 403 LOG(WARNING) << "Failed to access local file."; |
| 406 break; | 404 break; |
| 407 } | 405 } |
| 408 } | 406 } |
| 409 return SYNC_STATUS_OK; | 407 return SYNC_STATUS_OK; |
| 410 } | 408 } |
| 411 | 409 |
| 412 void LocalFileChangeTracker::RecordChange( | 410 void LocalFileChangeTracker::RecordChange( |
| 413 const FileSystemURL& url, const FileChange& change) { | 411 const FileSystemURL& url, const FileChange& change) { |
| 414 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 412 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 413 int change_seq = current_change_seq_++; | |
|
nhiroki
2014/07/23 06:37:13
(Option) Since |current_change_seq_| is confusing
tzik
2014/07/24 15:35:20
Done.
| |
| 415 if (ContainsKey(demoted_changes_, url)) { | 414 if (ContainsKey(demoted_changes_, url)) { |
| 416 RecordChangeToChangeMaps(url, change, 0, &demoted_changes_, NULL); | 415 RecordChangeToChangeMaps(url, change, change_seq, |
| 417 return; | 416 &demoted_changes_, NULL); |
| 417 } else{ | |
|
nhiroki
2014/07/23 06:37:12
nit: please add a space after 'else'.
tzik
2014/07/24 15:35:20
Done.
| |
| 418 RecordChangeToChangeMaps(url, change, change_seq, &changes_, &change_seqs_); | |
| 418 } | 419 } |
| 419 int change_seq = current_change_seq_++; | |
| 420 RecordChangeToChangeMaps(url, change, change_seq, &changes_, &change_seqs_); | |
| 421 if (ContainsKey(mirror_changes_, url)) | 420 if (ContainsKey(mirror_changes_, url)) |
| 422 RecordChangeToChangeMaps(url, change, change_seq, &mirror_changes_, NULL); | 421 RecordChangeToChangeMaps(url, change, change_seq, &mirror_changes_, NULL); |
| 423 UpdateNumChanges(); | 422 UpdateNumChanges(); |
| 424 } | 423 } |
| 425 | 424 |
| 426 // static | 425 // static |
| 427 void LocalFileChangeTracker::RecordChangeToChangeMaps( | 426 void LocalFileChangeTracker::RecordChangeToChangeMaps( |
| 428 const FileSystemURL& url, | 427 const FileSystemURL& url, |
| 429 const FileChange& change, | 428 const FileChange& change, |
| 430 int new_change_seq, | 429 int new_change_seq, |
| 431 FileChangeMap* changes, | 430 FileChangeMap* changes, |
| 432 ChangeSeqMap* change_seqs) { | 431 ChangeSeqMap* change_seqs) { |
| 433 ChangeInfo& info = (*changes)[url]; | 432 ChangeInfo& info = (*changes)[url]; |
| 434 if (info.change_seq >= 0 && change_seqs) | 433 if (info.change_seq >= 0 && change_seqs) |
| 435 change_seqs->erase(info.change_seq); | 434 change_seqs->erase(info.change_seq); |
| 436 info.change_list.Update(change); | 435 info.change_list.Update(change); |
| 437 if (info.change_list.empty()) { | 436 if (info.change_list.empty()) { |
| 438 changes->erase(url); | 437 changes->erase(url); |
| 439 return; | 438 return; |
| 440 } | 439 } |
| 441 info.change_seq = new_change_seq; | 440 info.change_seq = new_change_seq; |
| 442 if (change_seqs) | 441 if (change_seqs) |
| 443 (*change_seqs)[info.change_seq] = url; | 442 (*change_seqs)[info.change_seq] = url; |
| 444 } | 443 } |
| 445 | 444 |
| 445 void LocalFileChangeTracker::ResetForURL(const fileapi::FileSystemURL& url, | |
| 446 int change_seq, | |
| 447 leveldb::WriteBatch* batch) { | |
| 448 mirror_changes_.erase(url); | |
| 449 demoted_changes_.erase(url); | |
| 450 change_seqs_.erase(change_seq); | |
| 451 changes_.erase(url); | |
| 452 | |
| 453 std::string serialized_url; | |
| 454 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) { | |
| 455 NOTREACHED() << "Failed to serialize: " << url.DebugString(); | |
| 456 return; | |
| 457 } | |
| 458 batch->Delete(serialized_url); | |
| 459 } | |
| 460 | |
| 446 // TrackerDB ------------------------------------------------------------------- | 461 // TrackerDB ------------------------------------------------------------------- |
| 447 | 462 |
| 448 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, | 463 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, |
| 449 leveldb::Env* env_override) | 464 leveldb::Env* env_override) |
| 450 : base_path_(base_path), | 465 : base_path_(base_path), |
| 451 env_override_(env_override), | 466 env_override_(env_override), |
| 452 db_status_(SYNC_STATUS_OK) {} | 467 db_status_(SYNC_STATUS_OK) {} |
| 453 | 468 |
| 454 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( | 469 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( |
| 455 RecoveryOption recovery_option) { | 470 RecoveryOption recovery_option) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 if (!status.ok() && !status.IsNotFound()) { | 605 if (!status.ok() && !status.IsNotFound()) { |
| 591 HandleError(FROM_HERE, status); | 606 HandleError(FROM_HERE, status); |
| 592 db_status_ = LevelDBStatusToSyncStatusCode(status); | 607 db_status_ = LevelDBStatusToSyncStatusCode(status); |
| 593 db_.reset(); | 608 db_.reset(); |
| 594 return db_status_; | 609 return db_status_; |
| 595 } | 610 } |
| 596 return SYNC_STATUS_OK; | 611 return SYNC_STATUS_OK; |
| 597 } | 612 } |
| 598 | 613 |
| 599 } // namespace sync_file_system | 614 } // namespace sync_file_system |
| OLD | NEW |