blob: ab575edee871ade8ae8db4ae91576a781057a505 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COBALT_SRC_LOCAL_AGGREGATION_1_1_LOCAL_AGGREGATE_STORAGE_IMMEDIATE_LOCAL_AGGREGATE_STORAGE_H_
#define COBALT_SRC_LOCAL_AGGREGATION_1_1_LOCAL_AGGREGATE_STORAGE_IMMEDIATE_LOCAL_AGGREGATE_STORAGE_H_
#include <cstdint>
#include <string>
#include "src/lib/util/consistent_proto_store.h"
#include "src/lib/util/file_system.h"
#include "src/local_aggregation_1_1/local_aggregate_storage/local_aggregate_storage.h"
#include "src/local_aggregation_1_1/local_aggregation.pb.h"
#include "src/logger/project_context_factory.h"
#include "src/registry/cobalt_registry.pb.h"
namespace cobalt::local_aggregation {
// ImmediateLocalAggregateStorage implements LocalAggregateStorage with immediate write to disk.
//
// This implementation uses a directory structure as follows:
//
// <customer_id>/
// <project_id>/
// <metric_id>
// <metric_id>
// <project_id>/
// <metric_id>
// <customer_id>/
// ...
//
// Each call to SaveMetricAggregate uses ConsistentProtoStore to overwrite the appropriate
// <metric_id> file.
//
// Note: This implementation fares poorly on systems with slow file system writes, and especially on
// those that suffer from write amplification.
class ImmediateLocalAggregateStorage : public LocalAggregateStorage {
public:
// Constructor for a ImmediateLocalAggregateStorage object
//
// |base_directory|: The absolute path to the directory where the local aggregation files are
// stored. This directory doesn't need to exist yet, but its parent
// directory must already exist.
// |fs|: An instance of the FileSystem interface. Used for reading/writing files.
// |global_project_context_factory|: The current global registry.
ImmediateLocalAggregateStorage(
std::string base_directory, util::FileSystem *fs,
const logger::ProjectContextFactory *global_project_context_factory);
~ImmediateLocalAggregateStorage() override = default;
lib::statusor::StatusOr<MetricAggregateRef> GetMetricAggregate(uint32_t customer_id,
uint32_t project_id,
uint32_t metric_id) override;
void DeleteData() override;
protected:
util::Status SaveMetricAggregate(uint32_t customer_id, uint32_t project_id,
uint32_t metric_id) override;
void ResetInternalMetrics(logger::LoggerInterface *internal_logger) override {}
private:
// DeleteOutdatedMetrics walks the filesystem from the |base_directory_| down and deletes
// MetricAggregate files, and project directories that do not exist in the CobaltRegistry.
//
// TODO(fxbug.dev/51390): Customers that are not present in the registry should be deleted
// too.
void DeleteOutdatedMetrics();
// InitializePersistentStore iterates through the registry and creates the customer/project
// directories for all of the metrics in the registry (if they don't already exist). Additionally,
// it adds empty MetricAggregate objects to the |aggregates_| object. It does not create metric
// files, since at this point they are guaranteed to be empty.
void InitializePersistentStore();
const std::string base_directory_;
util::FileSystem *fs_;
util::ConsistentProtoStore proto_store_;
const logger::ProjectContextFactory *global_project_context_factory_;
std::map<std::tuple<uint32_t, uint32_t, uint32_t>, MetricAggregate> aggregates_;
std::mutex mutex_;
};
} // namespace cobalt::local_aggregation
#endif // COBALT_SRC_LOCAL_AGGREGATION_1_1_LOCAL_AGGREGATE_STORAGE_IMMEDIATE_LOCAL_AGGREGATE_STORAGE_H_