| 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 23 matching lines...) Expand all Loading... |
| 34 #include "chrome/browser/sync/syncable/model_type.h" | 34 #include "chrome/browser/sync/syncable/model_type.h" |
| 35 #include "chrome/browser/sync/syncable/syncable_changes_version.h" | 35 #include "chrome/browser/sync/syncable/syncable_changes_version.h" |
| 36 #include "chrome/browser/sync/syncable/syncable_columns.h" | 36 #include "chrome/browser/sync/syncable/syncable_columns.h" |
| 37 #include "chrome/browser/sync/syncable/syncable_enum_conversions.h" | 37 #include "chrome/browser/sync/syncable/syncable_enum_conversions.h" |
| 38 #include "chrome/browser/sync/syncable/syncable-inl.h" | 38 #include "chrome/browser/sync/syncable/syncable-inl.h" |
| 39 #include "chrome/browser/sync/syncable/transaction_observer.h" | 39 #include "chrome/browser/sync/syncable/transaction_observer.h" |
| 40 #include "chrome/browser/sync/util/logging.h" | 40 #include "chrome/browser/sync/util/logging.h" |
| 41 #include "net/base/escape.h" | 41 #include "net/base/escape.h" |
| 42 | 42 |
| 43 namespace { | 43 namespace { |
| 44 |
| 44 enum InvariantCheckLevel { | 45 enum InvariantCheckLevel { |
| 45 OFF = 0, | 46 OFF = 0, |
| 46 VERIFY_IN_MEMORY = 1, | 47 VERIFY_IN_MEMORY = 1, |
| 47 FULL_DB_VERIFICATION = 2 | 48 FULL_DB_VERIFICATION = 2 |
| 48 }; | 49 }; |
| 49 | 50 |
| 50 static const InvariantCheckLevel kInvariantCheckLevel = VERIFY_IN_MEMORY; | 51 static const InvariantCheckLevel kInvariantCheckLevel = VERIFY_IN_MEMORY; |
| 51 | 52 |
| 52 // Max number of milliseconds to spend checking syncable entry invariants | 53 // Max number of milliseconds to spend checking syncable entry invariants |
| 53 static const int kInvariantCheckMaxMs = 50; | 54 static const int kInvariantCheckMaxMs = 50; |
| 54 } // namespace | 55 |
| 56 } // namespace. |
| 55 | 57 |
| 56 using std::string; | 58 using std::string; |
| 57 | 59 |
| 58 namespace syncable { | 60 namespace syncable { |
| 59 | 61 |
| 60 #define ENUM_CASE(x) case x: return #x; break | 62 #define ENUM_CASE(x) case x: return #x; break |
| 61 | 63 |
| 62 std::string WriterTagToString(WriterTag writer_tag) { | 64 std::string WriterTagToString(WriterTag writer_tag) { |
| 63 switch (writer_tag) { | 65 switch (writer_tag) { |
| 64 ENUM_CASE(INVALID); | 66 ENUM_CASE(INVALID); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 delete unapplied_update_metahandles; | 420 delete unapplied_update_metahandles; |
| 419 delete dirty_metahandles; | 421 delete dirty_metahandles; |
| 420 delete metahandles_to_purge; | 422 delete metahandles_to_purge; |
| 421 delete parent_id_child_index; | 423 delete parent_id_child_index; |
| 422 delete client_tag_index; | 424 delete client_tag_index; |
| 423 delete ids_index; | 425 delete ids_index; |
| 424 STLDeleteElements(metahandles_index); | 426 STLDeleteElements(metahandles_index); |
| 425 delete metahandles_index; | 427 delete metahandles_index; |
| 426 } | 428 } |
| 427 | 429 |
| 428 Directory::Directory() : kernel_(NULL), store_(NULL) { | 430 Directory::Directory() : kernel_(NULL), store_(NULL), |
| 431 unrecoverable_error_(false) { |
| 429 } | 432 } |
| 430 | 433 |
| 431 Directory::~Directory() { | 434 Directory::~Directory() { |
| 432 Close(); | 435 Close(); |
| 433 } | 436 } |
| 434 | 437 |
| 435 DirOpenResult Directory::Open(const FilePath& file_path, const string& name, | 438 DirOpenResult Directory::Open(const FilePath& file_path, const string& name, |
| 436 DirectoryChangeDelegate* delegate) { | 439 DirectoryChangeDelegate* delegate) { |
| 437 const DirOpenResult result = OpenImpl(file_path, name, delegate); | 440 const DirOpenResult result = OpenImpl(file_path, name, delegate); |
| 438 if (OPENED != result) | 441 if (OPENED != result) |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 // greater magnitude than could possibly be reached before the next save | 692 // greater magnitude than could possibly be reached before the next save |
| 690 // changes. In other words, it's effectively impossible for the user to | 693 // changes. In other words, it's effectively impossible for the user to |
| 691 // generate 65536 new bookmarks in 3 seconds. | 694 // generate 65536 new bookmarks in 3 seconds. |
| 692 snapshot->kernel_info.next_id -= 65536; | 695 snapshot->kernel_info.next_id -= 65536; |
| 693 snapshot->kernel_info_status = kernel_->info_status; | 696 snapshot->kernel_info_status = kernel_->info_status; |
| 694 // This one we reset on failure. | 697 // This one we reset on failure. |
| 695 kernel_->info_status = KERNEL_SHARE_INFO_VALID; | 698 kernel_->info_status = KERNEL_SHARE_INFO_VALID; |
| 696 } | 699 } |
| 697 | 700 |
| 698 bool Directory::SaveChanges() { | 701 bool Directory::SaveChanges() { |
| 702 if (unrecoverable_error_) |
| 703 return true; |
| 699 bool success = false; | 704 bool success = false; |
| 700 DCHECK(store_); | 705 DCHECK(store_); |
| 701 | 706 |
| 702 base::AutoLock scoped_lock(kernel_->save_changes_mutex); | 707 base::AutoLock scoped_lock(kernel_->save_changes_mutex); |
| 703 | 708 |
| 704 // Snapshot and save. | 709 // Snapshot and save. |
| 705 SaveChangesSnapshot snapshot; | 710 SaveChangesSnapshot snapshot; |
| 706 TakeSnapshotForSaveChanges(&snapshot); | 711 TakeSnapshotForSaveChanges(&snapshot); |
| 707 success = store_->SaveChanges(snapshot); | 712 success = store_->SaveChanges(snapshot); |
| 708 | 713 |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1110 } | 1115 } |
| 1111 | 1116 |
| 1112 void Directory::AddTransactionObserver(TransactionObserver* observer) { | 1117 void Directory::AddTransactionObserver(TransactionObserver* observer) { |
| 1113 kernel_->observers->AddObserver(observer); | 1118 kernel_->observers->AddObserver(observer); |
| 1114 } | 1119 } |
| 1115 | 1120 |
| 1116 void Directory::RemoveTransactionObserver(TransactionObserver* observer) { | 1121 void Directory::RemoveTransactionObserver(TransactionObserver* observer) { |
| 1117 kernel_->observers->RemoveObserver(observer); | 1122 kernel_->observers->RemoveObserver(observer); |
| 1118 } | 1123 } |
| 1119 | 1124 |
| 1125 void Directory::set_unrecoverable_error() { |
| 1126 unrecoverable_error_ = true; |
| 1127 } |
| 1128 |
| 1129 bool Directory::unrecoverable_error() const { |
| 1130 return unrecoverable_error_; |
| 1131 } |
| 1132 |
| 1120 /////////////////////////////////////////////////////////////////////////////// | 1133 /////////////////////////////////////////////////////////////////////////////// |
| 1121 // ScopedKernelLock | 1134 // ScopedKernelLock |
| 1122 | 1135 |
| 1123 ScopedKernelLock::ScopedKernelLock(const Directory* dir) | 1136 ScopedKernelLock::ScopedKernelLock(const Directory* dir) |
| 1124 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) { | 1137 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) { |
| 1125 } | 1138 } |
| 1126 | 1139 |
| 1127 /////////////////////////////////////////////////////////////////////////// | 1140 /////////////////////////////////////////////////////////////////////////// |
| 1128 // Transactions | 1141 // Transactions |
| 1129 | 1142 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1150 BaseTransaction::BaseTransaction(const tracked_objects::Location& from_here, | 1163 BaseTransaction::BaseTransaction(const tracked_objects::Location& from_here, |
| 1151 const char* name, | 1164 const char* name, |
| 1152 WriterTag writer, | 1165 WriterTag writer, |
| 1153 Directory* directory) | 1166 Directory* directory) |
| 1154 : from_here_(from_here), name_(name), writer_(writer), | 1167 : from_here_(from_here), name_(name), writer_(writer), |
| 1155 directory_(directory), dirkernel_(directory->kernel_) { | 1168 directory_(directory), dirkernel_(directory->kernel_) { |
| 1156 dirkernel_->observers->Notify( | 1169 dirkernel_->observers->Notify( |
| 1157 &TransactionObserver::OnTransactionStart, from_here_, writer_); | 1170 &TransactionObserver::OnTransactionStart, from_here_, writer_); |
| 1158 } | 1171 } |
| 1159 | 1172 |
| 1173 void BaseTransaction::set_unrecoverable_error() { |
| 1174 directory_->set_unrecoverable_error(); |
| 1175 } |
| 1176 |
| 1160 BaseTransaction::~BaseTransaction() { | 1177 BaseTransaction::~BaseTransaction() { |
| 1161 dirkernel_->observers->Notify( | 1178 dirkernel_->observers->Notify( |
| 1162 &TransactionObserver::OnTransactionEnd, from_here_, writer_); | 1179 &TransactionObserver::OnTransactionEnd, from_here_, writer_); |
| 1163 } | 1180 } |
| 1164 | 1181 |
| 1165 ReadTransaction::ReadTransaction(const tracked_objects::Location& location, | 1182 ReadTransaction::ReadTransaction(const tracked_objects::Location& location, |
| 1166 Directory* directory) | 1183 Directory* directory) |
| 1167 : BaseTransaction(location, "Read", INVALID, directory) { | 1184 : BaseTransaction(location, "Read", INVALID, directory) { |
| 1168 Lock(); | 1185 Lock(); |
| 1169 } | 1186 } |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 | 1292 |
| 1276 void WriteTransaction::NotifyTransactionComplete( | 1293 void WriteTransaction::NotifyTransactionComplete( |
| 1277 ModelTypeBitSet models_with_changes) { | 1294 ModelTypeBitSet models_with_changes) { |
| 1278 dirkernel_->delegate->HandleTransactionCompleteChangeEvent( | 1295 dirkernel_->delegate->HandleTransactionCompleteChangeEvent( |
| 1279 models_with_changes); | 1296 models_with_changes); |
| 1280 } | 1297 } |
| 1281 | 1298 |
| 1282 WriteTransaction::~WriteTransaction() { | 1299 WriteTransaction::~WriteTransaction() { |
| 1283 const ImmutableEntryKernelMutationMap& mutations = RecordMutations(); | 1300 const ImmutableEntryKernelMutationMap& mutations = RecordMutations(); |
| 1284 | 1301 |
| 1302 if (directory_->unrecoverable_error()) |
| 1303 return; |
| 1285 if (OFF != kInvariantCheckLevel) { | 1304 if (OFF != kInvariantCheckLevel) { |
| 1286 const bool full_scan = (FULL_DB_VERIFICATION == kInvariantCheckLevel); | 1305 const bool full_scan = (FULL_DB_VERIFICATION == kInvariantCheckLevel); |
| 1287 if (full_scan) | 1306 if (full_scan) |
| 1288 directory()->CheckTreeInvariants(this, full_scan); | 1307 directory()->CheckTreeInvariants(this, full_scan); |
| 1289 else | 1308 else |
| 1290 directory()->CheckTreeInvariants(this, mutations.Get()); | 1309 directory()->CheckTreeInvariants(this, mutations.Get()); |
| 1291 } | 1310 } |
| 1292 | 1311 |
| 1293 UnlockAndNotify(mutations); | 1312 UnlockAndNotify(mutations); |
| 1294 } | 1313 } |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1478 ScopedIndexUpdater<ParentIdAndHandleIndexer> updater(lock, kernel_, | 1497 ScopedIndexUpdater<ParentIdAndHandleIndexer> updater(lock, kernel_, |
| 1479 dir()->kernel_->parent_id_child_index); | 1498 dir()->kernel_->parent_id_child_index); |
| 1480 | 1499 |
| 1481 kernel_->put(IS_DEL, is_del); | 1500 kernel_->put(IS_DEL, is_del); |
| 1482 kernel_->mark_dirty(dir()->kernel_->dirty_metahandles); | 1501 kernel_->mark_dirty(dir()->kernel_->dirty_metahandles); |
| 1483 } | 1502 } |
| 1484 | 1503 |
| 1485 if (!is_del) | 1504 if (!is_del) |
| 1486 // Restores position to the 0th index. | 1505 // Restores position to the 0th index. |
| 1487 if (!PutPredecessor(Id())) { | 1506 if (!PutPredecessor(Id())) { |
| 1488 // TODO(lipalani) : Propagate the error to caller. crbug.com/100444. | 1507 return false; |
| 1489 NOTREACHED(); | |
| 1490 } | 1508 } |
| 1491 | 1509 |
| 1492 return true; | 1510 return true; |
| 1493 } | 1511 } |
| 1494 | 1512 |
| 1495 bool MutableEntry::Put(Int64Field field, const int64& value) { | 1513 bool MutableEntry::Put(Int64Field field, const int64& value) { |
| 1496 DCHECK(kernel_); | 1514 DCHECK(kernel_); |
| 1497 if (kernel_->ref(field) != value) { | 1515 if (kernel_->ref(field) != value) { |
| 1498 ScopedKernelLock lock(dir()); | 1516 ScopedKernelLock lock(dir()); |
| 1499 if (SERVER_POSITION_IN_PARENT == field) { | 1517 if (SERVER_POSITION_IN_PARENT == field) { |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1978 CHECK(result); | 1996 CHECK(result); |
| 1979 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), | 1997 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), |
| 1980 end = GetParentChildIndexUpperBound(lock, parent_id); | 1998 end = GetParentChildIndexUpperBound(lock, parent_id); |
| 1981 i != end; ++i) { | 1999 i != end; ++i) { |
| 1982 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); | 2000 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); |
| 1983 result->push_back((*i)->ref(META_HANDLE)); | 2001 result->push_back((*i)->ref(META_HANDLE)); |
| 1984 } | 2002 } |
| 1985 } | 2003 } |
| 1986 | 2004 |
| 1987 } // namespace syncable | 2005 } // namespace syncable |
| OLD | NEW |