| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/syncable/syncable.h" | 5 #include "chrome/browser/sync/syncable/syncable.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <functional> | 9 #include <functional> |
| 10 #include <iomanip> | 10 #include <iomanip> |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 SetFieldValues(*this, kernel_info, | 342 SetFieldValues(*this, kernel_info, |
| 343 &GetBitTempString, &Value::CreateBooleanValue, | 343 &GetBitTempString, &Value::CreateBooleanValue, |
| 344 BIT_TEMPS_BEGIN, BIT_TEMPS_END - 1); | 344 BIT_TEMPS_BEGIN, BIT_TEMPS_END - 1); |
| 345 | 345 |
| 346 return kernel_info; | 346 return kernel_info; |
| 347 } | 347 } |
| 348 | 348 |
| 349 /////////////////////////////////////////////////////////////////////////// | 349 /////////////////////////////////////////////////////////////////////////// |
| 350 // Directory | 350 // Directory |
| 351 | 351 |
| 352 void Directory::InitKernel(const std::string& name, | 352 void Directory::InitKernelForTest( |
| 353 DirectoryChangeDelegate* delegate) { | 353 const std::string& name, |
| 354 DCHECK(kernel_ == NULL); | 354 DirectoryChangeDelegate* delegate, |
| 355 kernel_ = new Kernel(FilePath(), name, KernelLoadInfo(), delegate); | 355 const browser_sync::WeakHandle<TransactionObserver>& |
| 356 transaction_observer) { |
| 357 DCHECK(!kernel_); |
| 358 kernel_ = new Kernel(FilePath(), name, KernelLoadInfo(), |
| 359 delegate, transaction_observer); |
| 356 } | 360 } |
| 357 | 361 |
| 358 Directory::PersistedKernelInfo::PersistedKernelInfo() | 362 Directory::PersistedKernelInfo::PersistedKernelInfo() |
| 359 : next_id(0) { | 363 : next_id(0) { |
| 360 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | 364 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { |
| 361 reset_download_progress(ModelTypeFromInt(i)); | 365 reset_download_progress(ModelTypeFromInt(i)); |
| 362 } | 366 } |
| 363 } | 367 } |
| 364 | 368 |
| 365 Directory::PersistedKernelInfo::~PersistedKernelInfo() {} | 369 Directory::PersistedKernelInfo::~PersistedKernelInfo() {} |
| 366 | 370 |
| 367 void Directory::PersistedKernelInfo::reset_download_progress( | 371 void Directory::PersistedKernelInfo::reset_download_progress( |
| 368 ModelType model_type) { | 372 ModelType model_type) { |
| 369 download_progress[model_type].set_data_type_id( | 373 download_progress[model_type].set_data_type_id( |
| 370 GetExtensionFieldNumberFromModelType(model_type)); | 374 GetExtensionFieldNumberFromModelType(model_type)); |
| 371 // An empty-string token indicates no prior knowledge. | 375 // An empty-string token indicates no prior knowledge. |
| 372 download_progress[model_type].set_token(std::string()); | 376 download_progress[model_type].set_token(std::string()); |
| 373 } | 377 } |
| 374 | 378 |
| 375 Directory::SaveChangesSnapshot::SaveChangesSnapshot() | 379 Directory::SaveChangesSnapshot::SaveChangesSnapshot() |
| 376 : kernel_info_status(KERNEL_SHARE_INFO_INVALID) { | 380 : kernel_info_status(KERNEL_SHARE_INFO_INVALID) { |
| 377 } | 381 } |
| 378 | 382 |
| 379 Directory::SaveChangesSnapshot::~SaveChangesSnapshot() {} | 383 Directory::SaveChangesSnapshot::~SaveChangesSnapshot() {} |
| 380 | 384 |
| 381 Directory::Kernel::Kernel(const FilePath& db_path, | 385 Directory::Kernel::Kernel( |
| 382 const string& name, | 386 const FilePath& db_path, const string& name, |
| 383 const KernelLoadInfo& info, | 387 const KernelLoadInfo& info, DirectoryChangeDelegate* delegate, |
| 384 DirectoryChangeDelegate* delegate) | 388 const browser_sync::WeakHandle<TransactionObserver>& |
| 389 transaction_observer) |
| 385 : db_path(db_path), | 390 : db_path(db_path), |
| 386 refcount(1), | 391 refcount(1), |
| 387 next_write_transaction_id(0), | 392 next_write_transaction_id(0), |
| 388 name(name), | 393 name(name), |
| 389 metahandles_index(new Directory::MetahandlesIndex), | 394 metahandles_index(new Directory::MetahandlesIndex), |
| 390 ids_index(new Directory::IdsIndex), | 395 ids_index(new Directory::IdsIndex), |
| 391 parent_id_child_index(new Directory::ParentIdChildIndex), | 396 parent_id_child_index(new Directory::ParentIdChildIndex), |
| 392 client_tag_index(new Directory::ClientTagIndex), | 397 client_tag_index(new Directory::ClientTagIndex), |
| 393 unapplied_update_metahandles(new MetahandleSet), | 398 unapplied_update_metahandles(new MetahandleSet), |
| 394 unsynced_metahandles(new MetahandleSet), | 399 unsynced_metahandles(new MetahandleSet), |
| 395 dirty_metahandles(new MetahandleSet), | 400 dirty_metahandles(new MetahandleSet), |
| 396 metahandles_to_purge(new MetahandleSet), | 401 metahandles_to_purge(new MetahandleSet), |
| 397 info_status(Directory::KERNEL_SHARE_INFO_VALID), | 402 info_status(Directory::KERNEL_SHARE_INFO_VALID), |
| 398 persisted_info(info.kernel_info), | 403 persisted_info(info.kernel_info), |
| 399 cache_guid(info.cache_guid), | 404 cache_guid(info.cache_guid), |
| 400 next_metahandle(info.max_metahandle + 1), | 405 next_metahandle(info.max_metahandle + 1), |
| 401 delegate(delegate), | 406 delegate(delegate), |
| 402 observers(new ObserverListThreadSafe<TransactionObserver>()) { | 407 transaction_observer(transaction_observer) { |
| 403 DCHECK(delegate); | 408 DCHECK(delegate); |
| 409 DCHECK(transaction_observer.IsInitialized()); |
| 404 } | 410 } |
| 405 | 411 |
| 406 void Directory::Kernel::AddRef() { | 412 void Directory::Kernel::AddRef() { |
| 407 base::subtle::NoBarrier_AtomicIncrement(&refcount, 1); | 413 base::subtle::NoBarrier_AtomicIncrement(&refcount, 1); |
| 408 } | 414 } |
| 409 | 415 |
| 410 void Directory::Kernel::Release() { | 416 void Directory::Kernel::Release() { |
| 411 if (!base::subtle::NoBarrier_AtomicIncrement(&refcount, -1)) | 417 if (!base::subtle::NoBarrier_AtomicIncrement(&refcount, -1)) |
| 412 delete this; | 418 delete this; |
| 413 } | 419 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 425 delete metahandles_index; | 431 delete metahandles_index; |
| 426 } | 432 } |
| 427 | 433 |
| 428 Directory::Directory() : kernel_(NULL), store_(NULL) { | 434 Directory::Directory() : kernel_(NULL), store_(NULL) { |
| 429 } | 435 } |
| 430 | 436 |
| 431 Directory::~Directory() { | 437 Directory::~Directory() { |
| 432 Close(); | 438 Close(); |
| 433 } | 439 } |
| 434 | 440 |
| 435 DirOpenResult Directory::Open(const FilePath& file_path, const string& name, | 441 DirOpenResult Directory::Open( |
| 436 DirectoryChangeDelegate* delegate) { | 442 const FilePath& file_path, const string& name, |
| 437 const DirOpenResult result = OpenImpl(file_path, name, delegate); | 443 DirectoryChangeDelegate* delegate, |
| 444 const browser_sync::WeakHandle<TransactionObserver>& |
| 445 transaction_observer) { |
| 446 const DirOpenResult result = |
| 447 OpenImpl(file_path, name, delegate, transaction_observer); |
| 438 if (OPENED != result) | 448 if (OPENED != result) |
| 439 Close(); | 449 Close(); |
| 440 return result; | 450 return result; |
| 441 } | 451 } |
| 442 | 452 |
| 443 void Directory::InitializeIndices() { | 453 void Directory::InitializeIndices() { |
| 444 MetahandlesIndex::iterator it = kernel_->metahandles_index->begin(); | 454 MetahandlesIndex::iterator it = kernel_->metahandles_index->begin(); |
| 445 for (; it != kernel_->metahandles_index->end(); ++it) { | 455 for (; it != kernel_->metahandles_index->end(); ++it) { |
| 446 EntryKernel* entry = *it; | 456 EntryKernel* entry = *it; |
| 447 InitializeIndexEntry<ParentIdAndHandleIndexer>(entry, | 457 InitializeIndexEntry<ParentIdAndHandleIndexer>(entry, |
| 448 kernel_->parent_id_child_index); | 458 kernel_->parent_id_child_index); |
| 449 InitializeIndexEntry<IdIndexer>(entry, kernel_->ids_index); | 459 InitializeIndexEntry<IdIndexer>(entry, kernel_->ids_index); |
| 450 InitializeIndexEntry<ClientTagIndexer>(entry, kernel_->client_tag_index); | 460 InitializeIndexEntry<ClientTagIndexer>(entry, kernel_->client_tag_index); |
| 451 if (entry->ref(IS_UNSYNCED)) | 461 if (entry->ref(IS_UNSYNCED)) |
| 452 kernel_->unsynced_metahandles->insert(entry->ref(META_HANDLE)); | 462 kernel_->unsynced_metahandles->insert(entry->ref(META_HANDLE)); |
| 453 if (entry->ref(IS_UNAPPLIED_UPDATE)) | 463 if (entry->ref(IS_UNAPPLIED_UPDATE)) |
| 454 kernel_->unapplied_update_metahandles->insert(entry->ref(META_HANDLE)); | 464 kernel_->unapplied_update_metahandles->insert(entry->ref(META_HANDLE)); |
| 455 DCHECK(!entry->is_dirty()); | 465 DCHECK(!entry->is_dirty()); |
| 456 } | 466 } |
| 457 } | 467 } |
| 458 | 468 |
| 459 DirectoryBackingStore* Directory::CreateBackingStore( | 469 DirectoryBackingStore* Directory::CreateBackingStore( |
| 460 const string& dir_name, const FilePath& backing_filepath) { | 470 const string& dir_name, const FilePath& backing_filepath) { |
| 461 return new DirectoryBackingStore(dir_name, backing_filepath); | 471 return new DirectoryBackingStore(dir_name, backing_filepath); |
| 462 } | 472 } |
| 463 | 473 |
| 464 DirOpenResult Directory::OpenImpl(const FilePath& file_path, | 474 DirOpenResult Directory::OpenImpl( |
| 465 const string& name, | 475 const FilePath& file_path, |
| 466 DirectoryChangeDelegate* delegate) { | 476 const string& name, |
| 477 DirectoryChangeDelegate* delegate, |
| 478 const browser_sync::WeakHandle<TransactionObserver>& |
| 479 transaction_observer) { |
| 467 DCHECK_EQ(static_cast<DirectoryBackingStore*>(NULL), store_); | 480 DCHECK_EQ(static_cast<DirectoryBackingStore*>(NULL), store_); |
| 468 FilePath db_path(file_path); | 481 FilePath db_path(file_path); |
| 469 file_util::AbsolutePath(&db_path); | 482 file_util::AbsolutePath(&db_path); |
| 470 store_ = CreateBackingStore(name, db_path); | 483 store_ = CreateBackingStore(name, db_path); |
| 471 | 484 |
| 472 KernelLoadInfo info; | 485 KernelLoadInfo info; |
| 473 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) | 486 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) |
| 474 // swap these later. | 487 // swap these later. |
| 475 MetahandlesIndex metas_bucket; | 488 MetahandlesIndex metas_bucket; |
| 476 DirOpenResult result = store_->Load(&metas_bucket, &info); | 489 DirOpenResult result = store_->Load(&metas_bucket, &info); |
| 477 if (OPENED != result) | 490 if (OPENED != result) |
| 478 return result; | 491 return result; |
| 479 | 492 |
| 480 kernel_ = new Kernel(db_path, name, info, delegate); | 493 kernel_ = new Kernel(db_path, name, info, delegate, transaction_observer); |
| 481 kernel_->metahandles_index->swap(metas_bucket); | 494 kernel_->metahandles_index->swap(metas_bucket); |
| 482 InitializeIndices(); | 495 InitializeIndices(); |
| 483 return OPENED; | 496 return OPENED; |
| 484 } | 497 } |
| 485 | 498 |
| 486 void Directory::Close() { | 499 void Directory::Close() { |
| 487 if (store_) | 500 if (store_) |
| 488 delete store_; | 501 delete store_; |
| 489 store_ = NULL; | 502 store_ = NULL; |
| 490 if (kernel_) { | 503 if (kernel_) { |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 int64 elapsed_ms = check_timer.Elapsed().InMilliseconds(); | 1115 int64 elapsed_ms = check_timer.Elapsed().InMilliseconds(); |
| 1103 if (elapsed_ms > max_ms) { | 1116 if (elapsed_ms > max_ms) { |
| 1104 VLOG(1) << "Cutting Invariant check short after " << elapsed_ms | 1117 VLOG(1) << "Cutting Invariant check short after " << elapsed_ms |
| 1105 << "ms. Processed " << entries_done << "/" << handles.size() | 1118 << "ms. Processed " << entries_done << "/" << handles.size() |
| 1106 << " entries"; | 1119 << " entries"; |
| 1107 return; | 1120 return; |
| 1108 } | 1121 } |
| 1109 } | 1122 } |
| 1110 } | 1123 } |
| 1111 | 1124 |
| 1112 void Directory::AddTransactionObserver(TransactionObserver* observer) { | |
| 1113 kernel_->observers->AddObserver(observer); | |
| 1114 } | |
| 1115 | |
| 1116 void Directory::RemoveTransactionObserver(TransactionObserver* observer) { | |
| 1117 kernel_->observers->RemoveObserver(observer); | |
| 1118 } | |
| 1119 | |
| 1120 /////////////////////////////////////////////////////////////////////////////// | 1125 /////////////////////////////////////////////////////////////////////////////// |
| 1121 // ScopedKernelLock | 1126 // ScopedKernelLock |
| 1122 | 1127 |
| 1123 ScopedKernelLock::ScopedKernelLock(const Directory* dir) | 1128 ScopedKernelLock::ScopedKernelLock(const Directory* dir) |
| 1124 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) { | 1129 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) { |
| 1125 } | 1130 } |
| 1126 | 1131 |
| 1127 /////////////////////////////////////////////////////////////////////////// | 1132 /////////////////////////////////////////////////////////////////////////// |
| 1128 // Transactions | 1133 // Transactions |
| 1129 | 1134 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1146 << name_ << " transaction completed in " << elapsed.InSecondsF() | 1151 << name_ << " transaction completed in " << elapsed.InSecondsF() |
| 1147 << " seconds."; | 1152 << " seconds."; |
| 1148 } | 1153 } |
| 1149 | 1154 |
| 1150 BaseTransaction::BaseTransaction(const tracked_objects::Location& from_here, | 1155 BaseTransaction::BaseTransaction(const tracked_objects::Location& from_here, |
| 1151 const char* name, | 1156 const char* name, |
| 1152 WriterTag writer, | 1157 WriterTag writer, |
| 1153 Directory* directory) | 1158 Directory* directory) |
| 1154 : from_here_(from_here), name_(name), writer_(writer), | 1159 : from_here_(from_here), name_(name), writer_(writer), |
| 1155 directory_(directory), dirkernel_(directory->kernel_) { | 1160 directory_(directory), dirkernel_(directory->kernel_) { |
| 1156 dirkernel_->observers->Notify( | 1161 dirkernel_->transaction_observer.Call(FROM_HERE, |
| 1157 &TransactionObserver::OnTransactionStart, from_here_, writer_); | 1162 &TransactionObserver::OnTransactionStart, from_here_, writer_); |
| 1158 } | 1163 } |
| 1159 | 1164 |
| 1160 BaseTransaction::~BaseTransaction() { | 1165 BaseTransaction::~BaseTransaction() { |
| 1161 if (writer_ != INVALID) { | 1166 if (writer_ != INVALID) { |
| 1162 dirkernel_->observers->Notify( | 1167 dirkernel_->transaction_observer.Call(FROM_HERE, |
| 1163 &TransactionObserver::OnTransactionEnd, from_here_, writer_); | 1168 &TransactionObserver::OnTransactionEnd, from_here_, writer_); |
| 1164 } | 1169 } |
| 1165 } | 1170 } |
| 1166 | 1171 |
| 1167 ReadTransaction::ReadTransaction(const tracked_objects::Location& location, | 1172 ReadTransaction::ReadTransaction(const tracked_objects::Location& location, |
| 1168 Directory* directory) | 1173 Directory* directory) |
| 1169 : BaseTransaction(location, "Read", INVALID, directory) { | 1174 : BaseTransaction(location, "Read", INVALID, directory) { |
| 1170 Lock(); | 1175 Lock(); |
| 1171 } | 1176 } |
| 1172 | 1177 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 immutable_write_transaction_info, this); | 1266 immutable_write_transaction_info, this); |
| 1262 } else { | 1267 } else { |
| 1263 delegate->HandleCalculateChangesChangeEventFromSyncer( | 1268 delegate->HandleCalculateChangesChangeEventFromSyncer( |
| 1264 immutable_write_transaction_info, this); | 1269 immutable_write_transaction_info, this); |
| 1265 } | 1270 } |
| 1266 | 1271 |
| 1267 ModelTypeBitSet models_with_changes = | 1272 ModelTypeBitSet models_with_changes = |
| 1268 delegate->HandleTransactionEndingChangeEvent( | 1273 delegate->HandleTransactionEndingChangeEvent( |
| 1269 immutable_write_transaction_info, this); | 1274 immutable_write_transaction_info, this); |
| 1270 | 1275 |
| 1271 dirkernel_->observers->Notify( | 1276 dirkernel_->transaction_observer.Call(FROM_HERE, |
| 1272 &TransactionObserver::OnTransactionWrite, | 1277 &TransactionObserver::OnTransactionWrite, |
| 1273 immutable_write_transaction_info, models_with_changes); | 1278 immutable_write_transaction_info, models_with_changes); |
| 1274 | 1279 |
| 1275 return models_with_changes; | 1280 return models_with_changes; |
| 1276 } | 1281 } |
| 1277 | 1282 |
| 1278 void WriteTransaction::NotifyTransactionComplete( | 1283 void WriteTransaction::NotifyTransactionComplete( |
| 1279 ModelTypeBitSet models_with_changes) { | 1284 ModelTypeBitSet models_with_changes) { |
| 1280 dirkernel_->delegate->HandleTransactionCompleteChangeEvent( | 1285 dirkernel_->delegate->HandleTransactionCompleteChangeEvent( |
| 1281 models_with_changes); | 1286 models_with_changes); |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2021 if (entry->ref(NEXT_ID).IsRoot() || | 2026 if (entry->ref(NEXT_ID).IsRoot() || |
| 2022 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { | 2027 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { |
| 2023 return entry; | 2028 return entry; |
| 2024 } | 2029 } |
| 2025 } | 2030 } |
| 2026 // There were no children in the linked list. | 2031 // There were no children in the linked list. |
| 2027 return NULL; | 2032 return NULL; |
| 2028 } | 2033 } |
| 2029 | 2034 |
| 2030 } // namespace syncable | 2035 } // namespace syncable |
| OLD | NEW |