1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef SYNC_NOTIFIER_ACK_TRACKER_H_ 6 #define SYNC_NOTIFIER_ACK_TRACKER_H_ 7 8 #include <map> 9 10 #include "base/basictypes.h" 11 #include "base/callback_forward.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/threading/thread_checker.h" 14 #include "base/time/time.h" 15 #include "base/timer/timer.h" 16 #include "net/base/backoff_entry.h" 17 #include "sync/base/sync_export.h" 18 #include "sync/notifier/invalidation_util.h" 19 20 namespace base { 21 class TickClock; 22 } // namespace base 23 24 namespace syncer { 25 26 // A simple class that tracks sets of object IDs that have not yet been 27 // acknowledged. Internally, it manages timeouts for the tracked object IDs and 28 // periodically triggers a callback for each timeout period. The timeout is a 29 // simple exponentially increasing time that starts at 60 seconds and is capped 30 // at 600 seconds. 31 class SYNC_EXPORT_PRIVATE AckTracker { 32 public: 33 class SYNC_EXPORT_PRIVATE Delegate { 34 public: 35 virtual ~Delegate(); 36 37 // |ids| contains all object IDs that have timed out in this time interval. 38 virtual void OnTimeout(const ObjectIdSet& ids) = 0; 39 }; 40 41 typedef base::Callback<scoped_ptr<net::BackoffEntry>( 42 const net::BackoffEntry::Policy* const)> CreateBackoffEntryCallback; 43 44 AckTracker(base::TickClock* tick_clock, Delegate* delegate); 45 ~AckTracker(); 46 47 // Equivalent to calling Ack() on all currently registered object IDs. 48 void Clear(); 49 50 // Starts tracking timeouts for |ids|. Timeouts will be triggered for each 51 // object ID until it is acknowledged. Note that no de-duplication is 52 // performed; calling Track() twice on the same set of ids will result in two 53 // different timeouts being triggered for those ids. 54 void Track(const ObjectIdSet& ids); 55 // Marks a set of |ids| as acknowledged. 56 void Ack(const ObjectIdSet& ids); 57 58 // Testing methods. 59 void SetCreateBackoffEntryCallbackForTest( 60 const CreateBackoffEntryCallback& create_backoff_entry_callback); 61 // Returns true iff there are no timeouts scheduled to occur before |now|. 62 // Used in testing to make sure we don't have timeouts set to expire before 63 // when they should. 64 bool TriggerTimeoutAtForTest(base::TimeTicks now); 65 bool IsQueueEmptyForTest() const; 66 const base::Timer& GetTimerForTest() const; 67 68 private: 69 struct Entry { 70 Entry(scoped_ptr<net::BackoffEntry> backoff, const ObjectIdSet& ids); 71 ~Entry(); 72 73 scoped_ptr<net::BackoffEntry> backoff; 74 ObjectIdSet ids; 75 76 private: 77 DISALLOW_COPY_AND_ASSIGN(Entry); 78 }; 79 80 void NudgeTimer(); 81 void OnTimeout(); 82 void OnTimeoutAt(base::TimeTicks now); 83 84 static scoped_ptr<net::BackoffEntry> DefaultCreateBackoffEntryStrategy( 85 const net::BackoffEntry::Policy* const policy); 86 87 // Used for testing purposes. 88 CreateBackoffEntryCallback create_backoff_entry_callback_; 89 90 base::TickClock* const tick_clock_; 91 92 Delegate* const delegate_; 93 94 base::OneShotTimer<AckTracker> timer_; 95 // The time that the timer should fire at. We use this to determine if we need 96 // to start or update |timer_| in NudgeTimer(). We can't simply use 97 // timer_.desired_run_time() for this purpose because it always uses 98 // base::TimeTicks::Now() as a reference point when Timer::Start() is called, 99 // while NudgeTimer() needs a fixed reference point to avoid unnecessarily 100 // updating the timer. 101 base::TimeTicks desired_run_time_; 102 std::multimap<base::TimeTicks, Entry*> queue_; 103 104 base::ThreadChecker thread_checker_; 105 106 DISALLOW_COPY_AND_ASSIGN(AckTracker); 107 }; 108 109 } // namespace syncer 110 111 #endif // SYNC_NOTIFIER_ACK_TRACKER_H_ 112