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