blob: a0983bbcd616f080f628bd4b96791061b70b3c36 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MISSIVE_HEALTH_HEALTH_MODULE_FILES_H_
#define MISSIVE_HEALTH_HEALTH_MODULE_FILES_H_
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <base/files/file.h>
#include <base/sequence_checker.h>
#include <base/thread_annotations.h>
#include "missive/proto/health.pb.h"
#include "missive/util/status.h"
#include "missive/util/statusor.h"
namespace reporting {
// HealthModuleFiles is a module used by the health module to persistently
// store ERP Health data. It contains the logic for reading and writing data to
// files and populating the ERPHealthData proto. Accesses to the underlying
// files should be called on the same sequenced task runner to achieve mutual
// exclusion.
class HealthModuleFiles {
public:
~HealthModuleFiles();
HealthModuleFiles(const HealthModuleFiles& other) = delete;
HealthModuleFiles& operator=(const HealthModuleFiles& other) = delete;
// Creation logic for the files interface. Maps what files are available
// to be read, and the storage usage. Also attempts to clear up space if too
// much is being used relative to |max_storage_space|.
static std::unique_ptr<HealthModuleFiles> Create(
const base::FilePath& directory,
std::string_view file_base_name,
uint32_t max_storage_space);
// Dumps contents of underlying files into |data|.
void PopulateHistory(ERPHealthData* data) const;
// Writes data to the underlying files. If space is full, this will cause
// other bits of data to be removed from the files.
Status Write(std::string_view data);
private:
// Constructor for the class. Called by Create method.
HealthModuleFiles(const base::FilePath& directory,
std::string_view file_base_name,
uint32_t max_storage_space,
uint32_t storage_used,
uint32_t max_file_header,
const std::map<uint32_t, base::FilePath>& files);
// Frees |storage| space from underlying files. This will do nothing if
// |storage| + |storage_used_| < |max_storage_space|. It may free more space
// than |storage| as it will remove an entire line from the underlying files
// (i.e. the oldest file's first line is 5 chars, and we request to remove 3
// bytes. In this case the remaining 2 bytes of the line plus the newline
// will also be removed.
Status FreeStorage(uint32_t storage);
// Requests a certain amount of storage from the health module. This will
// trigger some data to be deleted from the underlying files if |storage| +
// |storage_used_| > |max_storage_space|.
Status ReserveStorage(uint32_t storage);
// Add a new file to |files|.
base::FilePath CreateNewFile();
// Remove the last file in |files|. Age is tracked by the file header.
void DeleteOldestFile();
// Helper method checking size for a given file.
static StatusOr<uint32_t> FileSize(const base::FilePath& file_path);
SEQUENCE_CHECKER(sequence_checker_);
// Root directory of ERP Health data files.
const base::FilePath directory_;
// Base name of files for the storage represented.
const std::string file_base_name_;
// Max storage space that can be used by every file.
const uint32_t max_storage_space_;
// Available storage space.
uint32_t storage_used_ GUARDED_BY_CONTEXT(sequence_checker_);
// Current largest file header in use.
uint32_t max_file_header_ GUARDED_BY_CONTEXT(sequence_checker_) = 0u;
// Files currently managed for a given history.
std::map<uint32_t, base::FilePath> files_
GUARDED_BY_CONTEXT(sequence_checker_);
// Max storage used by an individual history, currently constant 10KiB.
// TODO(tylergarrett) control each history per policy.
const uint32_t max_file_storage_ = 10 * 1024u;
};
} // namespace reporting
#endif // MISSIVE_HEALTH_HEALTH_MODULE_FILES_H_