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 // A class that manages the registration of types for server-issued
      6 // notifications.
      7 
      8 #ifndef SYNC_NOTIFIER_REGISTRATION_MANAGER_H_
      9 #define SYNC_NOTIFIER_REGISTRATION_MANAGER_H_
     10 
     11 #include <map>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/threading/non_thread_safe.h"
     15 #include "base/time/time.h"
     16 #include "base/timer/timer.h"
     17 // For invalidation::InvalidationListener::RegistrationState.
     18 #include "google/cacheinvalidation/include/invalidation-listener.h"
     19 #include "google/cacheinvalidation/include/types.h"
     20 #include "sync/base/sync_export.h"
     21 #include "sync/notifier/invalidation_util.h"
     22 
     23 namespace syncer {
     24 
     25 using ::invalidation::InvalidationListener;
     26 
     27 // Manages the details of registering types for invalidation.
     28 // Implements exponential backoff for repeated registration attempts
     29 // to the invalidation client.
     30 //
     31 // TODO(akalin): Consolidate exponential backoff code.  Other
     32 // implementations include the syncer thread (both versions) and XMPP
     33 // retries.  The most sophisticated one is URLRequestThrottler; making
     34 // that generic should work for everyone.
     35 class SYNC_EXPORT_PRIVATE RegistrationManager : public base::NonThreadSafe {
     36  public:
     37   // Constants for exponential backoff (used by tests).
     38   static const int kInitialRegistrationDelaySeconds;
     39   static const int kRegistrationDelayExponent;
     40   static const double kRegistrationDelayMaxJitter;
     41   static const int kMinRegistrationDelaySeconds;
     42   static const int kMaxRegistrationDelaySeconds;
     43 
     44   // Types used by testing functions.
     45   struct PendingRegistrationInfo {
     46     PendingRegistrationInfo();
     47 
     48     // Last time a registration request was actually sent.
     49     base::Time last_registration_request;
     50     // Time the registration was attempted.
     51     base::Time registration_attempt;
     52     // The calculated delay of the pending registration (which may be
     53     // negative).
     54     base::TimeDelta delay;
     55     // The delay of the timer, which should be max(delay, 0).
     56     base::TimeDelta actual_delay;
     57   };
     58   // Map of object IDs with pending registrations to info about the
     59   // pending registration.
     60   typedef std::map<invalidation::ObjectId,
     61                    PendingRegistrationInfo,
     62                    ObjectIdLessThan>
     63       PendingRegistrationMap;
     64 
     65   // Does not take ownership of |invalidation_client_|.
     66   explicit RegistrationManager(
     67       invalidation::InvalidationClient* invalidation_client);
     68 
     69   virtual ~RegistrationManager();
     70 
     71   // Registers all object IDs included in the given set (that are not
     72   // already disabled) and unregisters all other object IDs. The return value is
     73   // the set of IDs that was unregistered.
     74   ObjectIdSet UpdateRegisteredIds(const ObjectIdSet& ids);
     75 
     76   // Marks the registration for the |id| lost and re-registers
     77   // it (unless it's disabled).
     78   void MarkRegistrationLost(const invalidation::ObjectId& id);
     79 
     80   // Marks registrations lost for all enabled object IDs and re-registers them.
     81   void MarkAllRegistrationsLost();
     82 
     83   // Marks the registration for the |id| permanently lost and blocks any future
     84   // registration attempts.
     85   void DisableId(const invalidation::ObjectId& id);
     86 
     87   // Calculate exponential backoff.  |jitter| must be Uniform[-1.0, 1.0].
     88   static double CalculateBackoff(double retry_interval,
     89                                  double initial_retry_interval,
     90                                  double min_retry_interval,
     91                                  double max_retry_interval,
     92                                  double backoff_exponent,
     93                                  double jitter,
     94                                  double max_jitter);
     95 
     96   // The functions below should only be used in tests.
     97 
     98   // Gets all currently registered ids.
     99   ObjectIdSet GetRegisteredIdsForTest() const;
    100 
    101   // Gets all pending registrations and their next min delays.
    102   PendingRegistrationMap GetPendingRegistrationsForTest() const;
    103 
    104   // Run pending registrations immediately.
    105   void FirePendingRegistrationsForTest();
    106 
    107  protected:
    108   // Overrideable for testing purposes.
    109   virtual double GetJitter();
    110 
    111  private:
    112   struct RegistrationStatus {
    113     RegistrationStatus(const invalidation::ObjectId& id,
    114                        RegistrationManager* manager);
    115     ~RegistrationStatus();
    116 
    117     // Calls registration_manager->DoRegister(model_type). (needed by
    118     // |registration_timer|).  Should only be called if |enabled| is
    119     // true.
    120     void DoRegister();
    121 
    122     // Sets |enabled| to false and resets other variables.
    123     void Disable();
    124 
    125     // The object for which this is the status.
    126     const invalidation::ObjectId id;
    127     // The parent registration manager.
    128     RegistrationManager* const registration_manager;
    129 
    130     // Whether this data type should be registered.  Set to false if
    131     // we get a non-transient registration failure.
    132     bool enabled;
    133     // The current registration state.
    134     InvalidationListener::RegistrationState state;
    135     // When we last sent a registration request.
    136     base::Time last_registration_request;
    137     // When we last tried to register.
    138     base::Time last_registration_attempt;
    139     // The calculated delay of any pending registration (which may be
    140     // negative).
    141     base::TimeDelta delay;
    142     // The minimum time to wait until any next registration attempt.
    143     // Increased after each consecutive failure.
    144     base::TimeDelta next_delay;
    145     // The actual timer for registration.
    146     base::OneShotTimer<RegistrationStatus> registration_timer;
    147 
    148     DISALLOW_COPY_AND_ASSIGN(RegistrationStatus);
    149   };
    150   typedef std::map<invalidation::ObjectId,
    151                    RegistrationStatus*,
    152                    ObjectIdLessThan>
    153       RegistrationStatusMap;
    154 
    155   // Does nothing if the given id is disabled.  Otherwise, if
    156   // |is_retry| is not set, registers the given type immediately and
    157   // resets all backoff parameters.  If |is_retry| is set, registers
    158   // the given type at some point in the future and increases the
    159   // delay until the next retry.
    160   void TryRegisterId(const invalidation::ObjectId& id,
    161                      bool is_retry);
    162 
    163   // Registers the given id, which must be valid, immediately.
    164   // Updates |last_registration| in the appropriate
    165   // RegistrationStatus.  Should only be called by
    166   // RegistrationStatus::DoRegister().
    167   void DoRegisterId(const invalidation::ObjectId& id);
    168 
    169   // Unregisters the given object ID.
    170   void UnregisterId(const invalidation::ObjectId& id);
    171 
    172   // Gets all currently registered ids.
    173   ObjectIdSet GetRegisteredIds() const;
    174 
    175   // Returns true iff the given object ID is registered.
    176   bool IsIdRegistered(const invalidation::ObjectId& id) const;
    177 
    178   RegistrationStatusMap registration_statuses_;
    179   // Weak pointer.
    180   invalidation::InvalidationClient* invalidation_client_;
    181 
    182   DISALLOW_COPY_AND_ASSIGN(RegistrationManager);
    183 };
    184 
    185 }  // namespace syncer
    186 
    187 #endif  // SYNC_NOTIFIER_REGISTRATION_MANAGER_H_
    188