| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 | 72 |
| 73 // LocalFileChangeTracker ------------------------------------------------------ | 73 // LocalFileChangeTracker ------------------------------------------------------ |
| 74 | 74 |
| 75 LocalFileChangeTracker::LocalFileChangeTracker( | 75 LocalFileChangeTracker::LocalFileChangeTracker( |
| 76 const base::FilePath& base_path, | 76 const base::FilePath& base_path, |
| 77 leveldb::Env* env_override, | 77 leveldb::Env* env_override, |
| 78 base::SequencedTaskRunner* file_task_runner) | 78 base::SequencedTaskRunner* file_task_runner) |
| 79 : initialized_(false), | 79 : initialized_(false), |
| 80 file_task_runner_(file_task_runner), | 80 file_task_runner_(file_task_runner), |
| 81 tracker_db_(new TrackerDB(base_path, env_override)), | 81 tracker_db_(new TrackerDB(base_path, env_override)), |
| 82 current_change_seq_(0), | 82 current_change_seq_number_(0), |
| 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 DCHECK(!ContainsKey(changes_, url)); |
| 207 demoted_changes_[url] = info; |
| 208 } else { |
| 209 DCHECK(!ContainsKey(demoted_changes_, url)); |
| 210 change_seqs_[info.change_seq] = url; |
| 211 changes_[url] = info; |
| 212 } |
| 207 RemoveMirrorAndCommitChangesForURL(url); | 213 RemoveMirrorAndCommitChangesForURL(url); |
| 208 } | 214 } |
| 209 | 215 |
| 210 void LocalFileChangeTracker::DemoteChangesForURL( | 216 void LocalFileChangeTracker::DemoteChangesForURL( |
| 211 const fileapi::FileSystemURL& url) { | 217 const fileapi::FileSystemURL& url) { |
| 212 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 218 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 219 |
| 213 FileChangeMap::iterator found = changes_.find(url); | 220 FileChangeMap::iterator found = changes_.find(url); |
| 214 if (found == changes_.end()) | 221 if (found == changes_.end()) |
| 215 return; | 222 return; |
| 216 FileChangeList changes = found->second.change_list; | 223 DCHECK(!ContainsKey(demoted_changes_, url)); |
| 217 | |
| 218 mirror_changes_.erase(url); | |
| 219 change_seqs_.erase(found->second.change_seq); | 224 change_seqs_.erase(found->second.change_seq); |
| 225 demoted_changes_.insert(*found); |
| 220 changes_.erase(found); | 226 changes_.erase(found); |
| 221 | |
| 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 UpdateNumChanges(); | 227 UpdateNumChanges(); |
| 229 } | 228 } |
| 230 | 229 |
| 231 void LocalFileChangeTracker::PromoteDemotedChangesForURL( | 230 void LocalFileChangeTracker::PromoteDemotedChangesForURL( |
| 232 const fileapi::FileSystemURL& url) { | 231 const fileapi::FileSystemURL& url) { |
| 233 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 232 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 234 | 233 |
| 235 FileChangeMap::iterator iter = demoted_changes_.find(url); | 234 FileChangeMap::iterator iter = demoted_changes_.find(url); |
| 236 if (iter == demoted_changes_.end()) | 235 if (iter == demoted_changes_.end()) |
| 237 return; | 236 return; |
| 238 | 237 |
| 239 FileChangeList::List change_list = iter->second.change_list.list(); | 238 FileChangeList::List change_list = iter->second.change_list.list(); |
| 240 // Make sure that this URL is in no queues. | 239 // Make sure that this URL is in no queues. |
| 240 DCHECK(!ContainsKey(change_seqs_, iter->second.change_seq)); |
| 241 DCHECK(!ContainsKey(changes_, url)); | 241 DCHECK(!ContainsKey(changes_, url)); |
| 242 DCHECK(!ContainsKey(mirror_changes_, url)); | |
| 243 | 242 |
| 243 change_seqs_[iter->second.change_seq] = url; |
| 244 changes_.insert(*iter); |
| 244 demoted_changes_.erase(iter); | 245 demoted_changes_.erase(iter); |
| 245 | |
| 246 while (!change_list.empty()) { | |
| 247 RecordChange(url, change_list.front()); | |
| 248 change_list.pop_front(); | |
| 249 } | |
| 250 } | 246 } |
| 251 | 247 |
| 252 bool LocalFileChangeTracker::PromoteDemotedChanges() { | 248 bool LocalFileChangeTracker::PromoteDemotedChanges() { |
| 253 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 249 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 254 if (demoted_changes_.empty()) | 250 if (demoted_changes_.empty()) |
| 255 return false; | 251 return false; |
| 256 while (!demoted_changes_.empty()) { | 252 while (!demoted_changes_.empty()) { |
| 257 fileapi::FileSystemURL url = demoted_changes_.begin()->first; | 253 fileapi::FileSystemURL url = demoted_changes_.begin()->first; |
| 258 PromoteDemotedChangesForURL(url); | 254 PromoteDemotedChangesForURL(url); |
| 259 } | 255 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 274 } | 270 } |
| 275 | 271 |
| 276 void LocalFileChangeTracker::ResetForFileSystem( | 272 void LocalFileChangeTracker::ResetForFileSystem( |
| 277 const GURL& origin, | 273 const GURL& origin, |
| 278 fileapi::FileSystemType type) { | 274 fileapi::FileSystemType type) { |
| 279 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 275 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 280 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 276 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
| 281 for (FileChangeMap::iterator iter = changes_.begin(); | 277 for (FileChangeMap::iterator iter = changes_.begin(); |
| 282 iter != changes_.end();) { | 278 iter != changes_.end();) { |
| 283 fileapi::FileSystemURL url = iter->first; | 279 fileapi::FileSystemURL url = iter->first; |
| 284 if (url.origin() != origin || url.type() != type) { | 280 int change_seq = iter->second.change_seq; |
| 285 ++iter; | 281 // Advance |iter| before calling ResetForURL to avoid the iterator |
| 286 continue; | 282 // invalidation in it. |
| 287 } | 283 ++iter; |
| 288 mirror_changes_.erase(url); | 284 if (url.origin() == origin && url.type() == type) |
| 289 demoted_changes_.erase(url); | 285 ResetForURL(url, change_seq, batch.get()); |
| 290 change_seqs_.erase(iter->second.change_seq); | 286 } |
| 291 changes_.erase(iter++); | |
| 292 | 287 |
| 293 std::string serialized_url; | 288 for (FileChangeMap::iterator iter = demoted_changes_.begin(); |
| 294 const bool should_success = | 289 iter != demoted_changes_.end();) { |
| 295 SerializeSyncableFileSystemURL(url, &serialized_url); | 290 fileapi::FileSystemURL url = iter->first; |
| 296 if (!should_success) { | 291 int change_seq = iter->second.change_seq; |
| 297 NOTREACHED() << "Failed to serialize: " << url.DebugString(); | 292 // Advance |iter| before calling ResetForURL to avoid the iterator |
| 298 continue; | 293 // invalidation in it. |
| 299 } | 294 ++iter; |
| 300 batch->Delete(serialized_url); | 295 if (url.origin() == origin && url.type() == type) |
| 296 ResetForURL(url, change_seq, batch.get()); |
| 301 } | 297 } |
| 298 |
| 302 // Fail to apply batch to database wouldn't have critical effect, they'll be | 299 // Fail to apply batch to database wouldn't have critical effect, they'll be |
| 303 // just marked deleted on next relaunch. | 300 // just marked deleted on next relaunch. |
| 304 tracker_db_->WriteBatch(batch.Pass()); | 301 tracker_db_->WriteBatch(batch.Pass()); |
| 305 UpdateNumChanges(); | 302 UpdateNumChanges(); |
| 306 } | 303 } |
| 307 | 304 |
| 308 void LocalFileChangeTracker::UpdateNumChanges() { | 305 void LocalFileChangeTracker::UpdateNumChanges() { |
| 309 base::AutoLock lock(num_changes_lock_); | 306 base::AutoLock lock(num_changes_lock_); |
| 310 num_changes_ = static_cast<int64>(change_seqs_.size()); | 307 num_changes_ = static_cast<int64>(change_seqs_.size()); |
| 311 } | 308 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 LOG(WARNING) << "Failed to access local file."; | 405 LOG(WARNING) << "Failed to access local file."; |
| 409 break; | 406 break; |
| 410 } | 407 } |
| 411 } | 408 } |
| 412 return SYNC_STATUS_OK; | 409 return SYNC_STATUS_OK; |
| 413 } | 410 } |
| 414 | 411 |
| 415 void LocalFileChangeTracker::RecordChange( | 412 void LocalFileChangeTracker::RecordChange( |
| 416 const FileSystemURL& url, const FileChange& change) { | 413 const FileSystemURL& url, const FileChange& change) { |
| 417 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 414 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| 415 int change_seq = current_change_seq_number_++; |
| 418 if (ContainsKey(demoted_changes_, url)) { | 416 if (ContainsKey(demoted_changes_, url)) { |
| 419 RecordChangeToChangeMaps(url, change, 0, &demoted_changes_, NULL); | 417 RecordChangeToChangeMaps(url, change, change_seq, |
| 420 return; | 418 &demoted_changes_, NULL); |
| 419 } else { |
| 420 RecordChangeToChangeMaps(url, change, change_seq, &changes_, &change_seqs_); |
| 421 } | 421 } |
| 422 int change_seq = current_change_seq_++; | |
| 423 RecordChangeToChangeMaps(url, change, change_seq, &changes_, &change_seqs_); | |
| 424 if (ContainsKey(mirror_changes_, url)) | 422 if (ContainsKey(mirror_changes_, url)) |
| 425 RecordChangeToChangeMaps(url, change, change_seq, &mirror_changes_, NULL); | 423 RecordChangeToChangeMaps(url, change, change_seq, &mirror_changes_, NULL); |
| 426 UpdateNumChanges(); | 424 UpdateNumChanges(); |
| 427 } | 425 } |
| 428 | 426 |
| 429 // static | 427 // static |
| 430 void LocalFileChangeTracker::RecordChangeToChangeMaps( | 428 void LocalFileChangeTracker::RecordChangeToChangeMaps( |
| 431 const FileSystemURL& url, | 429 const FileSystemURL& url, |
| 432 const FileChange& change, | 430 const FileChange& change, |
| 433 int new_change_seq, | 431 int new_change_seq, |
| 434 FileChangeMap* changes, | 432 FileChangeMap* changes, |
| 435 ChangeSeqMap* change_seqs) { | 433 ChangeSeqMap* change_seqs) { |
| 436 ChangeInfo& info = (*changes)[url]; | 434 ChangeInfo& info = (*changes)[url]; |
| 437 if (info.change_seq >= 0 && change_seqs) | 435 if (info.change_seq >= 0 && change_seqs) |
| 438 change_seqs->erase(info.change_seq); | 436 change_seqs->erase(info.change_seq); |
| 439 info.change_list.Update(change); | 437 info.change_list.Update(change); |
| 440 if (info.change_list.empty()) { | 438 if (info.change_list.empty()) { |
| 441 changes->erase(url); | 439 changes->erase(url); |
| 442 return; | 440 return; |
| 443 } | 441 } |
| 444 info.change_seq = new_change_seq; | 442 info.change_seq = new_change_seq; |
| 445 if (change_seqs) | 443 if (change_seqs) |
| 446 (*change_seqs)[info.change_seq] = url; | 444 (*change_seqs)[info.change_seq] = url; |
| 447 } | 445 } |
| 448 | 446 |
| 447 void LocalFileChangeTracker::ResetForURL(const fileapi::FileSystemURL& url, |
| 448 int change_seq, |
| 449 leveldb::WriteBatch* batch) { |
| 450 mirror_changes_.erase(url); |
| 451 demoted_changes_.erase(url); |
| 452 change_seqs_.erase(change_seq); |
| 453 changes_.erase(url); |
| 454 |
| 455 std::string serialized_url; |
| 456 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) { |
| 457 NOTREACHED() << "Failed to serialize: " << url.DebugString(); |
| 458 return; |
| 459 } |
| 460 batch->Delete(serialized_url); |
| 461 } |
| 462 |
| 449 // TrackerDB ------------------------------------------------------------------- | 463 // TrackerDB ------------------------------------------------------------------- |
| 450 | 464 |
| 451 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, | 465 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, |
| 452 leveldb::Env* env_override) | 466 leveldb::Env* env_override) |
| 453 : base_path_(base_path), | 467 : base_path_(base_path), |
| 454 env_override_(env_override), | 468 env_override_(env_override), |
| 455 db_status_(SYNC_STATUS_OK) {} | 469 db_status_(SYNC_STATUS_OK) {} |
| 456 | 470 |
| 457 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( | 471 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( |
| 458 RecoveryOption recovery_option) { | 472 RecoveryOption recovery_option) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 if (!status.ok() && !status.IsNotFound()) { | 607 if (!status.ok() && !status.IsNotFound()) { |
| 594 HandleError(FROM_HERE, status); | 608 HandleError(FROM_HERE, status); |
| 595 db_status_ = LevelDBStatusToSyncStatusCode(status); | 609 db_status_ = LevelDBStatusToSyncStatusCode(status); |
| 596 db_.reset(); | 610 db_.reset(); |
| 597 return db_status_; | 611 return db_status_; |
| 598 } | 612 } |
| 599 return SYNC_STATUS_OK; | 613 return SYNC_STATUS_OK; |
| 600 } | 614 } |
| 601 | 615 |
| 602 } // namespace sync_file_system | 616 } // namespace sync_file_system |
| OLD | NEW |