| 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 "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
| 10 #if defined(OS_POSIX) | 10 #if defined(OS_POSIX) |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 | 377 |
| 378 void Directory::Kernel::AddRef() { | 378 void Directory::Kernel::AddRef() { |
| 379 base::subtle::NoBarrier_AtomicIncrement(&refcount, 1); | 379 base::subtle::NoBarrier_AtomicIncrement(&refcount, 1); |
| 380 } | 380 } |
| 381 | 381 |
| 382 void Directory::Kernel::Release() { | 382 void Directory::Kernel::Release() { |
| 383 if (!base::subtle::NoBarrier_AtomicIncrement(&refcount, -1)) | 383 if (!base::subtle::NoBarrier_AtomicIncrement(&refcount, -1)) |
| 384 delete this; | 384 delete this; |
| 385 } | 385 } |
| 386 | 386 |
| 387 void Directory::Kernel::AddChangeListener( |
| 388 DirectoryChangeListener* listener) { |
| 389 base::AutoLock lock(change_listeners_lock_); |
| 390 change_listeners_.AddObserver(listener); |
| 391 } |
| 392 |
| 393 void Directory::Kernel::RemoveChangeListener( |
| 394 DirectoryChangeListener* listener) { |
| 395 base::AutoLock lock(change_listeners_lock_); |
| 396 change_listeners_.RemoveObserver(listener); |
| 397 } |
| 398 |
| 399 // Note: it is possible that a listener will remove itself after we |
| 400 // have made a copy, but before the copy is consumed. This could |
| 401 // theoretically result in accessing a garbage pointer, but can only |
| 402 // occur when an about:sync window is closed in the middle of a |
| 403 // notification. See crbug.com/85481. |
| 404 void Directory::Kernel::CopyChangeListeners( |
| 405 ObserverList<DirectoryChangeListener>* change_listeners) { |
| 406 DCHECK_EQ(0U, change_listeners->size()); |
| 407 base::AutoLock lock(change_listeners_lock_); |
| 408 ObserverListBase<DirectoryChangeListener>::Iterator it(change_listeners_); |
| 409 DirectoryChangeListener* obs; |
| 410 while ((obs = it.GetNext()) != NULL) |
| 411 change_listeners->AddObserver(obs); |
| 412 } |
| 413 |
| 387 Directory::Kernel::~Kernel() { | 414 Directory::Kernel::~Kernel() { |
| 388 CHECK_EQ(0, refcount); | 415 CHECK_EQ(0, refcount); |
| 389 delete channel; | 416 delete channel; |
| 390 delete unsynced_metahandles; | 417 delete unsynced_metahandles; |
| 391 delete unapplied_update_metahandles; | 418 delete unapplied_update_metahandles; |
| 392 delete dirty_metahandles; | 419 delete dirty_metahandles; |
| 393 delete metahandles_to_purge; | 420 delete metahandles_to_purge; |
| 394 delete parent_id_child_index; | 421 delete parent_id_child_index; |
| 395 delete client_tag_index; | 422 delete client_tag_index; |
| 396 delete ids_index; | 423 delete ids_index; |
| (...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 if (elapsed_ms > max_ms) { | 1180 if (elapsed_ms > max_ms) { |
| 1154 VLOG(1) << "Cutting Invariant check short after " << elapsed_ms | 1181 VLOG(1) << "Cutting Invariant check short after " << elapsed_ms |
| 1155 << "ms. Processed " << entries_done << "/" << handles.size() | 1182 << "ms. Processed " << entries_done << "/" << handles.size() |
| 1156 << " entries"; | 1183 << " entries"; |
| 1157 return; | 1184 return; |
| 1158 } | 1185 } |
| 1159 } | 1186 } |
| 1160 } | 1187 } |
| 1161 | 1188 |
| 1162 void Directory::AddChangeListener(DirectoryChangeListener* listener) { | 1189 void Directory::AddChangeListener(DirectoryChangeListener* listener) { |
| 1163 kernel_->change_listeners_.AddObserver(listener); | 1190 kernel_->AddChangeListener(listener); |
| 1164 } | 1191 } |
| 1165 | 1192 |
| 1166 void Directory::RemoveChangeListener(DirectoryChangeListener* listener) { | 1193 void Directory::RemoveChangeListener(DirectoryChangeListener* listener) { |
| 1167 kernel_->change_listeners_.RemoveObserver(listener); | 1194 kernel_->RemoveChangeListener(listener); |
| 1168 } | 1195 } |
| 1169 | 1196 |
| 1170 /////////////////////////////////////////////////////////////////////////////// | 1197 /////////////////////////////////////////////////////////////////////////////// |
| 1171 // ScopedKernelLock | 1198 // ScopedKernelLock |
| 1172 | 1199 |
| 1173 ScopedKernelLock::ScopedKernelLock(const Directory* dir) | 1200 ScopedKernelLock::ScopedKernelLock(const Directory* dir) |
| 1174 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) { | 1201 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) { |
| 1175 } | 1202 } |
| 1176 | 1203 |
| 1177 /////////////////////////////////////////////////////////////////////////// | 1204 /////////////////////////////////////////////////////////////////////////// |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1231 const base::TimeDelta elapsed = base::TimeTicks::Now() - time_acquired_; | 1258 const base::TimeDelta elapsed = base::TimeTicks::Now() - time_acquired_; |
| 1232 if (LOG_IS_ON(INFO) && | 1259 if (LOG_IS_ON(INFO) && |
| 1233 (1 <= logging::GetVlogLevelHelper( | 1260 (1 <= logging::GetVlogLevelHelper( |
| 1234 source_file_, ::strlen(source_file_))) && | 1261 source_file_, ::strlen(source_file_))) && |
| 1235 (elapsed.InMilliseconds() > 50)) { | 1262 (elapsed.InMilliseconds() > 50)) { |
| 1236 logging::LogMessage(source_file_, line_, logging::LOG_INFO).stream() | 1263 logging::LogMessage(source_file_, line_, logging::LOG_INFO).stream() |
| 1237 << name_ << " transaction completed in " << elapsed.InSecondsF() | 1264 << name_ << " transaction completed in " << elapsed.InSecondsF() |
| 1238 << " seconds."; | 1265 << " seconds."; |
| 1239 } | 1266 } |
| 1240 | 1267 |
| 1268 ObserverList<DirectoryChangeListener> change_listeners; |
| 1269 dirkernel_->CopyChangeListeners(&change_listeners); |
| 1270 |
| 1241 if (NULL == originals.get() || originals->empty() || | 1271 if (NULL == originals.get() || originals->empty() || |
| 1242 (dirkernel_->change_listeners_.size() == 0)) { | 1272 (change_listeners.size() == 0)) { |
| 1243 dirkernel_->transaction_mutex.Release(); | 1273 dirkernel_->transaction_mutex.Release(); |
| 1244 return false; | 1274 return false; |
| 1245 } | 1275 } |
| 1246 | 1276 |
| 1247 if (writer_ == syncable::SYNCAPI) { | 1277 if (writer_ == syncable::SYNCAPI) { |
| 1248 FOR_EACH_OBSERVER(DirectoryChangeListener, | 1278 FOR_EACH_OBSERVER(DirectoryChangeListener, |
| 1249 dirkernel_->change_listeners_, | 1279 change_listeners, |
| 1250 HandleCalculateChangesChangeEventFromSyncApi( | 1280 HandleCalculateChangesChangeEventFromSyncApi( |
| 1251 *originals.get(), | 1281 *originals.get(), |
| 1252 writer_, | 1282 writer_, |
| 1253 this)); | 1283 this)); |
| 1254 } else { | 1284 } else { |
| 1255 FOR_EACH_OBSERVER(DirectoryChangeListener, | 1285 FOR_EACH_OBSERVER(DirectoryChangeListener, |
| 1256 dirkernel_->change_listeners_, | 1286 change_listeners, |
| 1257 HandleCalculateChangesChangeEventFromSyncer( | 1287 HandleCalculateChangesChangeEventFromSyncer( |
| 1258 *originals.get(), | 1288 *originals.get(), |
| 1259 writer_, | 1289 writer_, |
| 1260 this)); | 1290 this)); |
| 1261 } | 1291 } |
| 1262 | 1292 |
| 1263 // Set |*models_with_changes| to the union of the return values of | 1293 // Set |*models_with_changes| to the union of the return values of |
| 1264 // the HandleTransactionEndingChangeEvent call to each | 1294 // the HandleTransactionEndingChangeEvent call to each |
| 1265 // DirectoryChangeListener. | 1295 // DirectoryChangeListener. |
| 1266 { | 1296 { |
| 1267 ObserverList<DirectoryChangeListener>::Iterator it( | 1297 ObserverList<DirectoryChangeListener>::Iterator it(change_listeners); |
| 1268 dirkernel_->change_listeners_); | |
| 1269 DirectoryChangeListener* obs = NULL; | 1298 DirectoryChangeListener* obs = NULL; |
| 1270 while ((obs = it.GetNext()) != NULL) { | 1299 while ((obs = it.GetNext()) != NULL) { |
| 1271 *models_with_changes |= obs->HandleTransactionEndingChangeEvent(this); | 1300 *models_with_changes |= obs->HandleTransactionEndingChangeEvent(this); |
| 1272 } | 1301 } |
| 1273 }; | 1302 }; |
| 1274 | 1303 |
| 1275 // Release the transaction. Note, once the transaction is released this thread | 1304 // Release the transaction. Note, once the transaction is released this thread |
| 1276 // can be interrupted by another that was waiting for the transaction, | 1305 // can be interrupted by another that was waiting for the transaction, |
| 1277 // resulting in this code possibly being interrupted with another thread | 1306 // resulting in this code possibly being interrupted with another thread |
| 1278 // performing following the same code path. From this point foward, only | 1307 // performing following the same code path. From this point foward, only |
| 1279 // local state can be touched. | 1308 // local state can be touched. |
| 1280 dirkernel_->transaction_mutex.Release(); | 1309 dirkernel_->transaction_mutex.Release(); |
| 1281 return true; | 1310 return true; |
| 1282 } | 1311 } |
| 1283 | 1312 |
| 1284 void BaseTransaction::NotifyTransactionComplete( | 1313 void BaseTransaction::NotifyTransactionComplete( |
| 1285 ModelTypeBitSet models_with_changes) { | 1314 ModelTypeBitSet models_with_changes) { |
| 1286 FOR_EACH_OBSERVER(DirectoryChangeListener, | 1315 ObserverList<DirectoryChangeListener> change_listeners; |
| 1287 dirkernel_->change_listeners_, | 1316 dirkernel_->CopyChangeListeners(&change_listeners); |
| 1288 HandleTransactionCompleteChangeEvent( | 1317 FOR_EACH_OBSERVER(DirectoryChangeListener, |
| 1289 models_with_changes)); | 1318 change_listeners, |
| 1319 HandleTransactionCompleteChangeEvent( |
| 1320 models_with_changes)); |
| 1290 } | 1321 } |
| 1291 | 1322 |
| 1292 ReadTransaction::ReadTransaction(Directory* directory, const char* file, | 1323 ReadTransaction::ReadTransaction(Directory* directory, const char* file, |
| 1293 int line) | 1324 int line) |
| 1294 : BaseTransaction(directory, "Read", file, line, INVALID) { | 1325 : BaseTransaction(directory, "Read", file, line, INVALID) { |
| 1295 } | 1326 } |
| 1296 | 1327 |
| 1297 ReadTransaction::ReadTransaction(const ScopedDirLookup& scoped_dir, | 1328 ReadTransaction::ReadTransaction(const ScopedDirLookup& scoped_dir, |
| 1298 const char* file, int line) | 1329 const char* file, int line) |
| 1299 : BaseTransaction(scoped_dir.operator -> (), "Read", file, line, INVALID) { | 1330 : BaseTransaction(scoped_dir.operator -> (), "Read", file, line, INVALID) { |
| (...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 CHECK(result); | 2032 CHECK(result); |
| 2002 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), | 2033 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), |
| 2003 end = GetParentChildIndexUpperBound(lock, parent_id); | 2034 end = GetParentChildIndexUpperBound(lock, parent_id); |
| 2004 i != end; ++i) { | 2035 i != end; ++i) { |
| 2005 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); | 2036 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); |
| 2006 result->push_back((*i)->ref(META_HANDLE)); | 2037 result->push_back((*i)->ref(META_HANDLE)); |
| 2007 } | 2038 } |
| 2008 } | 2039 } |
| 2009 | 2040 |
| 2010 } // namespace syncable | 2041 } // namespace syncable |
| OLD | NEW |