summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync
diff options
context:
space:
mode:
authorzea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-11 17:57:39 +0000
committerzea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-11 17:57:39 +0000
commit603b3f168d4e6b546ba6c8597fb6d16fe637f88e (patch)
tree8c2702ce71d3c894eafacf68f7d86cfc77a71596 /chrome/browser/sync
parent583634b8cb62af00593258b64680bf6b2358d43d (diff)
downloadchromium_src-603b3f168d4e6b546ba6c8597fb6d16fe637f88e.zip
chromium_src-603b3f168d4e6b546ba6c8597fb6d16fe637f88e.tar.gz
chromium_src-603b3f168d4e6b546ba6c8597fb6d16fe637f88e.tar.bz2
Plumb datatype information to syncer from nudges.
Add plumbing to support tracking which datatypes are triggering nudges. This gets plumbed from the nudges to the actual sync session. Also added some histogramming for the frequency at which particular datatypes trigger syncs (as a result, also supports tracking how often datatypes are changing). New histograms are of the form "Sync.Freq<datatype>", with bucket units in milliseconds. BUG=None TEST=unit_tests Review URL: http://codereview.chromium.org/4659003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65818 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync')
-rw-r--r--chrome/browser/sync/engine/download_updates_command.cc3
-rw-r--r--chrome/browser/sync/engine/syncapi.cc57
-rw-r--r--chrome/browser/sync/engine/syncer.cc11
-rw-r--r--chrome/browser/sync/engine/syncer.h16
-rw-r--r--chrome/browser/sync/engine/syncer_thread.cc50
-rw-r--r--chrome/browser/sync/engine/syncer_thread.h20
-rw-r--r--chrome/browser/sync/engine/syncer_thread_unittest.cc30
-rw-r--r--chrome/browser/sync/notifier/server_notifier_thread.cc11
-rw-r--r--chrome/browser/sync/sessions/sync_session.cc12
-rw-r--r--chrome/browser/sync/sessions/sync_session.h13
-rw-r--r--chrome/browser/sync/syncable/model_type.cc70
-rw-r--r--chrome/browser/sync/syncable/model_type.h11
12 files changed, 256 insertions, 48 deletions
diff --git a/chrome/browser/sync/engine/download_updates_command.cc b/chrome/browser/sync/engine/download_updates_command.cc
index 4677f87..a8d495d 100644
--- a/chrome/browser/sync/engine/download_updates_command.cc
+++ b/chrome/browser/sync/engine/download_updates_command.cc
@@ -67,7 +67,8 @@ void DownloadUpdatesCommand::ExecuteImpl(SyncSession* session) {
get_updates->set_fetch_folders(true);
// Set GetUpdatesMessage.GetUpdatesCallerInfo information.
- get_updates->mutable_caller_info()->set_source(session->TestAndSetSource());
+ get_updates->mutable_caller_info()->set_source(
+ session->TestAndSetSource().first);
get_updates->mutable_caller_info()->set_notifications_enabled(
session->context()->notifications_enabled());
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 9d42312..bdd7be9 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -186,8 +186,8 @@ std::string BaseNode::GenerateSyncableHash(
sync_pb::PasswordSpecificsData* DecryptPasswordSpecifics(
const sync_pb::EntitySpecifics& specifics, Cryptographer* crypto) {
- if (!specifics.HasExtension(sync_pb::password))
- return NULL;
+ if (!specifics.HasExtension(sync_pb::password))
+ return NULL;
const sync_pb::EncryptedData& encrypted =
specifics.GetExtension(sync_pb::password).encrypted();
scoped_ptr<sync_pb::PasswordSpecificsData> data(
@@ -1884,6 +1884,7 @@ void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncApi(
bool exists_unsynced_items = false;
bool only_preference_changes = true;
+ syncable::ModelTypeBitSet model_types;
for (syncable::OriginalEntries::const_iterator i = event.originals->begin();
i != event.originals->end() && !exists_unsynced_items;
++i) {
@@ -1902,6 +1903,7 @@ void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncApi(
// Unsynced items will cause us to nudge the the syncer.
exists_unsynced_items = true;
+ model_types[model_type] = true;
if (model_type != syncable::PREFERENCES)
only_preference_changes = false;
}
@@ -1909,7 +1911,10 @@ void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncApi(
if (exists_unsynced_items && syncer_thread()) {
int nudge_delay = only_preference_changes ?
kPreferencesNudgeDelayMilliseconds : kDefaultNudgeDelayMilliseconds;
- syncer_thread()->NudgeSyncer(nudge_delay, SyncerThread::kLocal);
+ syncer_thread()->NudgeSyncerWithDataTypes(
+ nudge_delay,
+ SyncerThread::kLocal,
+ model_types);
}
}
@@ -2146,26 +2151,48 @@ void SyncManager::SyncInternal::TalkMediatorLogin(
void SyncManager::SyncInternal::OnIncomingNotification(
const IncomingNotificationData& notification_data) {
+ syncable::ModelTypeBitSet model_types;
+
// Check if the service url is a sync URL. An empty service URL is
// treated as a legacy sync notification. If we're listening to
// server-issued notifications, no need to check the service_url.
- if ((notifier_options_.notification_method ==
- notifier::NOTIFICATION_SERVER) ||
- notification_data.service_url.empty() ||
- (notification_data.service_url ==
- browser_sync::kSyncLegacyServiceUrl) ||
- (notification_data.service_url ==
- browser_sync::kSyncServiceUrl)) {
- VLOG(1) << "P2P: Updates on server, pushing syncer";
- if (syncer_thread()) {
- // Introduce a delay to help coalesce initial notifications.
- syncer_thread()->NudgeSyncer(250, SyncerThread::kNotification);
+ if (notifier_options_.notification_method ==
+ notifier::NOTIFICATION_SERVER) {
+ VLOG(1) << "Sync received server notification: " <<
+ notification_data.service_specific_data;
+
+ if (!syncable::ModelTypeBitSetFromString(
+ notification_data.service_specific_data,
+ &model_types)) {
+ LOG(DFATAL) << "Could not extract model types from server data.";
+ model_types.set();
}
- allstatus_.IncrementNotificationsReceived();
+ } else if (notification_data.service_url.empty() ||
+ (notification_data.service_url ==
+ browser_sync::kSyncLegacyServiceUrl) ||
+ (notification_data.service_url ==
+ browser_sync::kSyncServiceUrl)) {
+ VLOG(1) << "Sync received P2P notification.";
+
+ // Catch for sync integration tests (uses p2p). Just set all datatypes.
+ model_types.set();
} else {
LOG(WARNING) << "Notification fron unexpected source: "
<< notification_data.service_url;
}
+
+ if (model_types.any()) {
+ if (syncer_thread()) {
+ // Introduce a delay to help coalesce initial notifications.
+ syncer_thread()->NudgeSyncerWithDataTypes(
+ 250,
+ SyncerThread::kNotification,
+ model_types);
+ }
+ allstatus_.IncrementNotificationsReceived();
+ } else {
+ LOG(WARNING) << "Sync received notification without any type information.";
+ }
}
void SyncManager::SyncInternal::OnOutgoingNotification() {
diff --git a/chrome/browser/sync/engine/syncer.cc b/chrome/browser/sync/engine/syncer.cc
index 98776b2..24f417d 100644
--- a/chrome/browser/sync/engine/syncer.cc
+++ b/chrome/browser/sync/engine/syncer.cc
@@ -58,9 +58,9 @@ Syncer::Syncer(sessions::SyncSessionContext* context)
max_commit_batch_size_(kDefaultMaxCommitBatchSize),
resolver_scoper_(context, &resolver_),
context_(context),
- updates_source_(sync_pb::GetUpdatesCallerInfo::UNKNOWN),
+ updates_source_(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
+ syncable::ModelTypeBitSet()),
pre_conflict_resolution_closure_(NULL) {
-
ScopedDirLookup dir(context->directory_manager(), context->account_name());
// The directory must be good here.
CHECK(dir.good());
@@ -84,10 +84,9 @@ bool Syncer::SyncShare(sessions::SyncSession::Delegate* delegate) {
}
bool Syncer::SyncShare(sessions::SyncSession* session) {
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source =
- TestAndSetUpdatesSource();
+ sessions::SyncSourceInfo source = TestAndSetUpdatesSource();
session->set_source(source);
- if (sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA == source) {
+ if (sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA == source.first) {
SyncShare(session, CLEAR_PRIVATE_DATA, SYNCER_END);
return false;
} else {
@@ -154,7 +153,7 @@ void Syncer::SyncShare(sessions::SyncSession* session,
break;
}
case PROCESS_UPDATES: {
- VLOG(1) << "Processing Updates";
+ VLOG(1) << "Processing Updates";
ProcessUpdatesCommand process_updates;
process_updates.Execute(session);
next_step = STORE_TIMESTAMPS;
diff --git a/chrome/browser/sync/engine/syncer.h b/chrome/browser/sync/engine/syncer.h
index e2d1c65..9344732 100644
--- a/chrome/browser/sync/engine/syncer.h
+++ b/chrome/browser/sync/engine/syncer.h
@@ -19,6 +19,7 @@
#include "chrome/browser/sync/engine/syncproto.h"
#include "chrome/browser/sync/sessions/sync_session.h"
#include "chrome/browser/sync/syncable/directory_event.h"
+#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/util/extensions_activity_monitor.h"
#include "chrome/common/deprecated/event_sys.h"
#include "chrome/common/deprecated/event_sys-inl.h"
@@ -106,16 +107,17 @@ class Syncer {
// Volatile reader for the source member of the syncer session object. The
// value is set to the SYNC_CYCLE_CONTINUATION value to signal that it has
// been read.
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource TestAndSetUpdatesSource() {
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource old_source =
- updates_source_;
- set_updates_source(sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION);
+ sessions::SyncSourceInfo TestAndSetUpdatesSource() {
+ sessions::SyncSourceInfo old_source = updates_source_;
+ set_updates_source(sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
+ updates_source_.second);
return old_source;
}
void set_updates_source(
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) {
- updates_source_ = source;
+ sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+ const syncable::ModelTypeBitSet& datatypes) {
+ updates_source_ = sessions::SyncSourceInfo(source, datatypes);
}
private:
@@ -143,7 +145,7 @@ class Syncer {
sessions::SyncSessionContext* context_;
// The source of the last nudge.
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source_;
+ sessions::SyncSourceInfo updates_source_;
// A callback hook used in unittests to simulate changes between conflict set
// building and conflict resolution.
diff --git a/chrome/browser/sync/engine/syncer_thread.cc b/chrome/browser/sync/engine/syncer_thread.cc
index 7906f38..765c1f1 100644
--- a/chrome/browser/sync/engine/syncer_thread.cc
+++ b/chrome/browser/sync/engine/syncer_thread.cc
@@ -16,6 +16,7 @@
#include <queue>
#include "base/rand_util.h"
+#include "base/stringprintf.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "chrome/browser/sync/engine/model_safe_worker.h"
#include "chrome/browser/sync/engine/net/server_connection_manager.h"
@@ -53,13 +54,28 @@ static const int kBackoffRandomizationFactor = 2;
const int SyncerThread::kMaxBackoffSeconds = 60 * 60 * 4; // 4 hours.
-void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) {
+void SyncerThread::NudgeSyncerWithDataTypes(
+ int milliseconds_from_now,
+ NudgeSource source,
+ const syncable::ModelTypeBitSet& model_types) {
AutoLock lock(lock_);
if (vault_.syncer_ == NULL) {
return;
}
- NudgeSyncImpl(milliseconds_from_now, source);
+ NudgeSyncImpl(milliseconds_from_now, source, model_types);
+}
+
+void SyncerThread::NudgeSyncer(
+ int milliseconds_from_now,
+ NudgeSource source) {
+ AutoLock lock(lock_);
+ if (vault_.syncer_ == NULL) {
+ return;
+ }
+
+ syncable::ModelTypeBitSet model_types; // All false by default.
+ NudgeSyncImpl(milliseconds_from_now, source, model_types);
}
SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
@@ -77,7 +93,6 @@ SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
if (context->connection_manager())
WatchConnectionManager(context->connection_manager());
-
}
SyncerThread::~SyncerThread() {
@@ -321,7 +336,24 @@ void SyncerThread::ThreadMainLoop() {
VLOG(1) << "Calling Sync Main at time " << Time::Now().ToInternalValue();
SyncMain(vault_.syncer_);
- last_sync_time = TimeTicks::Now();
+
+ // Update timing information for how often these datatypes are triggering
+ // nudges.
+ base::TimeTicks now = TimeTicks::Now();
+ for (size_t i = syncable::FIRST_REAL_MODEL_TYPE;
+ i < vault_.pending_nudge_types_.size();
+ ++i) {
+ if (vault_.pending_nudge_types_[i]) {
+ syncable::PostTimeToTypeHistogram(syncable::ModelType(i),
+ now - last_sync_time);
+ }
+ }
+
+ // Now that the nudge has been handled, we can reset our tracking of the
+ // datatypes triggering a nudge.
+ vault_.pending_nudge_types_.reset();
+
+ last_sync_time = now;
VLOG(1) << "Updating the next polling time after SyncMain";
vault_.current_wait_interval_ = CalculatePollingWaitTime(
@@ -555,7 +587,8 @@ void SyncerThread::SetUpdatesSource(bool nudged, NudgeSource nudge_source,
break;
}
}
- vault_.syncer_->set_updates_source(updates_source);
+ vault_.syncer_->set_updates_source(
+ updates_source, vault_.pending_nudge_types_);
}
void SyncerThread::CreateSyncer(const std::string& dirname) {
@@ -658,7 +691,8 @@ int SyncerThread::CalculateSyncWaitTime(int last_interval, int user_idle_ms) {
// Called with mutex_ already locked.
void SyncerThread::NudgeSyncImpl(int milliseconds_from_now,
- NudgeSource source) {
+ NudgeSource source,
+ const syncable::ModelTypeBitSet& model_types) {
// TODO(sync): Add the option to reset the backoff state machine.
// This is needed so nudges that are a result of the user's desire
// to download updates for a new data type can be satisfied quickly.
@@ -677,6 +711,10 @@ void SyncerThread::NudgeSyncImpl(int milliseconds_from_now,
return;
}
+ // Union the current bitset with any from nudges that may have already
+ // posted (coalesce the nudge datatype information).
+ vault_.pending_nudge_types_ |= model_types;
+
VLOG(1) << "Replacing pending nudge for source " << source
<< " at " << nudge_time.ToInternalValue();
vault_.pending_nudge_source_ = source;
diff --git a/chrome/browser/sync/engine/syncer_thread.h b/chrome/browser/sync/engine/syncer_thread.h
index 60d986e..a7322be 100644
--- a/chrome/browser/sync/engine/syncer_thread.h
+++ b/chrome/browser/sync/engine/syncer_thread.h
@@ -10,6 +10,7 @@
#pragma once
#include <list>
+#include <string>
#include <vector>
#include "base/basictypes.h"
@@ -25,6 +26,7 @@
#endif
#include "chrome/browser/sync/engine/syncer_types.h"
#include "chrome/browser/sync/sessions/sync_session.h"
+#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/common/deprecated/event_sys-inl.h"
class EventListenerHookup;
@@ -43,6 +45,7 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
FRIEND_TEST_ALL_PREFIXES(SyncerThreadTest, CalculatePollingWaitTime);
FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Polling);
FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Nudge);
+ FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithDataTypes);
FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Throttling);
FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, AuthInvalid);
FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Pause);
@@ -127,6 +130,13 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
// from the SyncerThread's controller and will cause a mutex lock.
virtual void NudgeSyncer(int milliseconds_from_now, NudgeSource source);
+ // Same as |NudgeSyncer|, but supports tracking the datatypes that caused
+ // the nudge to occur.
+ virtual void NudgeSyncerWithDataTypes(
+ int milliseconds_from_now,
+ NudgeSource source,
+ const syncable::ModelTypeBitSet& model_type);
+
void SetNotificationsEnabled(bool notifications_enabled);
// Call this when a directory is opened
@@ -185,6 +195,11 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
// could be a pending nudge of type kUnknown, so it's better to
// check pending_nudge_time_.)
NudgeSource pending_nudge_source_;
+
+ // BitSet of the datatypes that have triggered the current nudge
+ // (can be union of various bitsets when multiple nudges are coalesced)
+ syncable::ModelTypeBitSet pending_nudge_types_;
+
// null iff there is no pending nudge.
base::TimeTicks pending_nudge_time_;
@@ -300,7 +315,10 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
// This causes syncer to start syncing ASAP. If the rate of requests is too
// high the request will be silently dropped. mutex_ should be held when
// this is called.
- void NudgeSyncImpl(int milliseconds_from_now, NudgeSource source);
+ void NudgeSyncImpl(
+ int milliseconds_from_now,
+ NudgeSource source,
+ const syncable::ModelTypeBitSet& model_types);
#if defined(OS_LINUX)
// On Linux, we need this information in order to query idle time.
diff --git a/chrome/browser/sync/engine/syncer_thread_unittest.cc b/chrome/browser/sync/engine/syncer_thread_unittest.cc
index bcce98a..a5fcc8f 100644
--- a/chrome/browser/sync/engine/syncer_thread_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread_unittest.cc
@@ -697,6 +697,36 @@ TEST_F(SyncerThreadWithSyncerTest, Nudge) {
EXPECT_TRUE(syncer_thread()->Stop(2000));
}
+TEST_F(SyncerThreadWithSyncerTest, NudgeWithDataTypes) {
+ SyncShareIntercept interceptor;
+ connection()->SetMidCommitObserver(&interceptor);
+ // We don't want a poll to happen during this test (except the first one).
+ PreventThreadFromPolling();
+ EXPECT_TRUE(syncer_thread()->Start());
+ metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
+ const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
+ interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
+
+ EXPECT_EQ(static_cast<unsigned int>(1),
+ interceptor.times_sync_occured().size());
+ // The SyncerThread should be waiting for the poll now. Nudge it to sync
+ // immediately (5ms).
+ syncable::ModelTypeBitSet model_types;
+ model_types[syncable::BOOKMARKS] = true;
+ syncer_thread()->NudgeSyncerWithDataTypes(5,
+ SyncerThread::kUnknown,
+ model_types);
+ EXPECT_EQ(model_types, syncer_thread()->vault_.pending_nudge_types_);
+ interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1));
+ EXPECT_EQ(static_cast<unsigned int>(2),
+ interceptor.times_sync_occured().size());
+ EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.none());
+
+ // SyncerThread should be waiting again. Signal it to stop.
+ EXPECT_TRUE(syncer_thread()->Stop(2000));
+}
+
TEST_F(SyncerThreadWithSyncerTest, Throttling) {
SyncShareIntercept interceptor;
connection()->SetMidCommitObserver(&interceptor);
diff --git a/chrome/browser/sync/notifier/server_notifier_thread.cc b/chrome/browser/sync/notifier/server_notifier_thread.cc
index 53aadb0..ede1a47 100644
--- a/chrome/browser/sync/notifier/server_notifier_thread.cc
+++ b/chrome/browser/sync/notifier/server_notifier_thread.cc
@@ -72,17 +72,22 @@ void ServerNotifierThread::OnInvalidate(syncable::ModelType model_type) {
// needed anymore.
VLOG(1) << "OnInvalidate: " << ((model_type == syncable::UNSPECIFIED) ?
"UNKNOWN" : syncable::ModelTypeToString(model_type));
- // TODO(akalin): Signal notification only for the invalidated types.
- // TODO(akalin): Fill this in with something meaningful.
+
+ syncable::ModelTypeBitSet model_types;
+ model_types[model_type] = true;
IncomingNotificationData notification_data;
+ notification_data.service_specific_data = model_types.to_string();
observers_->Notify(&Observer::OnIncomingNotification, notification_data);
}
void ServerNotifierThread::OnInvalidateAll() {
DCHECK_EQ(MessageLoop::current(), worker_message_loop());
VLOG(1) << "OnInvalidateAll";
- // TODO(akalin): Fill this in with something meaningful.
+
+ syncable::ModelTypeBitSet model_types;
+ model_types.set(); // InvalidateAll, so set all datatypes to true.
IncomingNotificationData notification_data;
+ notification_data.service_specific_data = model_types.to_string();
observers_->Notify(&Observer::OnIncomingNotification, notification_data);
}
diff --git a/chrome/browser/sync/sessions/sync_session.cc b/chrome/browser/sync/sessions/sync_session.cc
index a861b2c..831eae6 100644
--- a/chrome/browser/sync/sessions/sync_session.cc
+++ b/chrome/browser/sync/sessions/sync_session.cc
@@ -11,10 +11,10 @@ namespace sessions {
SyncSession::SyncSession(SyncSessionContext* context, Delegate* delegate)
: context_(context),
- source_(sync_pb::GetUpdatesCallerInfo::UNKNOWN),
+ source_(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
+ syncable::ModelTypeBitSet()),
write_transaction_(NULL),
delegate_(delegate) {
-
context_->registrar()->GetWorkers(
const_cast<std::vector<ModelSafeWorker*>*>(&workers_));
context_->registrar()->GetModelSafeRoutingInfo(
@@ -56,10 +56,10 @@ SyncSessionSnapshot SyncSession::TakeSnapshot() const {
status_controller_->did_commit_items());
}
-sync_pb::GetUpdatesCallerInfo::GetUpdatesSource
- SyncSession::TestAndSetSource() {
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource old_source = source_;
- set_source(sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION);
+SyncSourceInfo SyncSession::TestAndSetSource() {
+ SyncSourceInfo old_source = source_;
+ set_source(sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
+ source_.second);
return old_source;
}
diff --git a/chrome/browser/sync/sessions/sync_session.h b/chrome/browser/sync/sessions/sync_session.h
index 568c1f4..f90b6dd 100644
--- a/chrome/browser/sync/sessions/sync_session.h
+++ b/chrome/browser/sync/sessions/sync_session.h
@@ -15,6 +15,7 @@
#define CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSION_H_
#pragma once
+#include <utility>
#include <vector>
#include "base/basictypes.h"
@@ -34,6 +35,8 @@ namespace browser_sync {
class ModelSafeWorker;
namespace sessions {
+typedef std::pair<sync_pb::GetUpdatesCallerInfo::GetUpdatesSource,
+ syncable::ModelTypeBitSet> SyncSourceInfo;
class SyncSession {
public:
@@ -101,10 +104,14 @@ class SyncSession {
// Volatile reader for the source member of the sync session object. The
// value is set to the SYNC_CYCLE_CONTINUATION value to signal that it has
// been read.
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource TestAndSetSource();
- void set_source(sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) {
+ SyncSourceInfo TestAndSetSource();
+ void set_source(SyncSourceInfo source) {
source_ = source;
}
+ void set_source(sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+ syncable::ModelTypeBitSet model_types) {
+ source_ = SyncSourceInfo(source, model_types);
+ }
const std::vector<ModelSafeWorker*>& workers() const { return workers_; }
const ModelSafeRoutingInfo& routing_info() const { return routing_info_; }
@@ -119,7 +126,7 @@ class SyncSession {
SyncSessionContext* const context_;
// The source for initiating this sync session.
- sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source_;
+ SyncSourceInfo source_;
// Information about extensions activity since the last successful commit.
ExtensionsActivityMonitor::Records extensions_activity_;
diff --git a/chrome/browser/sync/syncable/model_type.cc b/chrome/browser/sync/syncable/model_type.cc
index 2d17ebc..a765856 100644
--- a/chrome/browser/sync/syncable/model_type.cc
+++ b/chrome/browser/sync/syncable/model_type.cc
@@ -4,6 +4,9 @@
#include "chrome/browser/sync/syncable/model_type.h"
+#include <sstream>
+
+#include "base/metrics/histogram.h"
#include "chrome/browser/sync/engine/syncproto.h"
#include "chrome/browser/sync/protocol/app_specifics.pb.h"
#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
@@ -177,6 +180,73 @@ ModelType ModelTypeFromString(const std::string& model_type_string) {
return UNSPECIFIED;
}
+bool ModelTypeBitSetFromString(
+ const std::string& model_type_bitset_string,
+ ModelTypeBitSet* model_types) {
+ if (model_type_bitset_string.length() != MODEL_TYPE_COUNT) {
+ return false;
+ }
+
+ std::istringstream iss(model_type_bitset_string);
+ iss >> *model_types;
+ return iss.eof();
+}
+
+// For now, this just implements UMA_HISTOGRAM_LONG_TIMES. This can be adjusted
+// if we feel the min, max, or bucket count amount are not appropriate.
+#define SYNC_FREQ_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES( \
+ name, time, base::TimeDelta::FromMilliseconds(1), \
+ base::TimeDelta::FromHours(1), 50)
+
+void PostTimeToTypeHistogram(ModelType model_type, base::TimeDelta time) {
+ switch (model_type) {
+ case BOOKMARKS: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqBookmarks", time);
+ return;
+ }
+ case PREFERENCES: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqPreferences", time);
+ return;
+ }
+ case PASSWORDS: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqPasswords", time);
+ return;
+ }
+ case AUTOFILL: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqAutofill", time);
+ return;
+ }
+ case THEMES: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqThemes", time);
+ return;
+ }
+ case TYPED_URLS: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqTypedUrls", time);
+ return;
+ }
+ case EXTENSIONS: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqExtensions", time);
+ return;
+ }
+ case NIGORI: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqNigori", time);
+ return;
+ }
+ case SESSIONS: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqSessions", time);
+ return;
+ }
+ case APPS: {
+ SYNC_FREQ_HISTOGRAM("Sync.FreqApps", time);
+ return;
+ }
+ default:
+ LOG(ERROR) << "No known extension for model type.";
+ }
+}
+
+#undef SYNC_FREQ_HISTOGRAM
+
// TODO(akalin): Figure out a better way to do these mappings.
namespace {
diff --git a/chrome/browser/sync/syncable/model_type.h b/chrome/browser/sync/syncable/model_type.h
index c619b7e..2831bd2 100644
--- a/chrome/browser/sync/syncable/model_type.h
+++ b/chrome/browser/sync/syncable/model_type.h
@@ -15,6 +15,7 @@
#include <string>
#include "base/logging.h"
+#include "base/time.h"
namespace sync_pb {
class EntitySpecifics;
@@ -95,6 +96,16 @@ std::string ModelTypeToString(ModelType model_type);
// Returns the ModelType corresponding to the name |model_type_string|.
ModelType ModelTypeFromString(const std::string& model_type_string);
+// Converts a string into a model type bitset. If successful, returns true. If
+// failed to parse string, returns false and model_types is unspecified.
+bool ModelTypeBitSetFromString(
+ const std::string& model_type_bitset_string,
+ ModelTypeBitSet* model_types);
+
+// Posts timedeltas to histogram of datatypes. Allows tracking of the frequency
+// at which datatypes cause syncs.
+void PostTimeToTypeHistogram(ModelType model_type, base::TimeDelta time);
+
// Convert a real model type to a notification type (used for
// subscribing to server-issued notifications). Returns true iff
// |model_type| was a real model type and |notification_type| was