Chromium Code Reviews| Index: chrome/browser/sync/engine/syncapi.cc |
| diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc |
| index b1678e8572564c81c66720f7eccef30bb2a69cee..665447c0d158e5537a1378fb4dff068e13a5a12e 100644 |
| --- a/chrome/browser/sync/engine/syncapi.cc |
| +++ b/chrome/browser/sync/engine/syncapi.cc |
| @@ -770,12 +770,21 @@ bool ReadNode::InitByTagLookup(const std::string& tag) { |
| // ReadTransaction member definitions |
| ReadTransaction::ReadTransaction(UserShare* share) |
| : BaseTransaction(share), |
| - transaction_(NULL) { |
| + transaction_(NULL), |
| + close_transaction_(true) { |
| transaction_ = new syncable::ReadTransaction(GetLookup(), __FILE__, __LINE__); |
| } |
| +ReadTransaction::ReadTransaction(UserShare* share, |
| + syncable::BaseTransaction* trans) |
| + : BaseTransaction(share), |
| + transaction_(trans), |
| + close_transaction_(false) {} |
| + |
| ReadTransaction::~ReadTransaction() { |
| - delete transaction_; |
| + if (close_transaction_) { |
| + delete transaction_; |
| + } |
| } |
| syncable::BaseTransaction* ReadTransaction::GetWrappedTrans() const { |
| @@ -923,7 +932,7 @@ class SyncManager::SyncInternal |
| // builds the list of sync-engine initiated changes that will be forwarded to |
| // the SyncManager's Observers. |
| virtual void HandleChannelEvent(const syncable::DirectoryChangeEvent& event); |
| - void HandleTransactionCompleteChangeEvent( |
| + void HandleTransactionEndingChangeEvent( |
| const syncable::DirectoryChangeEvent& event); |
| void HandleCalculateChangesChangeEventFromSyncApi( |
| const syncable::DirectoryChangeEvent& event); |
| @@ -1143,8 +1152,8 @@ class SyncManager::SyncInternal |
| // Each element of this array is a store of change records produced by |
| // HandleChangeEvent during the CALCULATE_CHANGES step. The changes are |
| // segregated by model type, and are stored here to be processed and |
| - // forwarded to the observer slightly later, at the TRANSACTION_COMPLETE |
| - // step by HandleTransactionCompleteChangeEvent. |
| + // forwarded to the observer slightly later, at the TRANSACTION_ENDING |
| + // step by HandleTransactionEndingChangeEvent. |
| ChangeReorderBuffer change_buffers_[syncable::MODEL_TYPE_COUNT]; |
| // The event listener hookup that is registered for HandleChangeEvent. |
| @@ -1635,8 +1644,8 @@ void SyncManager::SyncInternal::HandleDirectoryManagerEvent( |
| // ApplyUpdates) to data_->changelist. |
| void SyncManager::SyncInternal::HandleChannelEvent( |
| const syncable::DirectoryChangeEvent& event) { |
| - if (event.todo == syncable::DirectoryChangeEvent::TRANSACTION_COMPLETE) { |
| - HandleTransactionCompleteChangeEvent(event); |
| + if (event.todo == syncable::DirectoryChangeEvent::TRANSACTION_ENDING) { |
|
ncarter (slow)
2010/07/21 03:02:14
Do we even need the new TRANSACTION_ENDING phase,
|
| + HandleTransactionEndingChangeEvent(event); |
| return; |
| } else if (event.todo == syncable::DirectoryChangeEvent::CALCULATE_CHANGES) { |
| if (event.writer == syncable::SYNCAPI) { |
| @@ -1650,15 +1659,21 @@ void SyncManager::SyncInternal::HandleChannelEvent( |
| } |
| } |
| -void SyncManager::SyncInternal::HandleTransactionCompleteChangeEvent( |
| +void SyncManager::SyncInternal::HandleTransactionEndingChangeEvent( |
| const syncable::DirectoryChangeEvent& event) { |
| - // This notification happens immediately after a syncable WriteTransaction |
| - // falls out of scope. |
| - DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::TRANSACTION_COMPLETE); |
| + // This notification happens immediately before a syncable WriteTransaction |
| + // falls out of scope. It happens while the channel mutex is still held, |
| + // and while the transaction mutex is held, so it cannot be re-entrant. |
| + DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::TRANSACTION_ENDING); |
| if (!observer_ || ChangeBuffersAreEmpty()) |
| return; |
| - ReadTransaction trans(GetUserShare()); |
| + // This will continue the WriteTransaction using a read only wrapper. |
| + // This is the last chance for read to occur in the WriteTransaction |
| + // that's closing. This special ReadTransaction will not close the |
| + // underlying transaction. |
| + ReadTransaction trans(GetUserShare(), event.trans); |
| + |
| for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { |
| if (change_buffers_[i].IsEmpty()) |
| continue; |