// (C) 2018-2024 by Folkert van Heusden // Released under MIT license #include <cassert> #include "disk_backend.h" #include "gen.h" #include "utils.h" #if IS_POSIX #include "disk_backend_file.h" #else #include "disk_backend_esp32.h" #endif #include "disk_backend_nbd.h" disk_backend::disk_backend() { } disk_backend::~disk_backend() { } void disk_backend::store_object_in_overlay(const off_t id, const std::vector<uint8_t> & data) { overlay.insert_or_assign(id, data); } std::optional<std::vector<uint8_t> > disk_backend::get_object_from_overlay(const off_t id) { auto it = overlay.find(id); if (it != overlay.end()) return it->second; return { }; } std::optional<std::vector<uint8_t> > disk_backend::get_from_overlay(const off_t offset, const size_t sector_size) { assert((offset % sector_size) == 0); if (use_overlay) return get_object_from_overlay(offset / sector_size); return { }; } bool disk_backend::store_mem_range_in_overlay(const off_t offset, const size_t n, const uint8_t *const from, const size_t sector_size) { assert((offset % sector_size) == 0); assert((n % sector_size) == 0); if (use_overlay) { for(size_t o=0; o<n; o += sector_size) store_object_in_overlay((offset + o) / sector_size, std::vector<uint8_t>(from + o, from + o + sector_size)); return true; } return false; } JsonDocument disk_backend::serialize_overlay() const { JsonDocument out; for(auto & id: overlay) { JsonDocument j_data; JsonArray j_data_work = j_data.to<JsonArray>(); for(size_t i=0; i<id.second.size(); i++) j_data_work.add(id.second.at(i)); out[format("%lu", id.first)] = j_data; } return out; } void disk_backend::deserialize_overlay(const JsonVariantConst j) { if (j.containsKey("overlay") == false) return; // we can have state-dumps without overlay for(auto kv : j.as<JsonObjectConst>()) { uint32_t id = std::atoi(kv.key().c_str()); std::vector<uint8_t> data; for(auto v: kv.value().as<JsonArrayConst>()) data.push_back(v); store_object_in_overlay(id, data); } } disk_backend *disk_backend::deserialize(const JsonVariantConst j) { std::string type = j["disk-backend-type"]; disk_backend *d = nullptr; if (type == "nbd") d = disk_backend_nbd::deserialize(j); #if IS_POSIX else if (type == "file") d = disk_backend_file::deserialize(j); #else else if (type == "esp32") d = disk_backend_esp32::deserialize(j); #endif // should not be triggered assert(d); d->deserialize_overlay(j); // assume we want snapshots (again?) d->begin(true); return d; }