Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: chrome/browser/sync/engine/syncapi.cc

Issue 2805095: Fix deadlock by introducing a new transaction event. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/sync/engine/syncapi.h ('k') | chrome/browser/sync/syncable/syncable.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/engine/syncapi.h" 5 #include "chrome/browser/sync/engine/syncapi.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #include <iomanip> 9 #include <iomanip>
10 #include <list> 10 #include <list>
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 LOG_IF(WARNING, model_type == syncable::UNSPECIFIED || 763 LOG_IF(WARNING, model_type == syncable::UNSPECIFIED ||
764 model_type == syncable::TOP_LEVEL_FOLDER) 764 model_type == syncable::TOP_LEVEL_FOLDER)
765 << "SyncAPI InitByTagLookup referencing unusually typed object."; 765 << "SyncAPI InitByTagLookup referencing unusually typed object.";
766 return DecryptIfNecessary(entry_); 766 return DecryptIfNecessary(entry_);
767 } 767 }
768 768
769 ////////////////////////////////////////////////////////////////////////// 769 //////////////////////////////////////////////////////////////////////////
770 // ReadTransaction member definitions 770 // ReadTransaction member definitions
771 ReadTransaction::ReadTransaction(UserShare* share) 771 ReadTransaction::ReadTransaction(UserShare* share)
772 : BaseTransaction(share), 772 : BaseTransaction(share),
773 transaction_(NULL) { 773 transaction_(NULL),
774 close_transaction_(true) {
774 transaction_ = new syncable::ReadTransaction(GetLookup(), __FILE__, __LINE__); 775 transaction_ = new syncable::ReadTransaction(GetLookup(), __FILE__, __LINE__);
775 } 776 }
776 777
778 ReadTransaction::ReadTransaction(UserShare* share,
779 syncable::BaseTransaction* trans)
780 : BaseTransaction(share),
781 transaction_(trans),
782 close_transaction_(false) {}
783
777 ReadTransaction::~ReadTransaction() { 784 ReadTransaction::~ReadTransaction() {
778 delete transaction_; 785 if (close_transaction_) {
786 delete transaction_;
787 }
779 } 788 }
780 789
781 syncable::BaseTransaction* ReadTransaction::GetWrappedTrans() const { 790 syncable::BaseTransaction* ReadTransaction::GetWrappedTrans() const {
782 return transaction_; 791 return transaction_;
783 } 792 }
784 793
785 ////////////////////////////////////////////////////////////////////////// 794 //////////////////////////////////////////////////////////////////////////
786 // WriteTransaction member definitions 795 // WriteTransaction member definitions
787 WriteTransaction::WriteTransaction(UserShare* share) 796 WriteTransaction::WriteTransaction(UserShare* share)
788 : BaseTransaction(share), 797 : BaseTransaction(share),
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 void SetPassphrase(const std::string& passphrase); 925 void SetPassphrase(const std::string& passphrase);
917 926
918 // Call periodically from a database-safe thread to persist recent changes 927 // Call periodically from a database-safe thread to persist recent changes
919 // to the syncapi model. 928 // to the syncapi model.
920 void SaveChanges(); 929 void SaveChanges();
921 930
922 // This listener is called upon completion of a syncable transaction, and 931 // This listener is called upon completion of a syncable transaction, and
923 // builds the list of sync-engine initiated changes that will be forwarded to 932 // builds the list of sync-engine initiated changes that will be forwarded to
924 // the SyncManager's Observers. 933 // the SyncManager's Observers.
925 virtual void HandleChannelEvent(const syncable::DirectoryChangeEvent& event); 934 virtual void HandleChannelEvent(const syncable::DirectoryChangeEvent& event);
926 void HandleTransactionCompleteChangeEvent( 935 void HandleTransactionEndingChangeEvent(
927 const syncable::DirectoryChangeEvent& event); 936 const syncable::DirectoryChangeEvent& event);
928 void HandleCalculateChangesChangeEventFromSyncApi( 937 void HandleCalculateChangesChangeEventFromSyncApi(
929 const syncable::DirectoryChangeEvent& event); 938 const syncable::DirectoryChangeEvent& event);
930 void HandleCalculateChangesChangeEventFromSyncer( 939 void HandleCalculateChangesChangeEventFromSyncer(
931 const syncable::DirectoryChangeEvent& event); 940 const syncable::DirectoryChangeEvent& event);
932 941
933 // This listener is called by the syncer channel for all syncer events. 942 // This listener is called by the syncer channel for all syncer events.
934 virtual void HandleChannelEvent(const SyncerEvent& event); 943 virtual void HandleChannelEvent(const SyncerEvent& event);
935 944
936 // We have a direct hookup to the authwatcher to be notified for auth failures 945 // We have a direct hookup to the authwatcher to be notified for auth failures
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 // AuthWatcher kicks off the authentication process and follows it through 1145 // AuthWatcher kicks off the authentication process and follows it through
1137 // phase 1 (GAIA) to phase 2 (sync engine). As part of this work it determines 1146 // phase 1 (GAIA) to phase 2 (sync engine). As part of this work it determines
1138 // the initial connectivity and causes the server connection event to be 1147 // the initial connectivity and causes the server connection event to be
1139 // broadcast, which signals the syncer thread to start syncing. 1148 // broadcast, which signals the syncer thread to start syncing.
1140 // It has a heavy duty constructor requiring boilerplate so we heap allocate. 1149 // It has a heavy duty constructor requiring boilerplate so we heap allocate.
1141 scoped_refptr<AuthWatcher> auth_watcher_; 1150 scoped_refptr<AuthWatcher> auth_watcher_;
1142 1151
1143 // Each element of this array is a store of change records produced by 1152 // Each element of this array is a store of change records produced by
1144 // HandleChangeEvent during the CALCULATE_CHANGES step. The changes are 1153 // HandleChangeEvent during the CALCULATE_CHANGES step. The changes are
1145 // segregated by model type, and are stored here to be processed and 1154 // segregated by model type, and are stored here to be processed and
1146 // forwarded to the observer slightly later, at the TRANSACTION_COMPLETE 1155 // forwarded to the observer slightly later, at the TRANSACTION_ENDING
1147 // step by HandleTransactionCompleteChangeEvent. 1156 // step by HandleTransactionEndingChangeEvent.
1148 ChangeReorderBuffer change_buffers_[syncable::MODEL_TYPE_COUNT]; 1157 ChangeReorderBuffer change_buffers_[syncable::MODEL_TYPE_COUNT];
1149 1158
1150 // The event listener hookup that is registered for HandleChangeEvent. 1159 // The event listener hookup that is registered for HandleChangeEvent.
1151 scoped_ptr<browser_sync::ChannelHookup<syncable::DirectoryChangeEvent> > 1160 scoped_ptr<browser_sync::ChannelHookup<syncable::DirectoryChangeEvent> >
1152 dir_change_hookup_; 1161 dir_change_hookup_;
1153 1162
1154 // The event listener hookup registered for HandleSyncerEvent. 1163 // The event listener hookup registered for HandleSyncerEvent.
1155 scoped_ptr<browser_sync::ChannelHookup<SyncerEvent> > syncer_event_; 1164 scoped_ptr<browser_sync::ChannelHookup<SyncerEvent> > syncer_event_;
1156 1165
1157 // The event listener hookup registered for HandleAuthWatcherEvent. 1166 // The event listener hookup registered for HandleAuthWatcherEvent.
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 DCHECK(!initialized()) << "Should only happen once"; 1637 DCHECK(!initialized()) << "Should only happen once";
1629 MarkAndNotifyInitializationComplete(); 1638 MarkAndNotifyInitializationComplete();
1630 } 1639 }
1631 } 1640 }
1632 1641
1633 // Listen to model changes, filter out ones initiated by the sync API, and 1642 // Listen to model changes, filter out ones initiated by the sync API, and
1634 // saves the rest (hopefully just backend Syncer changes resulting from 1643 // saves the rest (hopefully just backend Syncer changes resulting from
1635 // ApplyUpdates) to data_->changelist. 1644 // ApplyUpdates) to data_->changelist.
1636 void SyncManager::SyncInternal::HandleChannelEvent( 1645 void SyncManager::SyncInternal::HandleChannelEvent(
1637 const syncable::DirectoryChangeEvent& event) { 1646 const syncable::DirectoryChangeEvent& event) {
1638 if (event.todo == syncable::DirectoryChangeEvent::TRANSACTION_COMPLETE) { 1647 if (event.todo == syncable::DirectoryChangeEvent::TRANSACTION_ENDING) {
ncarter (slow) 2010/07/21 03:02:14 Do we even need the new TRANSACTION_ENDING phase,
1639 HandleTransactionCompleteChangeEvent(event); 1648 HandleTransactionEndingChangeEvent(event);
1640 return; 1649 return;
1641 } else if (event.todo == syncable::DirectoryChangeEvent::CALCULATE_CHANGES) { 1650 } else if (event.todo == syncable::DirectoryChangeEvent::CALCULATE_CHANGES) {
1642 if (event.writer == syncable::SYNCAPI) { 1651 if (event.writer == syncable::SYNCAPI) {
1643 HandleCalculateChangesChangeEventFromSyncApi(event); 1652 HandleCalculateChangesChangeEventFromSyncApi(event);
1644 return; 1653 return;
1645 } 1654 }
1646 HandleCalculateChangesChangeEventFromSyncer(event); 1655 HandleCalculateChangesChangeEventFromSyncer(event);
1647 return; 1656 return;
1648 } else if (event.todo == syncable::DirectoryChangeEvent::SHUTDOWN) { 1657 } else if (event.todo == syncable::DirectoryChangeEvent::SHUTDOWN) {
1649 dir_change_hookup_.reset(); 1658 dir_change_hookup_.reset();
1650 } 1659 }
1651 } 1660 }
1652 1661
1653 void SyncManager::SyncInternal::HandleTransactionCompleteChangeEvent( 1662 void SyncManager::SyncInternal::HandleTransactionEndingChangeEvent(
1654 const syncable::DirectoryChangeEvent& event) { 1663 const syncable::DirectoryChangeEvent& event) {
1655 // This notification happens immediately after a syncable WriteTransaction 1664 // This notification happens immediately before a syncable WriteTransaction
1656 // falls out of scope. 1665 // falls out of scope. It happens while the channel mutex is still held,
1657 DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::TRANSACTION_COMPLETE); 1666 // and while the transaction mutex is held, so it cannot be re-entrant.
1667 DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::TRANSACTION_ENDING);
1658 if (!observer_ || ChangeBuffersAreEmpty()) 1668 if (!observer_ || ChangeBuffersAreEmpty())
1659 return; 1669 return;
1660 1670
1661 ReadTransaction trans(GetUserShare()); 1671 // This will continue the WriteTransaction using a read only wrapper.
1672 // This is the last chance for read to occur in the WriteTransaction
1673 // that's closing. This special ReadTransaction will not close the
1674 // underlying transaction.
1675 ReadTransaction trans(GetUserShare(), event.trans);
1676
1662 for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { 1677 for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) {
1663 if (change_buffers_[i].IsEmpty()) 1678 if (change_buffers_[i].IsEmpty())
1664 continue; 1679 continue;
1665 1680
1666 vector<ChangeRecord> ordered_changes; 1681 vector<ChangeRecord> ordered_changes;
1667 change_buffers_[i].GetAllChangesInTreeOrder(&trans, &ordered_changes); 1682 change_buffers_[i].GetAllChangesInTreeOrder(&trans, &ordered_changes);
1668 if (!ordered_changes.empty()) { 1683 if (!ordered_changes.empty()) {
1669 observer_->OnChangesApplied(syncable::ModelTypeFromInt(i), &trans, 1684 observer_->OnChangesApplied(syncable::ModelTypeFromInt(i), &trans,
1670 &ordered_changes[0], ordered_changes.size()); 1685 &ordered_changes[0], ordered_changes.size());
1671 } 1686 }
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
2118 BaseTransaction::~BaseTransaction() { 2133 BaseTransaction::~BaseTransaction() {
2119 delete lookup_; 2134 delete lookup_;
2120 } 2135 }
2121 2136
2122 UserShare* SyncManager::GetUserShare() const { 2137 UserShare* SyncManager::GetUserShare() const {
2123 DCHECK(data_->initialized()) << "GetUserShare requires initialization!"; 2138 DCHECK(data_->initialized()) << "GetUserShare requires initialization!";
2124 return data_->GetUserShare(); 2139 return data_->GetUserShare();
2125 } 2140 }
2126 2141
2127 } // namespace sync_api 2142 } // namespace sync_api
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/syncapi.h ('k') | chrome/browser/sync/syncable/syncable.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698