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 |