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

Unified Diff: chrome/browser/sync/syncable/syncable.cc

Issue 7190001: [Sync] Split DirectoryChangeListener for thread-safety (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix copyright Created 9 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/sync/syncable/syncable.h ('k') | chrome/browser/sync/syncable/syncable_mock.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/sync/syncable/syncable.cc
diff --git a/chrome/browser/sync/syncable/syncable.cc b/chrome/browser/sync/syncable/syncable.cc
index 0e119c48ba885489e80858e46f80587d5403eeb7..039ad4102cc827d274ca3263cce78cb682c56347 100644
--- a/chrome/browser/sync/syncable/syncable.cc
+++ b/chrome/browser/sync/syncable/syncable.cc
@@ -36,6 +36,7 @@
#include "base/string_util.h"
#include "base/stl_util-inl.h"
#include "base/time.h"
+#include "base/tracked.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/sync/engine/syncer.h"
@@ -43,13 +44,15 @@
#include "chrome/browser/sync/protocol/proto_value_conversions.h"
#include "chrome/browser/sync/protocol/service_constants.h"
#include "chrome/browser/sync/syncable/directory_backing_store.h"
-#include "chrome/browser/sync/syncable/directory_change_listener.h"
+#include "chrome/browser/sync/syncable/directory_change_delegate.h"
#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/syncable-inl.h"
#include "chrome/browser/sync/syncable/syncable_changes_version.h"
#include "chrome/browser/sync/syncable/syncable_columns.h"
#include "chrome/browser/sync/syncable/syncable_enum_conversions.h"
+#include "chrome/browser/sync/syncable/transaction_observer.h"
+#include "chrome/browser/sync/util/logging.h"
#include "chrome/common/deprecated/event_sys-inl.h"
#include "net/base/escape.h"
@@ -323,9 +326,10 @@ DictionaryValue* EntryKernel::ToValue() const {
///////////////////////////////////////////////////////////////////////////
// Directory
-void Directory::init_kernel(const std::string& name) {
+void Directory::InitKernel(const std::string& name,
+ DirectoryChangeDelegate* delegate) {
DCHECK(kernel_ == NULL);
- kernel_ = new Kernel(FilePath(), name, KernelLoadInfo());
+ kernel_ = new Kernel(FilePath(), name, KernelLoadInfo(), delegate);
}
Directory::PersistedKernelInfo::PersistedKernelInfo()
@@ -356,7 +360,8 @@ Directory::SaveChangesSnapshot::~SaveChangesSnapshot() {}
Directory::Kernel::Kernel(const FilePath& db_path,
const string& name,
- const KernelLoadInfo& info)
+ const KernelLoadInfo& info,
+ DirectoryChangeDelegate* delegate)
: db_path(db_path),
refcount(1),
name(name),
@@ -372,7 +377,10 @@ Directory::Kernel::Kernel(const FilePath& db_path,
info_status(Directory::KERNEL_SHARE_INFO_VALID),
persisted_info(info.kernel_info),
cache_guid(info.cache_guid),
- next_metahandle(info.max_metahandle + 1) {
+ next_metahandle(info.max_metahandle + 1),
+ delegate(delegate),
+ observers(new ObserverListThreadSafe<TransactionObserver>()) {
+ DCHECK(delegate);
}
void Directory::Kernel::AddRef() {
@@ -384,33 +392,6 @@ void Directory::Kernel::Release() {
delete this;
}
-void Directory::Kernel::AddChangeListener(
- DirectoryChangeListener* listener) {
- base::AutoLock lock(change_listeners_lock_);
- change_listeners_.AddObserver(listener);
-}
-
-void Directory::Kernel::RemoveChangeListener(
- DirectoryChangeListener* listener) {
- base::AutoLock lock(change_listeners_lock_);
- change_listeners_.RemoveObserver(listener);
-}
-
-// Note: it is possible that a listener will remove itself after we
-// have made a copy, but before the copy is consumed. This could
-// theoretically result in accessing a garbage pointer, but can only
-// occur when an about:sync window is closed in the middle of a
-// notification. See crbug.com/85481.
-void Directory::Kernel::CopyChangeListeners(
- ObserverList<DirectoryChangeListener>* change_listeners) {
- DCHECK_EQ(0U, change_listeners->size());
- base::AutoLock lock(change_listeners_lock_);
- ObserverListBase<DirectoryChangeListener>::Iterator it(change_listeners_);
- DirectoryChangeListener* obs;
- while ((obs = it.GetNext()) != NULL)
- change_listeners->AddObserver(obs);
-}
-
Directory::Kernel::~Kernel() {
CHECK_EQ(0, refcount);
delete channel;
@@ -432,8 +413,9 @@ Directory::~Directory() {
Close();
}
-DirOpenResult Directory::Open(const FilePath& file_path, const string& name) {
- const DirOpenResult result = OpenImpl(file_path, name);
+DirOpenResult Directory::Open(const FilePath& file_path, const string& name,
+ DirectoryChangeDelegate* delegate) {
+ const DirOpenResult result = OpenImpl(file_path, name, delegate);
if (OPENED != result)
Close();
return result;
@@ -461,7 +443,8 @@ DirectoryBackingStore* Directory::CreateBackingStore(
}
DirOpenResult Directory::OpenImpl(const FilePath& file_path,
- const string& name) {
+ const string& name,
+ DirectoryChangeDelegate* delegate) {
DCHECK_EQ(static_cast<DirectoryBackingStore*>(NULL), store_);
FilePath db_path(file_path);
file_util::AbsolutePath(&db_path);
@@ -475,7 +458,7 @@ DirOpenResult Directory::OpenImpl(const FilePath& file_path,
if (OPENED != result)
return result;
- kernel_ = new Kernel(db_path, name, info);
+ kernel_ = new Kernel(db_path, name, info, delegate);
kernel_->metahandles_index->swap(metas_bucket);
InitializeIndices();
return OPENED;
@@ -671,7 +654,7 @@ bool Directory::SafeToPurgeFromMemory(const EntryKernel* const entry) const {
}
void Directory::TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot) {
- ReadTransaction trans(this, __FILE__, __LINE__);
+ ReadTransaction trans(this, FROM_HERE);
ScopedKernelLock lock(this);
// Deep copy dirty entries from kernel_->metahandles_index into snapshot and
// clear dirty flags.
@@ -729,7 +712,7 @@ bool Directory::SaveChanges() {
void Directory::VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot) {
// Need a write transaction as we are about to permanently purge entries.
- WriteTransaction trans(this, VACUUM_AFTER_SAVE, __FILE__, __LINE__);
+ WriteTransaction trans(this, VACUUM_AFTER_SAVE, FROM_HERE);
ScopedKernelLock lock(this);
kernel_->flushed_metahandles.Push(0); // Begin flush marker
// Now drop everything we can out of memory.
@@ -770,7 +753,7 @@ void Directory::PurgeEntriesWithTypeIn(const std::set<ModelType>& types) {
return;
{
- WriteTransaction trans(this, PURGE_ENTRIES, __FILE__, __LINE__);
+ WriteTransaction trans(this, PURGE_ENTRIES, FROM_HERE);
{
ScopedKernelLock lock(this);
MetahandlesIndex::iterator it = kernel_->metahandles_index->begin();
@@ -1186,12 +1169,12 @@ void Directory::CheckTreeInvariants(syncable::BaseTransaction* trans,
}
}
-void Directory::AddChangeListener(DirectoryChangeListener* listener) {
- kernel_->AddChangeListener(listener);
+void Directory::AddTransactionObserver(TransactionObserver* observer) {
+ kernel_->observers->AddObserver(observer);
}
-void Directory::RemoveChangeListener(DirectoryChangeListener* listener) {
- kernel_->RemoveChangeListener(listener);
+void Directory::RemoveTransactionObserver(TransactionObserver* observer) {
+ kernel_->observers->RemoveObserver(observer);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1204,25 +1187,6 @@ ScopedKernelLock::ScopedKernelLock(const Directory* dir)
///////////////////////////////////////////////////////////////////////////
// Transactions
-// Helper functions/macros to do logging with a source file/line.
-
-namespace {
-
-bool VlogIsOn(const char* source_file, int verbose_level) {
- return (verbose_level <=
- logging::GetVlogLevelHelper(source_file, ::strlen(source_file)));
-}
-
-} // namespace
-
-#define VLOG_SRC_STREAM(source_file, line, verbose_level) \
- logging::LogMessage(source_file, line, -verbose_level).stream()
-
-#define VLOG_SRC(source_file, line, verbose_level) \
- LAZY_STREAM(VLOG_SRC_STREAM(source_file, line, verbose_level), \
- VLOG_IS_ON(verbose_level) || \
- VlogIsOn(source_file, verbose_level))
-
void BaseTransaction::Lock() {
base::TimeTicks start_time = base::TimeTicks::Now();
@@ -1230,31 +1194,28 @@ void BaseTransaction::Lock() {
time_acquired_ = base::TimeTicks::Now();
const base::TimeDelta elapsed = time_acquired_ - start_time;
- VLOG_SRC(source_file_, line_, 1)
+ VLOG_LOC(from_here_, 1)
<< name_ << " transaction waited "
<< elapsed.InSecondsF() << " seconds.";
}
-BaseTransaction::BaseTransaction(Directory* directory, const char* name,
- const char* source_file, int line, WriterTag writer)
+BaseTransaction::BaseTransaction(
+ Directory* directory, const char* name,
+ const tracked_objects::Location& from_here, WriterTag writer)
: directory_(directory), dirkernel_(directory->kernel_), name_(name),
- source_file_(source_file), line_(line), writer_(writer) {
+ from_here_(from_here), writer_(writer) {
+ dirkernel_->observers->Notify(
+ &TransactionObserver::OnTransactionStart, from_here_, writer_);
Lock();
}
-BaseTransaction::BaseTransaction(Directory* directory)
- : directory_(directory),
- dirkernel_(NULL),
- name_(NULL),
- source_file_(NULL),
- line_(0),
- writer_(INVALID) {
+BaseTransaction::~BaseTransaction() {
+ dirkernel_->observers->Notify(
+ &TransactionObserver::OnTransactionEnd, from_here_, writer_);
}
-BaseTransaction::~BaseTransaction() {}
-
void BaseTransaction::UnlockAndLog(OriginalEntries* entries) {
- // Work while trasnaction mutex is held
+ // Work while transaction mutex is held
ModelTypeBitSet models_with_changes;
if (!NotifyTransactionChangingAndEnding(entries, &models_with_changes))
return;
@@ -1270,50 +1231,32 @@ bool BaseTransaction::NotifyTransactionChangingAndEnding(
scoped_ptr<OriginalEntries> originals(entries);
const base::TimeDelta elapsed = base::TimeTicks::Now() - time_acquired_;
- VLOG_SRC(source_file_, line_, 1)
+ VLOG_LOC(from_here_, 1)
<< name_ << " transaction completed in " << elapsed.InSecondsF()
<< " seconds.";
- ObserverList<DirectoryChangeListener> change_listeners;
- dirkernel_->CopyChangeListeners(&change_listeners);
-
- if (NULL == originals.get() || originals->empty() ||
- (change_listeners.size() == 0)) {
+ if (NULL == originals.get() || originals->empty()) {
dirkernel_->transaction_mutex.Release();
return false;
}
+ DirectoryChangeDelegate* const delegate = dirkernel_->delegate;
if (writer_ == syncable::SYNCAPI) {
- FOR_EACH_OBSERVER(DirectoryChangeListener,
- change_listeners,
- HandleCalculateChangesChangeEventFromSyncApi(
- *originals.get(),
- writer_,
- this));
+ delegate->HandleCalculateChangesChangeEventFromSyncApi(*originals, this);
} else {
- FOR_EACH_OBSERVER(DirectoryChangeListener,
- change_listeners,
- HandleCalculateChangesChangeEventFromSyncer(
- *originals.get(),
- writer_,
- this));
+ delegate->HandleCalculateChangesChangeEventFromSyncer(*originals, this);
}
- // Set |*models_with_changes| to the union of the return values of
- // the HandleTransactionEndingChangeEvent call to each
- // DirectoryChangeListener.
- {
- ObserverList<DirectoryChangeListener>::Iterator it(change_listeners);
- DirectoryChangeListener* obs = NULL;
- while ((obs = it.GetNext()) != NULL) {
- *models_with_changes |= obs->HandleTransactionEndingChangeEvent(this);
- }
- };
+ *models_with_changes = delegate->HandleTransactionEndingChangeEvent(this);
+
+ dirkernel_->observers->Notify(
+ &TransactionObserver::OnTransactionMutate,
+ from_here_, writer_, *originals, *models_with_changes);
// Release the transaction. Note, once the transaction is released this thread
// can be interrupted by another that was waiting for the transaction,
// resulting in this code possibly being interrupted with another thread
- // performing following the same code path. From this point foward, only
+ // performing following the same code path. From this point forward, only
// local state can be touched.
dirkernel_->transaction_mutex.Release();
return true;
@@ -1321,26 +1264,22 @@ bool BaseTransaction::NotifyTransactionChangingAndEnding(
void BaseTransaction::NotifyTransactionComplete(
ModelTypeBitSet models_with_changes) {
- ObserverList<DirectoryChangeListener> change_listeners;
- dirkernel_->CopyChangeListeners(&change_listeners);
- FOR_EACH_OBSERVER(DirectoryChangeListener,
- change_listeners,
- HandleTransactionCompleteChangeEvent(
- models_with_changes));
+ dirkernel_->delegate->HandleTransactionCompleteChangeEvent(
+ models_with_changes);
}
-#undef VLOG_SRC
+#undef VLOG_LOC
-#undef VLOG_SRC_STREAM
+#undef VLOG_LOC_STREAM
-ReadTransaction::ReadTransaction(Directory* directory, const char* file,
- int line)
- : BaseTransaction(directory, "Read", file, line, INVALID) {
+ReadTransaction::ReadTransaction(Directory* directory,
+ const tracked_objects::Location& location)
+ : BaseTransaction(directory, "Read", location, INVALID) {
}
ReadTransaction::ReadTransaction(const ScopedDirLookup& scoped_dir,
- const char* file, int line)
- : BaseTransaction(scoped_dir.operator -> (), "Read", file, line, INVALID) {
+ const tracked_objects::Location& location)
+ : BaseTransaction(scoped_dir.operator -> (), "Read", location, INVALID) {
}
ReadTransaction::~ReadTransaction() {
@@ -1348,22 +1287,18 @@ ReadTransaction::~ReadTransaction() {
}
WriteTransaction::WriteTransaction(Directory* directory, WriterTag writer,
- const char* file, int line)
- : BaseTransaction(directory, "Write", file, line, writer),
+ const tracked_objects::Location& location)
+ : BaseTransaction(directory, "Write", location, writer),
originals_(new OriginalEntries) {
}
WriteTransaction::WriteTransaction(const ScopedDirLookup& scoped_dir,
- WriterTag writer, const char* file, int line)
- : BaseTransaction(scoped_dir.operator -> (), "Write", file, line, writer),
+ WriterTag writer,
+ const tracked_objects::Location& location)
+ : BaseTransaction(scoped_dir.operator -> (), "Write", location, writer),
originals_(new OriginalEntries) {
}
-WriteTransaction::WriteTransaction(Directory *directory)
- : BaseTransaction(directory),
- originals_(new OriginalEntries) {
-}
-
void WriteTransaction::SaveOriginal(EntryKernel* entry) {
if (NULL == entry)
return;
« no previous file with comments | « chrome/browser/sync/syncable/syncable.h ('k') | chrome/browser/sync/syncable/syncable_mock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698