• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 COMPONENTS_METRICS_PERSISTED_LOGS_H_
6 #define COMPONENTS_METRICS_PERSISTED_LOGS_H_
7 
8 #include <string>
9 #include <vector>
10 
11 #include "base/basictypes.h"
12 #include "base/logging.h"
13 #include "base/values.h"
14 
15 class PrefService;
16 
17 namespace metrics {
18 
19 // Maintains a list of unsent logs that are written and restored from disk.
20 class PersistedLogs {
21  public:
22   // Used to produce a histogram that keeps track of the status of recalling
23   // persisted per logs.
24   enum LogReadStatus {
25     RECALL_SUCCESS,         // We were able to correctly recall a persisted log.
26     LIST_EMPTY,             // Attempting to recall from an empty list.
27     LIST_SIZE_MISSING,      // Failed to recover list size using GetAsInteger().
28     LIST_SIZE_TOO_SMALL,    // Too few elements in the list (less than 3).
29     LIST_SIZE_CORRUPTION,   // List size is not as expected.
30     LOG_STRING_CORRUPTION,  // Failed to recover log string using GetAsString().
31     CHECKSUM_CORRUPTION,    // Failed to verify checksum.
32     CHECKSUM_STRING_CORRUPTION,  // Failed to recover checksum string using
33                                  // GetAsString().
34     DECODE_FAIL,            // Failed to decode log.
35     DEPRECATED_XML_PROTO_MISMATCH,  // The XML and protobuf logs have
36                                     // inconsistent data.
37     END_RECALL_STATUS       // Number of bins to use to create the histogram.
38   };
39 
40   enum StoreType {
41     NORMAL_STORE,       // A standard store operation.
42     PROVISIONAL_STORE,  // A store operation that can be easily reverted later.
43   };
44 
45   // Constructs a PersistedLogs that stores data in |local_state| under the
46   // preference |pref_name| and also reads from legacy pref |old_pref_name|.
47   // Calling code is responsible for ensuring that the lifetime of |local_state|
48   // is longer than the lifetime of PersistedLogs.
49   //
50   // When saving logs to disk, stores either the first |min_log_count| logs, or
51   // at least |min_log_bytes| bytes of logs, whichever is greater.
52   //
53   // If the optional |max_log_size| parameter is non-zero, all logs larger than
54   // that limit will be dropped before logs are written to disk.
55   PersistedLogs(PrefService* local_state,
56                 const char* pref_name,
57                 const char* old_pref_name,
58                 size_t min_log_count,
59                 size_t min_log_bytes,
60                 size_t max_log_size);
61   ~PersistedLogs();
62 
63   // Write list to storage.
64   void SerializeLogs();
65 
66   // Reads the list from the preference.
67   LogReadStatus DeserializeLogs();
68 
69   // Adds a log to the list.
70   void StoreLog(const std::string& log_data);
71 
72   // Stages the most recent log.  The staged_log will remain the same even if
73   // additional logs are added.
74   void StageLog();
75 
76   // Remove the staged log.
77   void DiscardStagedLog();
78 
79   // Saves the staged log, then clears staged_log().
80   // If |store_type| is PROVISIONAL_STORE, it can be dropped from storage with
81   // a later call to DiscardLastProvisionalStore (if it hasn't already been
82   // staged again).
83   // This is intended to be used when logs are being saved while an upload is in
84   // progress, in case the upload later succeeds.
85   // This can only be called if has_staged_log() is true.
86   void StoreStagedLogAsUnsent(StoreType store_type);
87 
88   // Discards the last log stored with StoreStagedLogAsUnsent with |store_type|
89   // set to PROVISIONAL_STORE, as long as it hasn't already been re-staged. If
90   // the log is no longer present, this is a no-op.
91   void DiscardLastProvisionalStore();
92 
93   // True if a log has been staged.
has_staged_log()94   bool has_staged_log() const {
95     return !staged_log_.compressed_log_data.empty();
96   }
97 
98   // Returns the element in the front of the list.
staged_log()99   const std::string& staged_log() const {
100     DCHECK(has_staged_log());
101     return staged_log_.compressed_log_data;
102   }
103 
104   // Returns the element in the front of the list.
staged_log_hash()105   const std::string& staged_log_hash() const {
106     DCHECK(has_staged_log());
107     return staged_log_.hash;
108   }
109 
110   // The number of elements currently stored.
size()111   size_t size() const { return list_.size(); }
112 
113   // True if there are no stored logs.
empty()114   bool empty() const { return list_.empty(); }
115 
116  private:
117   // Writes the list to the ListValue.
118   void WriteLogsToPrefList(base::ListValue* list);
119 
120   // Reads the list from the ListValue.
121   LogReadStatus ReadLogsFromPrefList(const base::ListValue& list);
122 
123   // Reads the list from the old pref's ListValue.
124   // TODO(asvitkine): Remove the old pref in M39.
125   LogReadStatus ReadLogsFromOldPrefList(const base::ListValue& list);
126 
127   // A weak pointer to the PrefService object to read and write the preference
128   // from.  Calling code should ensure this object continues to exist for the
129   // lifetime of the PersistedLogs object.
130   PrefService* local_state_;
131 
132   // The name of the preference to serialize logs to/from.
133   const char* pref_name_;
134 
135   // The name of the preference to serialize logs from.
136   // TODO(asvitkine): Remove the old pref in M39.
137   const char* old_pref_name_;
138 
139   // We will keep at least this |min_log_count_| logs or |min_log_bytes_| bytes
140   // of logs, whichever is greater, when writing to disk.  These apply after
141   // skipping logs greater than |max_log_size_|.
142   const size_t min_log_count_;
143   const size_t min_log_bytes_;
144 
145   // Logs greater than this size will not be written to disk.
146   const size_t max_log_size_;
147 
148   struct LogHashPair {
149     // Initializes the members based on uncompressed |log_data|.
150     void Init(const std::string& log_data);
151 
152     // Clears the struct members.
153     void Clear();
154 
155     // Swap both log and hash from another LogHashPair.
156     void Swap(LogHashPair* input);
157 
158     // Compressed log data - a serialized protobuf that's been gzipped.
159     std::string compressed_log_data;
160 
161     // The SHA1 hash of log, stored to catch errors from memory corruption.
162     std::string hash;
163   };
164   // A list of all of the stored logs, stored with SHA1 hashes to check for
165   // corruption while they are stored in memory.
166   std::vector<LogHashPair> list_;
167 
168   // The log staged for upload.
169   LogHashPair staged_log_;
170 
171   // The index and type of the last provisional store. If nothing has been
172   // provisionally stored, or the last provisional store has already been
173   // re-staged, the index will be -1;
174   // This is necessary because during an upload there are two logs (staged
175   // and current) and a client might store them in either order, so it's
176   // not necessarily the case that the provisional store is the last store.
177   int last_provisional_store_index_;
178 
179   DISALLOW_COPY_AND_ASSIGN(PersistedLogs);
180 };
181 
182 }  // namespace metrics
183 
184 #endif  // COMPONENTS_METRICS_PERSISTED_LOGS_H_
185