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

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

Issue 6182004: [SYNC] Refactor SyncSourceInfo and add support in chrome invalidation client ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Added util functions Created 9 years, 11 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 | Annotate | Revision Log
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/syncer_thread.h" 5 #include "chrome/browser/sync/engine/syncer_thread.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map>
9 #include <queue> 8 #include <queue>
9 #include <string>
10 #include <vector>
10 11
11 #include "base/rand_util.h" 12 #include "base/rand_util.h"
12 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 13 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
13 #include "build/build_config.h" 14 #include "build/build_config.h"
14 #include "chrome/browser/sync/engine/model_safe_worker.h" 15 #include "chrome/browser/sync/engine/model_safe_worker.h"
15 #include "chrome/browser/sync/engine/net/server_connection_manager.h" 16 #include "chrome/browser/sync/engine/net/server_connection_manager.h"
16 #include "chrome/browser/sync/engine/syncer.h" 17 #include "chrome/browser/sync/engine/syncer.h"
17 #include "chrome/browser/sync/sessions/sync_session.h" 18 #include "chrome/browser/sync/sessions/sync_session.h"
18 #include "jingle/notifier/listener/notification_constants.h" 19 #include "jingle/notifier/listener/notification_constants.h"
19 20
20 #if defined(OS_MACOSX) 21 #if defined(OS_MACOSX)
21 #include <CoreFoundation/CFNumber.h> 22 #include <CoreFoundation/CFNumber.h>
22 #include <IOKit/IOTypes.h> 23 #include <IOKit/IOTypes.h>
23 #include <IOKit/IOKitLib.h> 24 #include <IOKit/IOKitLib.h>
24 #endif 25 #endif
25 26
26 using std::priority_queue; 27 using std::priority_queue;
27 using std::min; 28 using std::min;
28 using base::Time; 29 using base::Time;
29 using base::TimeDelta; 30 using base::TimeDelta;
30 using base::TimeTicks; 31 using base::TimeTicks;
31 32
32 namespace browser_sync { 33 namespace browser_sync {
33 34
35 using sessions::ModelTypeMap;
34 using sessions::SyncSession; 36 using sessions::SyncSession;
35 using sessions::SyncSessionSnapshot; 37 using sessions::SyncSessionSnapshot;
36 using sessions::SyncSourceInfo; 38 using sessions::SyncSourceInfo;
37 39
38 // We use high values here to ensure that failure to receive poll updates from 40 // We use high values here to ensure that failure to receive poll updates from
39 // the server doesn't result in rapid-fire polling from the client due to low 41 // the server doesn't result in rapid-fire polling from the client due to low
40 // local limits. 42 // local limits.
41 const int SyncerThread::kDefaultShortPollIntervalSeconds = 3600 * 8; 43 const int SyncerThread::kDefaultShortPollIntervalSeconds = 3600 * 8;
42 const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600 * 12; 44 const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600 * 12;
43 45
44 // TODO(tim): This is used to regulate the short poll (when notifications are 46 // TODO(tim): This is used to regulate the short poll (when notifications are
45 // disabled) based on user idle time. If it is set to a smaller value than 47 // disabled) based on user idle time. If it is set to a smaller value than
46 // the short poll interval, it basically does nothing; for now, this is what 48 // the short poll interval, it basically does nothing; for now, this is what
47 // we want and allows stronger control over the poll rate from the server. We 49 // we want and allows stronger control over the poll rate from the server. We
48 // should probably re-visit this code later and figure out if user idle time 50 // should probably re-visit this code later and figure out if user idle time
49 // is really something we want and make sure it works, if it is. 51 // is really something we want and make sure it works, if it is.
50 const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000; 52 const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000;
51 53
52 // Backoff interval randomization factor. 54 // Backoff interval randomization factor.
53 static const int kBackoffRandomizationFactor = 2; 55 static const int kBackoffRandomizationFactor = 2;
54 56
55 const int SyncerThread::kMaxBackoffSeconds = 60 * 60 * 4; // 4 hours. 57 const int SyncerThread::kMaxBackoffSeconds = 60 * 60 * 4; // 4 hours.
56 58
59 void SyncerThread::NudgeSyncerWithPayloads(
60 int milliseconds_from_now,
61 NudgeSource source,
62 const ModelTypeMap& model_types_with_payloads) {
63 base::AutoLock lock(lock_);
64 if (vault_.syncer_ == NULL) {
65 return;
66 }
67
68 NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
69 }
70
57 void SyncerThread::NudgeSyncerWithDataTypes( 71 void SyncerThread::NudgeSyncerWithDataTypes(
58 int milliseconds_from_now, 72 int milliseconds_from_now,
59 NudgeSource source, 73 NudgeSource source,
60 const syncable::ModelTypeBitSet& model_types) { 74 const syncable::ModelTypeBitSet& model_types) {
61 base::AutoLock lock(lock_); 75 base::AutoLock lock(lock_);
62 if (vault_.syncer_ == NULL) { 76 if (vault_.syncer_ == NULL) {
63 return; 77 return;
64 } 78 }
65 79
66 NudgeSyncImpl(milliseconds_from_now, source, model_types); 80 ModelTypeMap model_types_with_payloads;
81 sessions::BuildModelTypeMapFromModelTypeBitSet(model_types,
82 std::string(),
83 &model_types_with_payloads);
84 NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
67 } 85 }
68 86
69 void SyncerThread::NudgeSyncer( 87 void SyncerThread::NudgeSyncer(
70 int milliseconds_from_now, 88 int milliseconds_from_now,
71 NudgeSource source) { 89 NudgeSource source) {
72 base::AutoLock lock(lock_); 90 base::AutoLock lock(lock_);
73 if (vault_.syncer_ == NULL) { 91 if (vault_.syncer_ == NULL) {
74 return; 92 return;
75 } 93 }
76 94
77 syncable::ModelTypeBitSet model_types; // All false by default. 95 // Set all enabled datatypes.
78 NudgeSyncImpl(milliseconds_from_now, source, model_types); 96 ModelTypeMap model_types_with_payloads;
97 ModelSafeRoutingInfo routes;
98 session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
99 sessions::BuildModelTypeMapFromModelSafeRoutingInfo(
100 routes,
101 std::string(),
102 &model_types_with_payloads);
103 NudgeSyncImpl(milliseconds_from_now, source, model_types_with_payloads);
79 } 104 }
80 105
81 SyncerThread::SyncerThread(sessions::SyncSessionContext* context) 106 SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
82 : thread_main_started_(false, false), 107 : thread_main_started_(false, false),
83 thread_("SyncEngine_SyncerThread"), 108 thread_("SyncEngine_SyncerThread"),
84 vault_field_changed_(&lock_), 109 vault_field_changed_(&lock_),
85 conn_mgr_hookup_(NULL), 110 conn_mgr_hookup_(NULL),
86 syncer_short_poll_interval_seconds_(kDefaultShortPollIntervalSeconds), 111 syncer_short_poll_interval_seconds_(kDefaultShortPollIntervalSeconds),
87 syncer_long_poll_interval_seconds_(kDefaultLongPollIntervalSeconds), 112 syncer_long_poll_interval_seconds_(kDefaultLongPollIntervalSeconds),
88 syncer_polling_interval_(kDefaultShortPollIntervalSeconds), 113 syncer_polling_interval_(kDefaultShortPollIntervalSeconds),
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // event. This will also update the source of the following SyncMain call. 360 // event. This will also update the source of the following SyncMain call.
336 VLOG(1) << "Calling Sync Main at time " << Time::Now().ToInternalValue(); 361 VLOG(1) << "Calling Sync Main at time " << Time::Now().ToInternalValue();
337 bool nudged = false; 362 bool nudged = false;
338 scoped_ptr<SyncSession> session; 363 scoped_ptr<SyncSession> session;
339 session.reset(SyncMain(vault_.syncer_, 364 session.reset(SyncMain(vault_.syncer_,
340 throttled, continue_sync_cycle, &initial_sync_for_thread, &nudged)); 365 throttled, continue_sync_cycle, &initial_sync_for_thread, &nudged));
341 366
342 // Update timing information for how often these datatypes are triggering 367 // Update timing information for how often these datatypes are triggering
343 // nudges. 368 // nudges.
344 base::TimeTicks now = TimeTicks::Now(); 369 base::TimeTicks now = TimeTicks::Now();
345 for (size_t i = syncable::FIRST_REAL_MODEL_TYPE; 370 if (!last_sync_time.is_null()) {
346 i < session->source().second.size(); 371 ModelTypeMap::const_iterator iter;
347 ++i) { 372 for (iter = session->source().types.begin();
348 if (session->source().second[i]) { 373 iter != session->source().types.end();
349 syncable::PostTimeToTypeHistogram(syncable::ModelType(i), 374 ++iter) {
375 syncable::PostTimeToTypeHistogram(iter->first,
350 now - last_sync_time); 376 now - last_sync_time);
351 } 377 }
352 } 378 }
353 379
354 last_sync_time = now; 380 last_sync_time = now;
355 381
356 VLOG(1) << "Updating the next polling time after SyncMain"; 382 VLOG(1) << "Updating the next polling time after SyncMain";
357 vault_.current_wait_interval_ = CalculatePollingWaitTime( 383 vault_.current_wait_interval_ = CalculatePollingWaitTime(
358 static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()), 384 static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()),
359 &user_idle_milliseconds, &continue_sync_cycle, nudged); 385 &user_idle_milliseconds, &continue_sync_cycle, nudged);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 VLOG(1) << "Done calling SyncShare."; 593 VLOG(1) << "Done calling SyncShare.";
568 return session.release(); 594 return session.release();
569 } 595 }
570 596
571 SyncSourceInfo SyncerThread::GetAndResetNudgeSource(bool was_throttled, 597 SyncSourceInfo SyncerThread::GetAndResetNudgeSource(bool was_throttled,
572 bool continue_sync_cycle, 598 bool continue_sync_cycle,
573 bool* initial_sync, 599 bool* initial_sync,
574 bool* was_nudged) { 600 bool* was_nudged) {
575 bool nudged = false; 601 bool nudged = false;
576 NudgeSource nudge_source = kUnknown; 602 NudgeSource nudge_source = kUnknown;
577 syncable::ModelTypeBitSet model_types; 603 ModelTypeMap model_types_with_payloads;
578 // Has the previous sync cycle completed? 604 // Has the previous sync cycle completed?
579 if (continue_sync_cycle) 605 if (continue_sync_cycle)
580 nudge_source = kContinuation; 606 nudge_source = kContinuation;
581 // Update the nudge source if a new nudge has come through during the 607 // Update the nudge source if a new nudge has come through during the
582 // previous sync cycle. 608 // previous sync cycle.
583 if (!vault_.pending_nudge_time_.is_null()) { 609 if (!vault_.pending_nudge_time_.is_null()) {
584 if (!was_throttled) { 610 if (!was_throttled) {
585 nudge_source = vault_.pending_nudge_source_; 611 nudge_source = vault_.pending_nudge_source_;
586 model_types = vault_.pending_nudge_types_; 612 model_types_with_payloads = vault_.pending_nudge_types_;
587 nudged = true; 613 nudged = true;
588 } 614 }
589 VLOG(1) << "Clearing pending nudge from " << vault_.pending_nudge_source_ 615 VLOG(1) << "Clearing pending nudge from " << vault_.pending_nudge_source_
590 << " at tick " << vault_.pending_nudge_time_.ToInternalValue(); 616 << " at tick " << vault_.pending_nudge_time_.ToInternalValue();
591 vault_.pending_nudge_source_ = kUnknown; 617 vault_.pending_nudge_source_ = kUnknown;
592 vault_.pending_nudge_types_.reset(); 618 vault_.pending_nudge_types_.clear();
593 vault_.pending_nudge_time_ = base::TimeTicks(); 619 vault_.pending_nudge_time_ = base::TimeTicks();
594 } 620 }
595 621
596 *was_nudged = nudged; 622 *was_nudged = nudged;
597 623
598 // TODO(tim): Hack for bug 64136 to correctly tag continuations that result 624 // TODO(tim): Hack for bug 64136 to correctly tag continuations that result
599 // from syncer having more work to do. This will be handled properly with 625 // from syncer having more work to do. This will be handled properly with
600 // the message loop based syncer thread, bug 26339. 626 // the message loop based syncer thread, bug 26339.
601 return MakeSyncSourceInfo(nudged || nudge_source == kContinuation, 627 return MakeSyncSourceInfo(nudged || nudge_source == kContinuation,
602 nudge_source, model_types, initial_sync); 628 nudge_source, model_types_with_payloads, initial_sync);
603 } 629 }
604 630
605 SyncSourceInfo SyncerThread::MakeSyncSourceInfo(bool nudged, 631 SyncSourceInfo SyncerThread::MakeSyncSourceInfo(bool nudged,
606 NudgeSource nudge_source, const syncable::ModelTypeBitSet& nudge_types, 632 NudgeSource nudge_source,
633 const ModelTypeMap& model_types_with_payloads,
607 bool* initial_sync) { 634 bool* initial_sync) {
608 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source = 635 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source =
609 sync_pb::GetUpdatesCallerInfo::UNKNOWN; 636 sync_pb::GetUpdatesCallerInfo::UNKNOWN;
610 if (*initial_sync) { 637 if (*initial_sync) {
611 updates_source = sync_pb::GetUpdatesCallerInfo::FIRST_UPDATE; 638 updates_source = sync_pb::GetUpdatesCallerInfo::FIRST_UPDATE;
612 *initial_sync = false; 639 *initial_sync = false;
613 } else if (!nudged) { 640 } else if (!nudged) {
614 updates_source = sync_pb::GetUpdatesCallerInfo::PERIODIC; 641 updates_source = sync_pb::GetUpdatesCallerInfo::PERIODIC;
615 } else { 642 } else {
616 switch (nudge_source) { 643 switch (nudge_source) {
617 case kNotification: 644 case kNotification:
618 updates_source = sync_pb::GetUpdatesCallerInfo::NOTIFICATION; 645 updates_source = sync_pb::GetUpdatesCallerInfo::NOTIFICATION;
619 break; 646 break;
620 case kLocal: 647 case kLocal:
621 updates_source = sync_pb::GetUpdatesCallerInfo::LOCAL; 648 updates_source = sync_pb::GetUpdatesCallerInfo::LOCAL;
622 break; 649 break;
623 case kContinuation: 650 case kContinuation:
624 updates_source = sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; 651 updates_source = sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION;
625 break; 652 break;
626 case kClearPrivateData: 653 case kClearPrivateData:
627 updates_source = sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA; 654 updates_source = sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA;
628 break; 655 break;
629 case kUnknown: 656 case kUnknown:
630 default: 657 default:
631 updates_source = sync_pb::GetUpdatesCallerInfo::UNKNOWN; 658 updates_source = sync_pb::GetUpdatesCallerInfo::UNKNOWN;
632 break; 659 break;
633 } 660 }
634 } 661 }
635 return SyncSourceInfo(updates_source, nudge_types); 662
663 ModelTypeMap sync_source_types;
664 if (model_types_with_payloads.empty()) {
665 // No datatypes requested. This must be a poll so set all enabled datatypes.
666 ModelSafeRoutingInfo routes;
667 session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
668 sessions::BuildModelTypeMapFromModelSafeRoutingInfo(routes,
669 std::string(),
670 &sync_source_types);
671 } else {
672 sync_source_types = model_types_with_payloads;
673 }
674
675 return SyncSourceInfo(updates_source, sync_source_types);
636 } 676 }
637 677
638 void SyncerThread::CreateSyncer(const std::string& dirname) { 678 void SyncerThread::CreateSyncer(const std::string& dirname) {
639 base::AutoLock lock(lock_); 679 base::AutoLock lock(lock_);
640 VLOG(1) << "Creating syncer up for: " << dirname; 680 VLOG(1) << "Creating syncer up for: " << dirname;
641 // The underlying database structure is ready, and we should create 681 // The underlying database structure is ready, and we should create
642 // the syncer. 682 // the syncer.
643 CHECK(vault_.syncer_ == NULL); 683 CHECK(vault_.syncer_ == NULL);
644 session_context_->set_account_name(dirname); 684 session_context_->set_account_name(dirname);
645 vault_.syncer_ = new Syncer(); 685 vault_.syncer_ = new Syncer();
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 // rate. 767 // rate.
728 if (idle >= kPollBackoffThresholdMultiplier * syncer_polling_interval_ms) { 768 if (idle >= kPollBackoffThresholdMultiplier * syncer_polling_interval_ms) {
729 next_wait = std::min(GetRecommendedDelaySeconds( 769 next_wait = std::min(GetRecommendedDelaySeconds(
730 last_interval / 1000), syncer_max_interval_ / 1000) * 1000; 770 last_interval / 1000), syncer_max_interval_ / 1000) * 1000;
731 } 771 }
732 772
733 return next_wait; 773 return next_wait;
734 } 774 }
735 775
736 // Called with mutex_ already locked. 776 // Called with mutex_ already locked.
737 void SyncerThread::NudgeSyncImpl(int milliseconds_from_now, 777 void SyncerThread::NudgeSyncImpl(
738 NudgeSource source, 778 int milliseconds_from_now,
739 const syncable::ModelTypeBitSet& model_types) { 779 NudgeSource source,
780 const ModelTypeMap& model_types_with_payloads) {
740 // TODO(sync): Add the option to reset the backoff state machine. 781 // TODO(sync): Add the option to reset the backoff state machine.
741 // This is needed so nudges that are a result of the user's desire 782 // This is needed so nudges that are a result of the user's desire
742 // to download updates for a new data type can be satisfied quickly. 783 // to download updates for a new data type can be satisfied quickly.
743 if (vault_.current_wait_interval_.mode == WaitInterval::THROTTLED || 784 if (vault_.current_wait_interval_.mode == WaitInterval::THROTTLED ||
744 vault_.current_wait_interval_.had_nudge_during_backoff) { 785 vault_.current_wait_interval_.had_nudge_during_backoff) {
745 // Drop nudges on the floor if we've already had one since starting this 786 // Drop nudges on the floor if we've already had one since starting this
746 // stage of exponential backoff or we are throttled. 787 // stage of exponential backoff or we are throttled.
747 return; 788 return;
748 } 789 }
749 790
750 // Union the current bitset with any from nudges that may have already 791 // Union the current ModelTypeMap with any from nudges that may have already
751 // posted (coalesce the nudge datatype information). 792 // posted (coalesce the nudge datatype information).
752 // TODO(tim): It seems weird to do this if the sources don't match up (e.g. 793 // TODO(tim): It seems weird to do this if the sources don't match up (e.g.
753 // if pending_source is kLocal and |source| is kClearPrivateData). 794 // if pending_source is kLocal and |source| is kClearPrivateData).
754 vault_.pending_nudge_types_ |= model_types; 795 for (ModelTypeMap::const_iterator i =
akalin 2011/01/24 22:17:29 I think this logic is tricky enough that it should
Nicolas Zea 2011/01/25 00:29:14 Done.
796 model_types_with_payloads.begin();
797 i != model_types_with_payloads.end();
798 ++i) {
799 if (vault_.pending_nudge_types_.count(i->first) == 0) {
800 // If this datatype isn't already in our map, add it.
801 vault_.pending_nudge_types_[i->first] = i->second;
802 } else if (i->second.length() > 0) {
803 // If it is, we only overwrite the payload if the new one is non-empty.
804 vault_.pending_nudge_types_[i->first] = i->second;
805 }
806 }
755 807
756 const TimeTicks nudge_time = TimeTicks::Now() + 808 const TimeTicks nudge_time = TimeTicks::Now() +
757 TimeDelta::FromMilliseconds(milliseconds_from_now); 809 TimeDelta::FromMilliseconds(milliseconds_from_now);
758 if (nudge_time <= vault_.pending_nudge_time_) { 810 if (nudge_time <= vault_.pending_nudge_time_) {
759 VLOG(1) << "Nudge for source " << source 811 VLOG(1) << "Nudge for source " << source
760 << " dropped due to existing later pending nudge"; 812 << " dropped due to existing later pending nudge";
761 return; 813 return;
762 } 814 }
763 815
764 VLOG(1) << "Replacing pending nudge for source " << source 816 VLOG(1) << "Replacing pending nudge for source " << source
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 was_logged = true; 894 was_logged = true;
843 VLOG(1) << "UserIdleTime unimplemented on this platform, synchronization " 895 VLOG(1) << "UserIdleTime unimplemented on this platform, synchronization "
844 "will not throttle when user idle"; 896 "will not throttle when user idle";
845 } 897 }
846 #endif 898 #endif
847 899
848 return 0; 900 return 0;
849 } 901 }
850 902
851 } // namespace browser_sync 903 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698