Home | History | Annotate | Download | only in notifier
      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