7#include "absl/strings/str_format.h"
8#include "absl/strings/str_cat.h"
14#include "nlohmann/json.hpp"
26 for (
size_t i = 0; i < data.size(); ++i) {
27 hash = hash * 31 + data[i];
29 return absl::StrFormat(
"%08x", hash);
34 auto now = std::chrono::system_clock::now();
35 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
36 now.time_since_epoch()).count();
37 return absl::StrFormat(
"snap_%lld", ms);
41 return std::chrono::duration_cast<std::chrono::milliseconds>(
42 std::chrono::system_clock::now().time_since_epoch()).count();
53 last_backup_time_(0) {
69 if (!initial_result.ok()) {
70 return initial_result.status();
78 const std::string& description,
79 const std::string& creator,
83 return absl::FailedPreconditionError(
"ROM not loaded");
87 std::vector<uint8_t> rom_data(
rom_->
size());
94 snapshot.
timestamp = GetCurrentTimestamp();
95 snapshot.
rom_hash = ComputeHash(rom_data);
105 snapshot.
rom_data = std::move(rom_data);
110 snapshot.metadata = nlohmann::json::object();
111 snapshot.metadata[
"size"] =
rom_->
size();
112 snapshot.metadata[
"auto_backup"] = !is_checkpoint;
130 return absl::NotFoundError(absl::StrCat(
"Snapshot not found: ", snapshot_id));
134 return absl::FailedPreconditionError(
"ROM not loaded");
140 std::vector<uint8_t> rom_data;
148 if (rom_data.size() !=
rom_->
size()) {
149 return absl::DataLossError(
"Snapshot size mismatch");
154 "Pre-restore backup",
158 if (!backup_result.ok()) {
159 return absl::InternalError(
"Failed to create pre-restore backup");
167 return absl::OkStatus();
173 return absl::NotFoundError(
"Snapshot not found");
176 it->second.is_safe_point =
true;
177 return absl::OkStatus();
181 std::vector<RomSnapshot> result;
183 for (
const auto& [
id, snapshot] :
snapshots_) {
184 if (!safe_points_only || snapshot.is_safe_point) {
185 result.push_back(snapshot);
190 std::sort(result.begin(), result.end(),
192 return a.timestamp > b.timestamp;
199 const std::string& snapshot_id)
const {
202 return absl::NotFoundError(
"Snapshot not found");
210 return absl::NotFoundError(
"Snapshot not found");
214 if (it->second.is_safe_point) {
215 return absl::FailedPreconditionError(
"Cannot delete safe point");
219 return absl::OkStatus();
228 return absl::FailedPreconditionError(
"ROM not loaded");
232 std::vector<uint8_t> current_data(
rom_->
size());
234 std::string current_hash = ComputeHash(current_data);
238 if (!integrity_status.ok()) {
255 if (snapshots.empty()) {
256 return absl::NotFoundError(
"No safe points available for recovery");
268 std::vector<uint8_t> data(
rom_->
size());
270 return ComputeHash(data);
277 std::vector<std::pair<int64_t, std::string>> auto_backups;
278 for (
const auto& [
id, snapshot] :
snapshots_) {
279 if (!snapshot.is_safe_point && !snapshot.is_checkpoint) {
280 auto_backups.push_back({snapshot.timestamp,
id});
285 std::sort(auto_backups.begin(), auto_backups.end());
289 snapshots_.erase(auto_backups.front().second);
290 auto_backups.erase(auto_backups.begin());
295 !auto_backups.empty()) {
296 snapshots_.erase(auto_backups.front().second);
297 auto_backups.erase(auto_backups.begin());
300 return absl::OkStatus();
307 for (
const auto& [
id, snapshot] :
snapshots_) {
333 std::vector<uint8_t> data(
rom_->
size());
335 return ComputeHash(data);
339 const std::vector<uint8_t>& data)
const {
346 const std::vector<uint8_t>& compressed)
const {
353 return absl::FailedPreconditionError(
"ROM not loaded");
358 return absl::DataLossError(
"ROM size is zero");
364 return absl::DataLossError(
"ROM too small to be valid");
367 return absl::OkStatus();
372 for (
const auto& [
id, snapshot] :
snapshots_) {
373 total += snapshot.compressed_size;
383 : version_mgr_(version_mgr),
396 const std::string& proposal_id,
397 const std::string& sender,
398 const std::string& description,
399 const nlohmann::json& proposal_data) {
403 status.
status =
"pending";
409 absl::StrCat(
"Before proposal: ", description),
413 if (!snapshot_result.ok()) {
414 return snapshot_result.status();
421 return absl::OkStatus();
425 const std::string& proposal_id,
426 const std::string& username,
431 return absl::NotFoundError(
"Proposal not found");
436 if (status.
status !=
"pending") {
437 return absl::FailedPreconditionError(
"Proposal already decided");
441 status.
votes[username] = approved;
445 status.
status =
"approved";
449 size_t rejection_count = 0;
450 for (
const auto& [user, vote] : status.
votes) {
451 if (!vote) rejection_count++;
457 status.
status =
"rejected";
462 return absl::OkStatus();
477 size_t approval_count = 0;
478 for (
const auto& [user, approved] : status.
votes) {
479 if (approved) approval_count++;
488 for (
const auto& [user, approved] : status.
votes) {
489 if (!approved)
return false;
502 const std::string& proposal_id)
const {
507 return it->second.status ==
"approved";
510std::vector<ProposalApprovalManager::ApprovalStatus>
512 std::vector<ApprovalStatus> pending;
514 if (status.status ==
"pending") {
515 pending.push_back(status);
521absl::StatusOr<ProposalApprovalManager::ApprovalStatus>
523 const std::string& proposal_id)
const {
526 return absl::NotFoundError(
"Proposal not found");
The Rom class is used to load, save, and modify Rom data.
std::vector< std::string > participants_
void SetHost(const std::string &host_username)
absl::StatusOr< ApprovalStatus > GetProposalStatus(const std::string &proposal_id) const
absl::Status VoteOnProposal(const std::string &proposal_id, const std::string &username, bool approved)
std::string host_username_
void SetApprovalMode(ApprovalMode mode)
bool IsProposalApproved(const std::string &proposal_id) const
RomVersionManager * version_mgr_
absl::Status SubmitProposal(const std::string &proposal_id, const std::string &sender, const std::string &description, const nlohmann::json &proposal_data)
std::vector< ApprovalStatus > GetPendingProposals() const
bool CheckApprovalThreshold(const ApprovalStatus &status) const
ProposalApprovalManager(RomVersionManager *version_mgr)
std::map< std::string, ApprovalStatus > proposals_
Manages ROM versioning, snapshots, and rollback capabilities.
std::string ComputeRomHash() const
absl::Status CleanupOldSnapshots()
std::vector< uint8_t > DecompressData(const std::vector< uint8_t > &compressed) const
size_t GetTotalStorageUsed() const
absl::StatusOr< std::string > CreateSnapshot(const std::string &description, const std::string &creator, bool is_checkpoint=false)
absl::StatusOr< RomSnapshot > GetSnapshot(const std::string &snapshot_id) const
std::string GetCurrentHash() const
std::map< std::string, RomSnapshot > snapshots_
absl::Status ValidateRomIntegrity() const
std::string last_known_hash_
RomVersionManager(Rom *rom)
absl::Status Initialize(const Config &config)
absl::Status AutoRecover()
absl::StatusOr< bool > DetectCorruption()
absl::Status RestoreSnapshot(const std::string &snapshot_id)
absl::Status MarkAsSafePoint(const std::string &snapshot_id)
std::vector< uint8_t > CompressData(const std::vector< uint8_t > &data) const
absl::Status DeleteSnapshot(const std::string &snapshot_id)
std::vector< RomSnapshot > GetSnapshots(bool safe_points_only=false) const
std::string ComputeHash(const std::vector< uint8_t > &data)
int64_t GetCurrentTimestamp()
Main namespace for the application.
std::string snapshot_before
std::map< std::string, bool > votes
Represents a versioned snapshot of ROM state.
std::vector< uint8_t > rom_data
bool enable_corruption_detection
size_t total_storage_bytes
size_t manual_checkpoints
int64_t oldest_snapshot_timestamp
int64_t newest_snapshot_timestamp