1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#ifndef COMPONENTS_METRICS_PERSISTED_LOGS_H_ 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define COMPONENTS_METRICS_PERSISTED_LOGS_H_ 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector> 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/basictypes.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/values.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class PrefService; 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace metrics { 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Maintains a list of unsent logs that are written and restored from disk. 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class PersistedLogs { 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Used to produce a histogram that keeps track of the status of recalling 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // persisted per logs. 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) enum LogReadStatus { 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RECALL_SUCCESS, // We were able to correctly recall a persisted log. 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LIST_EMPTY, // Attempting to recall from an empty list. 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LIST_SIZE_MISSING, // Failed to recover list size using GetAsInteger(). 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LIST_SIZE_TOO_SMALL, // Too few elements in the list (less than 3). 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LIST_SIZE_CORRUPTION, // List size is not as expected. 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG_STRING_CORRUPTION, // Failed to recover log string using GetAsString(). 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECKSUM_CORRUPTION, // Failed to verify checksum. 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECKSUM_STRING_CORRUPTION, // Failed to recover checksum string using 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // GetAsString(). 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DECODE_FAIL, // Failed to decode log. 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DEPRECATED_XML_PROTO_MISMATCH, // The XML and protobuf logs have 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // inconsistent data. 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) END_RECALL_STATUS // Number of bins to use to create the histogram. 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Constructs a PersistedLogs that stores data in |local_state| under the 4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // preference |pref_name|. 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Calling code is responsible for ensuring that the lifetime of |local_state| 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // is longer than the lifetime of PersistedLogs. 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // When saving logs to disk, stores either the first |min_log_count| logs, or 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // at least |min_log_bytes| bytes of logs, whichever is greater. 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the optional |max_log_size| parameter is non-zero, all logs larger than 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // that limit will be skipped when writing to disk. 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PersistedLogs(PrefService* local_state, 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const char* pref_name, 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t min_log_count, 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t min_log_bytes, 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t max_log_size); 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ~PersistedLogs(); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Write list to storage. 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void SerializeLogs() const; 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Reads the list from the preference. 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LogReadStatus DeserializeLogs(); 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Adds a log to the list. 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void StoreLog(const std::string& log_data); 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Stages the most recent log. The staged_log will remain the same even if 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // additional logs are added. 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void StageLog(); 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Remove the staged log. 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void DiscardStagedLog(); 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // True if a log has been staged. 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool has_staged_log() const { return staged_log_index_ != -1; } 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Returns the element in the front of the list. 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& staged_log() const { 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(has_staged_log()); 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return list_[staged_log_index_].compressed_log_data; 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Returns the element in the front of the list. 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& staged_log_hash() const { 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(has_staged_log()); 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return list_[staged_log_index_].hash; 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The number of elements currently stored. 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t size() const { return list_.size(); } 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // True if there are no stored logs. 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool empty() const { return list_.empty(); } 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Writes the list to the ListValue. 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void WriteLogsToPrefList(base::ListValue* list) const; 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Reads the list from the ListValue. 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LogReadStatus ReadLogsFromPrefList(const base::ListValue& list); 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // A weak pointer to the PrefService object to read and write the preference 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // from. Calling code should ensure this object continues to exist for the 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // lifetime of the PersistedLogs object. 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefService* local_state_; 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The name of the preference to serialize logs to/from. 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const char* pref_name_; 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We will keep at least this |min_log_count_| logs or |min_log_bytes_| bytes 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // of logs, whichever is greater, when writing to disk. These apply after 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // skipping logs greater than |max_log_size_|. 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t min_log_count_; 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t min_log_bytes_; 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Logs greater than this size will not be written to disk. 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t max_log_size_; 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) struct LogHashPair { 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Initializes the members based on uncompressed |log_data|. 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void Init(const std::string& log_data); 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Compressed log data - a serialized protobuf that's been gzipped. 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string compressed_log_data; 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The SHA1 hash of log, stored to catch errors from memory corruption. 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string hash; 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // A list of all of the stored logs, stored with SHA1 hashes to check for 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // corruption while they are stored in memory. 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<LogHashPair> list_; 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The index and type of the log staged for upload. If nothing has been 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // staged, the index will be -1. 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int staged_log_index_; 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(PersistedLogs); 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace metrics 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif // COMPONENTS_METRICS_PERSISTED_LOGS_H_ 142