blob: 0a3b3a222eeded7d4a0ce5aff44fbb0782976633 [file] [log] [blame]
// Copyright 2022 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 SRC_DEVELOPER_FORENSICS_CRASH_REPORTS_SNAPSHOT_STORE_H_
#define SRC_DEVELOPER_FORENSICS_CRASH_REPORTS_SNAPSHOT_STORE_H_
#include <deque>
#include <string>
#include "src/developer/forensics/crash_reports/item_location.h"
#include "src/developer/forensics/crash_reports/snapshot.h"
#include "src/developer/forensics/crash_reports/snapshot_persistence.h"
#include "src/developer/forensics/feedback/annotations/annotation_manager.h"
#include "src/developer/forensics/utils/storage_size.h"
namespace forensics::crash_reports {
// Manages the distribution and lifetime of snapshots.
//
// To limit memory usage, the managed snapshots' archive cannot exceed |max_archives_size_| in size.
//
// When space is constrained, calling AddSnapshot will cause SnapshotStore to drop the oldest
// archive until there is enough space for the new archive.
class SnapshotStore {
public:
SnapshotStore(feedback::AnnotationManager* annotation_manager,
std::string garbage_collected_snapshots_path,
const std::optional<SnapshotPersistence::Root>& temp_root,
const std::optional<SnapshotPersistence::Root>& persistent_root,
StorageSize max_archives_size);
// Stores the given data in memory for later retrieval.
void AddSnapshot(const std::string& uuid, fuchsia::feedback::Attachment archive);
// Deletes the data for |uuid| from memory, if it still exists.
void DeleteSnapshot(const std::string& uuid);
// Deletes all snapshots in memory and in persistence.
void DeleteAll();
// Moves the snapshot for |uuid| from memory to persistence, if possible. If |only_consider_tmp|
// is true, only /tmp will be considered as a valid storage location. Returns the location of the
// snapshot after the attempt to move.
ItemLocation MoveToPersistence(const std::string& uuid, bool only_consider_tmp);
// Attempts to move the snapshot for |uuid| from /cache to /tmp.
void MoveToTmp(const std::string& uuid);
// Returns true if data for |uuid| is currently stored in the SnapshotStore.
bool SnapshotExists(const std::string& uuid);
// Returns the location where the snapshot for |uuid| is currently stored in the SnapshotStore, if
// anywhere.
std::optional<ItemLocation> SnapshotLocation(const std::string& uuid);
// Returns the number of snapshots stored in SnapshotStore.
//
// Note: intended primarily for testing.
//
// TODO(https://fxbug.dev/42063091): Consider deleting this function after reports with timed out snapshots
// aren't associated with their original snapshot uuids (https://fxbug.dev/42062635).
size_t Size() const;
// Returns true if data for |uuid| was garbage collected.
bool IsGarbageCollected(const std::string& uuid) const;
// Returns true if the size of the currently stored archives is greater than the limit.
bool SizeLimitsExceeded() const;
// Returns the snapshot for |uuid|, if one exists. If no snapshot exists for |uuid| a
// MissingSnapshot containing annotations indicating the error will be returned.
//
// When a client no longer needs the data contained in a Snapshot, they should call Release to
// inform the SnapshotStore. If all clients call release, the SnapshotStore will voluntarily
// drop the Snapshot, freeing up space for new data.
Snapshot GetSnapshot(const std::string& uuid);
std::vector<std::string> GetSnapshotUuids() const;
// Returns the snapshot for |uuid|. Check-fails that |uuid| results in the return of a
// MissingSnapshot. A MissingSnapshot is guaranteed to be generated if |uuid| is the uuid of a
// SpecialCaseSnapshot.
MissingSnapshot GetMissingSnapshot(const std::string& uuid);
private:
// State associated with a snapshot.
// * The size of its archive.
// * The snapshot archive.
struct SnapshotData {
StorageSize archive_size;
std::shared_ptr<const ManagedSnapshot::Archive> archive;
};
// Drops archives if size limits are exceeded. Must call StartSnapshot for |uuid| first.
void EnforceSizeLimits(const std::string& uuid);
// Drop the archive for |data| and clean up state associated with it.
void DropArchive(SnapshotData* data);
SnapshotData* FindSnapshotData(const std::string& uuid);
void RecordAsGarbageCollected(const std::string& uuid);
feedback::AnnotationManager* annotation_manager_;
std::string garbage_collected_snapshots_path_;
SnapshotPersistence persistence_;
StorageSize max_archives_size_;
StorageSize current_archives_size_;
std::map<std::string, SnapshotData> data_;
std::deque<std::string> insertion_order_;
std::set<std::string> garbage_collected_snapshots_;
// Snapshot uuid and annotations to return under specific conditions, e.g., garbage collection,
// time outs.
struct SpecialCaseSnapshot {
explicit SpecialCaseSnapshot(std::string uuid, feedback::Annotations annotations)
: uuid(std::move(uuid)), annotations(std::move(annotations)) {}
std::string uuid;
feedback::Annotations annotations;
};
const SpecialCaseSnapshot garbage_collected_snapshot_;
const SpecialCaseSnapshot not_persisted_snapshot_;
const SpecialCaseSnapshot shutdown_snapshot_;
const SpecialCaseSnapshot no_uuid_snapshot_;
};
} // namespace forensics::crash_reports
#endif // SRC_DEVELOPER_FORENSICS_CRASH_REPORTS_SNAPSHOT_STORE_H_