payload_state.h revision 6e15aace93982e885181100b2380db7fe7e1278f
1// Copyright (c) 2012 The Chromium OS 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 UPDATE_ENGINE_PAYLOAD_STATE_H_
6#define UPDATE_ENGINE_PAYLOAD_STATE_H_
7
8#include <string>
9#include <vector>
10
11#include <base/time/time.h>
12#include <gtest/gtest_prod.h>  // for FRIEND_TEST
13
14#include "update_engine/metrics.h"
15#include "update_engine/payload_state_interface.h"
16#include "update_engine/prefs_interface.h"
17
18namespace chromeos_update_engine {
19
20class SystemState;
21
22// Encapsulates all the payload state required for download. This includes the
23// state necessary for handling multiple URLs in Omaha response, the backoff
24// state, etc. All state is persisted so that we use the most recently saved
25// value when resuming the update_engine process. All state is also cached in
26// memory so that we ensure we always make progress based on last known good
27// state even when there's any issue in reading/writing from the file system.
28class PayloadState : public PayloadStateInterface {
29 public:
30  PayloadState();
31  virtual ~PayloadState() {}
32
33  // Initializes a payload state object using the given global system state.
34  // It performs the initial loading of all persisted state into memory and
35  // dumps the initial state for debugging purposes.  Note: the other methods
36  // should be called only after calling Initialize on this object.
37  bool Initialize(SystemState* system_state);
38
39  // Implementation of PayloadStateInterface methods.
40  virtual void SetResponse(const OmahaResponse& response);
41  virtual void DownloadComplete();
42  virtual void DownloadProgress(size_t count);
43  virtual void UpdateResumed();
44  virtual void UpdateRestarted();
45  virtual void UpdateSucceeded();
46  virtual void UpdateFailed(ErrorCode error);
47  virtual void ResetUpdateStatus();
48  virtual bool ShouldBackoffDownload();
49  virtual void Rollback();
50  virtual void ExpectRebootInNewVersion(const std::string& target_version_uid);
51  virtual void SetUsingP2PForDownloading(bool value);
52
53  virtual inline std::string GetResponseSignature() {
54    return response_signature_;
55  }
56
57  virtual inline int GetFullPayloadAttemptNumber() {
58    return full_payload_attempt_number_;
59  }
60
61  virtual inline int GetPayloadAttemptNumber() {
62    return payload_attempt_number_;
63  }
64
65  virtual inline std::string GetCurrentUrl() {
66    return candidate_urls_.size() ? candidate_urls_[url_index_] : "";
67  }
68
69  virtual inline uint32_t GetUrlFailureCount() {
70    return url_failure_count_;
71  }
72
73  virtual inline uint32_t GetUrlSwitchCount() {
74    return url_switch_count_;
75  }
76
77  virtual inline int GetNumResponsesSeen() {
78    return num_responses_seen_;
79  }
80
81  virtual inline base::Time GetBackoffExpiryTime() {
82    return backoff_expiry_time_;
83  }
84
85  virtual base::TimeDelta GetUpdateDuration();
86
87  virtual base::TimeDelta GetUpdateDurationUptime();
88
89  virtual inline uint64_t GetCurrentBytesDownloaded(DownloadSource source) {
90    return source < kNumDownloadSources ? current_bytes_downloaded_[source] : 0;
91  }
92
93  virtual inline uint64_t GetTotalBytesDownloaded(DownloadSource source) {
94    return source < kNumDownloadSources ? total_bytes_downloaded_[source] : 0;
95  }
96
97  virtual inline uint32_t GetNumReboots() {
98    return num_reboots_;
99  }
100
101  virtual void UpdateEngineStarted();
102
103  virtual inline std::string GetRollbackVersion() {
104    return rollback_version_;
105  }
106
107  virtual int GetP2PNumAttempts();
108  virtual base::Time GetP2PFirstAttemptTimestamp();
109  virtual void P2PNewAttempt();
110  virtual bool P2PAttemptAllowed();
111
112  virtual bool GetUsingP2PForDownloading() {
113    return using_p2p_for_downloading_;
114  }
115
116 private:
117  enum class AttemptType {
118    kUpdate,
119    kRollback,
120  };
121
122  friend class PayloadStateTest;
123  FRIEND_TEST(PayloadStateTest, RebootAfterUpdateFailedMetric);
124  FRIEND_TEST(PayloadStateTest, RebootAfterUpdateSucceed);
125  FRIEND_TEST(PayloadStateTest, RebootAfterCanceledUpdate);
126  FRIEND_TEST(PayloadStateTest, RollbackVersion);
127  FRIEND_TEST(PayloadStateTest, UpdateSuccessWithWipedPrefs);
128
129  // Helper called when an attempt has begun, is called by
130  // UpdateResumed(), UpdateRestarted() and Rollback().
131  void AttemptStarted(AttemptType attempt_type);
132
133  // Increments the payload attempt number used for metrics.
134  void IncrementPayloadAttemptNumber();
135
136  // Increments the payload attempt number which governs the backoff behavior
137  // at the time of the next update check.
138  void IncrementFullPayloadAttemptNumber();
139
140  // Advances the current URL index to the next available one. If all URLs have
141  // been exhausted during the current payload download attempt (as indicated
142  // by the payload attempt number), then it will increment the payload attempt
143  // number and wrap around again with the first URL in the list. This also
144  // updates the URL switch count, if needed.
145  void IncrementUrlIndex();
146
147  // Increments the failure count of the current URL. If the configured max
148  // failure count is reached for this URL, it advances the current URL index
149  // to the next URL and resets the failure count for that URL.
150  void IncrementFailureCount();
151
152  // Updates the backoff expiry time exponentially based on the current
153  // payload attempt number.
154  void UpdateBackoffExpiryTime();
155
156  // Updates the value of current download source based on the current URL
157  // index. If the download source is not one of the known sources, it's set
158  // to kNumDownloadSources.
159  void UpdateCurrentDownloadSource();
160
161  // Updates the various metrics corresponding with the given number of bytes
162  // that were downloaded recently.
163  void UpdateBytesDownloaded(size_t count);
164
165  // Calculates the PayloadType we're using.
166  PayloadType CalculatePayloadType();
167
168  // Collects and reports the various metrics related to an update attempt.
169  void CollectAndReportAttemptMetrics(ErrorCode code);
170
171  // Persists values related to the UpdateEngine.Attempt.* metrics so
172  // we can identify later if an update attempt ends abnormally.
173  void PersistAttemptMetrics();
174
175  // Clears persistent state previously set using AttemptMetricsPersist().
176  void ClearPersistedAttemptMetrics();
177
178  // Checks if persistent state previously set using AttemptMetricsPersist()
179  // exists and, if so, emits it with |attempt_result| set to
180  // metrics::AttemptResult::kAbnormalTermination.
181  void ReportAndClearPersistedAttemptMetrics();
182
183  // Collects and reports the various metrics related to a successful update.
184  void CollectAndReportSuccessfulUpdateMetrics();
185
186  // Checks if we were expecting to be running in the new version but the
187  // boot into the new version failed for some reason. If that's the case, an
188  // UMA metric is sent reporting the number of attempts the same applied
189  // payload was attempted to reboot. This function is called by UpdateAttempter
190  // every time the update engine starts and there's no reboot pending.
191  void ReportFailedBootIfNeeded();
192
193  // Resets all the persisted state values which are maintained relative to the
194  // current response signature. The response signature itself is not reset.
195  void ResetPersistedState();
196
197  // Resets the appropriate state related to download sources that need to be
198  // reset on a new update.
199  void ResetDownloadSourcesOnNewUpdate();
200
201  // Returns the persisted value from prefs_ for the given key. It also
202  // validates that the value returned is non-negative.
203  int64_t GetPersistedValue(const std::string& key);
204
205  // Calculates the response "signature", which is basically a string composed
206  // of the subset of the fields in the current response that affect the
207  // behavior of the PayloadState.
208  std::string CalculateResponseSignature();
209
210  // Initializes the current response signature from the persisted state.
211  void LoadResponseSignature();
212
213  // Sets the response signature to the given value. Also persists the value
214  // being set so that we resume from the save value in case of a process
215  // restart.
216  void SetResponseSignature(const std::string& response_signature);
217
218  // Initializes the payload attempt number from the persisted state.
219  void LoadPayloadAttemptNumber();
220
221  // Initializes the payload attempt number for full payloads from the persisted
222  // state.
223  void LoadFullPayloadAttemptNumber();
224
225  // Sets the payload attempt number to the given value. Also persists the
226  // value being set so that we resume from the same value in case of a process
227  // restart.
228  void SetPayloadAttemptNumber(int payload_attempt_number);
229
230  // Sets the payload attempt number for full updates to the given value. Also
231  // persists the value being set so that we resume from the same value in case
232  // of a process restart.
233  void SetFullPayloadAttemptNumber(int payload_attempt_number);
234
235  // Initializes the current URL index from the persisted state.
236  void LoadUrlIndex();
237
238  // Sets the current URL index to the given value. Also persists the value
239  // being set so that we resume from the same value in case of a process
240  // restart.
241  void SetUrlIndex(uint32_t url_index);
242
243  // Initializes the current URL's failure count from the persisted stae.
244  void LoadUrlFailureCount();
245
246  // Sets the current URL's failure count to the given value. Also persists the
247  // value being set so that we resume from the same value in case of a process
248  // restart.
249  void SetUrlFailureCount(uint32_t url_failure_count);
250
251  // Sets |url_switch_count_| to the given value and persists the value.
252  void SetUrlSwitchCount(uint32_t url_switch_count);
253
254  // Initializes |url_switch_count_| from the persisted stae.
255  void LoadUrlSwitchCount();
256
257  // Initializes the backoff expiry time from the persisted state.
258  void LoadBackoffExpiryTime();
259
260  // Sets the backoff expiry time to the given value. Also persists the value
261  // being set so that we resume from the same value in case of a process
262  // restart.
263  void SetBackoffExpiryTime(const base::Time& new_time);
264
265  // Initializes |update_timestamp_start_| from the persisted state.
266  void LoadUpdateTimestampStart();
267
268  // Sets |update_timestamp_start_| to the given value and persists the value.
269  void SetUpdateTimestampStart(const base::Time& value);
270
271  // Sets |update_timestamp_end_| to the given value. This is not persisted
272  // as it happens at the end of the update process where state is deleted
273  // anyway.
274  void SetUpdateTimestampEnd(const base::Time& value);
275
276  // Initializes |update_duration_uptime_| from the persisted state.
277  void LoadUpdateDurationUptime();
278
279  // Helper method used in SetUpdateDurationUptime() and
280  // CalculateUpdateDurationUptime().
281  void SetUpdateDurationUptimeExtended(const base::TimeDelta& value,
282                                       const base::Time& timestamp,
283                                       bool use_logging);
284
285  // Sets |update_duration_uptime_| to the given value and persists
286  // the value and sets |update_duration_uptime_timestamp_| to the
287  // current monotonic time.
288  void SetUpdateDurationUptime(const base::TimeDelta& value);
289
290  // Adds the difference between current monotonic time and
291  // |update_duration_uptime_timestamp_| to |update_duration_uptime_| and
292  // sets |update_duration_uptime_timestamp_| to current monotonic time.
293  void CalculateUpdateDurationUptime();
294
295  // Returns the full key for a download source given the prefix.
296  std::string GetPrefsKey(const std::string& prefix, DownloadSource source);
297
298  // Loads the number of bytes that have been currently downloaded through the
299  // previous attempts from the persisted state for the given source. It's
300  // reset to 0 everytime we begin a full update and is continued from previous
301  // attempt if we're resuming the update.
302  void LoadCurrentBytesDownloaded(DownloadSource source);
303
304  // Sets the number of bytes that have been currently downloaded for the
305  // given source. This value is also persisted.
306  void SetCurrentBytesDownloaded(DownloadSource source,
307                                 uint64_t current_bytes_downloaded,
308                                 bool log);
309
310  // Loads the total number of bytes that have been downloaded (since the last
311  // successful update) from the persisted state for the given source. It's
312  // reset to 0 everytime we successfully apply an update and counts the bytes
313  // downloaded for both successful and failed attempts since then.
314  void LoadTotalBytesDownloaded(DownloadSource source);
315
316  // Sets the total number of bytes that have been downloaded so far for the
317  // given source. This value is also persisted.
318  void SetTotalBytesDownloaded(DownloadSource source,
319                               uint64_t total_bytes_downloaded,
320                               bool log);
321
322  // Loads the blacklisted version from our prefs file.
323  void LoadRollbackVersion();
324
325  // Blacklists this version from getting AU'd to until we receive a new update
326  // response.
327  void SetRollbackVersion(const std::string& rollback_version);
328
329  // Clears any blacklisted version.
330  void ResetRollbackVersion();
331
332  inline uint32_t GetUrlIndex() {
333    return url_index_;
334  }
335
336  // Computes the list of candidate URLs from the total list of payload URLs in
337  // the Omaha response.
338  void ComputeCandidateUrls();
339
340  // Sets |num_responses_seen_| and persist it to disk.
341  void SetNumResponsesSeen(int num_responses_seen);
342
343  // Initializes |num_responses_seen_| from persisted state.
344  void LoadNumResponsesSeen();
345
346  // Reports metric conveying how many times updates were abandoned since
347  // the last update was applied. The difference between this metric and the
348  // previous ReportUpdatesAbandonedCountMetric() one is that this metric is
349  // reported every time an update is abandoned, as oposed to the mentioned
350  // metric that is reported once the new update was applied.
351  void ReportUpdatesAbandonedEventCountMetric();
352
353  // Initializes |num_reboots_| from the persisted state.
354  void LoadNumReboots();
355
356  // Sets |num_reboots| for the update attempt. Also persists the
357  // value being set so that we resume from the same value in case of a process
358  // restart.
359  void SetNumReboots(uint32_t num_reboots);
360
361  // Checks to see if the device rebooted since the last call and if so
362  // increments num_reboots.
363  void UpdateNumReboots();
364
365  // Writes the current wall-clock time to the kPrefsSystemUpdatedMarker
366  // state variable.
367  void CreateSystemUpdatedMarkerFile();
368
369  // Called at program startup if the device booted into a new update.
370  // The |time_to_reboot| parameter contains the (wall-clock) duration
371  // from when the update successfully completed (the value written
372  // into the kPrefsSystemUpdatedMarker state variable) until the device
373  // was booted into the update (current wall-clock time).
374  void BootedIntoUpdate(base::TimeDelta time_to_reboot);
375
376  // Loads the |kPrefsP2PFirstAttemptTimestamp| state variable from disk
377  // into |p2p_first_attempt_timestamp_|.
378  void LoadP2PFirstAttemptTimestamp();
379
380  // Loads the |kPrefsP2PNumAttempts| state variable into |p2p_num_attempts_|.
381  void LoadP2PNumAttempts();
382
383  // Sets the |kPrefsP2PNumAttempts| state variable to |value|.
384  void SetP2PNumAttempts(int value);
385
386  // Sets the |kPrefsP2PFirstAttemptTimestamp| state variable to |time|.
387  void SetP2PFirstAttemptTimestamp(const base::Time& time);
388
389  // The global state of the system.
390  SystemState* system_state_;
391
392  // Interface object with which we read/write persisted state. This must
393  // be set by calling the Initialize method before calling any other method.
394  PrefsInterface* prefs_;
395
396  // Interface object with which we read/write persisted state. This must
397  // be set by calling the Initialize method before calling any other method.
398  // This object persists across powerwashes.
399  PrefsInterface* powerwash_safe_prefs_;
400
401  // This is the current response object from Omaha.
402  OmahaResponse response_;
403
404  // Whether p2p is being used for downloading as set with the
405  // SetUsingP2PForDownloading() method.
406  bool using_p2p_for_downloading_;
407
408  // This stores a "signature" of the current response. The signature here
409  // refers to a subset of the current response from Omaha.  Each update to
410  // this value is persisted so we resume from the same value in case of a
411  // process restart.
412  std::string response_signature_;
413
414  // The number of times we've tried to download the payload. This is
415  // incremented each time we download the payload successsfully or when we
416  // exhaust all failure limits for all URLs and are about to wrap around back
417  // to the first URL.  Each update to this value is persisted so we resume from
418  // the same value in case of a process restart.
419  int payload_attempt_number_;
420
421  // The number of times we've tried to download the payload in full. This is
422  // incremented each time we download the payload in full successsfully or
423  // when we exhaust all failure limits for all URLs and are about to wrap
424  // around back to the first URL.  Each update to this value is persisted so
425  // we resume from the same value in case of a process restart.
426  int full_payload_attempt_number_;
427
428  // The index of the current URL.  This type is different from the one in the
429  // accessor methods because PrefsInterface supports only int64_t but we want
430  // to provide a stronger abstraction of uint32_t.  Each update to this value
431  // is persisted so we resume from the same value in case of a process
432  // restart.
433  int64_t url_index_;
434
435  // The count of failures encountered in the current attempt to download using
436  // the current URL (specified by url_index_).  Each update to this value is
437  // persisted so we resume from the same value in case of a process restart.
438  int64_t url_failure_count_;
439
440  // The number of times we've switched URLs.
441  int32_t url_switch_count_;
442
443  // The current download source based on the current URL. This value is
444  // not persisted as it can be recomputed everytime we update the URL.
445  // We're storing this so as not to recompute this on every few bytes of
446  // data we read from the socket.
447  DownloadSource current_download_source_;
448
449  // The number of different Omaha responses seen. Increases every time
450  // a new response is seen. Resets to 0 only when the system has been
451  // successfully updated.
452  int num_responses_seen_;
453
454  // The number of system reboots during an update attempt. Technically since
455  // we don't go out of our way to not update it when not attempting an update,
456  // also records the number of reboots before the next update attempt starts.
457  uint32_t num_reboots_;
458
459  // The timestamp until which we've to wait before attempting to download the
460  // payload again, so as to backoff repeated downloads.
461  base::Time backoff_expiry_time_;
462
463  // The most recently calculated value of the update duration.
464  base::TimeDelta update_duration_current_;
465
466  // The point in time (wall-clock) that the update was started.
467  base::Time update_timestamp_start_;
468
469  // The point in time (wall-clock) that the update ended. If the update
470  // is still in progress, this is set to the Epoch (e.g. 0).
471  base::Time update_timestamp_end_;
472
473  // The update duration uptime
474  base::TimeDelta update_duration_uptime_;
475
476  // The monotonic time when |update_duration_uptime_| was last set
477  base::Time update_duration_uptime_timestamp_;
478
479  // The number of bytes that have been downloaded for each source for each new
480  // update attempt. If we resume an update, we'll continue from the previous
481  // value, but if we get a new response or if the previous attempt failed,
482  // we'll reset this to 0 to start afresh. Each update to this value is
483  // persisted so we resume from the same value in case of a process restart.
484  // The extra index in the array is to no-op accidental access in case the
485  // return value from GetCurrentDownloadSource is used without validation.
486  uint64_t current_bytes_downloaded_[kNumDownloadSources + 1];
487
488  // The number of bytes that have been downloaded for each source since the
489  // the last successful update. This is used to compute the overhead we incur.
490  // Each update to this value is persisted so we resume from the same value in
491  // case of a process restart.
492  // The extra index in the array is to no-op accidental access in case the
493  // return value from GetCurrentDownloadSource is used without validation.
494  uint64_t total_bytes_downloaded_[kNumDownloadSources + 1];
495
496  // A small timespan used when comparing wall-clock times for coping
497  // with the fact that clocks drift and consequently are adjusted
498  // (either forwards or backwards) via NTP.
499  static const base::TimeDelta kDurationSlack;
500
501  // The ordered list of the subset of payload URL candidates which are
502  // allowed as per device policy.
503  std::vector<std::string> candidate_urls_;
504
505  // This stores a blacklisted version set as part of rollback. When we rollback
506  // we store the version of the os from which we are rolling back from in order
507  // to guarantee that we do not re-update to it on the next au attempt after
508  // reboot.
509  std::string rollback_version_;
510
511  // The cached value of |kPrefsP2PFirstAttemptTimestamp|.
512  base::Time p2p_first_attempt_timestamp_;
513
514  // The cached value of |kPrefsP2PNumAttempts|.
515  int p2p_num_attempts_;
516
517  // The number of bytes downloaded per attempt.
518  int64_t attempt_num_bytes_downloaded_;
519
520  // The boot time when the attempt was started.
521  base::Time attempt_start_time_boot_;
522
523  // The monotonic time when the attempt was started.
524  base::Time attempt_start_time_monotonic_;
525
526  // The connection type when the attempt started.
527  metrics::ConnectionType attempt_connection_type_;
528
529  // Whether we're currently rolling back.
530  AttemptType attempt_type_;
531
532  DISALLOW_COPY_AND_ASSIGN(PayloadState);
533};
534
535}  // namespace chromeos_update_engine
536
537#endif  // UPDATE_ENGINE_PAYLOAD_STATE_H_
538