VeloGraphX
High-performance dynamic graph analytics in C++20
Loading...
Searching...
No Matches
partition_file.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <cstring>
5#include <filesystem>
6#include <fstream>
7#include <stdexcept>
8#include <string>
9#include <vector>
10
11#if defined(__linux__) || defined(__APPLE__)
12#include <fcntl.h>
13#include <sys/mman.h>
14#include <sys/stat.h>
15#include <unistd.h>
16#endif
17
18namespace velographx {
19
21 std::uint32_t magic{0x56475850u}; // VGXP
22 std::uint16_t version{1};
23 std::uint16_t flags{0};
24 std::uint64_t partition_id{0};
25 std::uint64_t payload_bytes{0};
26};
27
29 public:
30 static void write(const std::filesystem::path& path,
31 std::uint64_t partition_id,
32 const std::vector<std::uint8_t>& payload) {
33 std::ofstream out(path, std::ios::binary | std::ios::trunc);
34 if (!out) throw std::runtime_error("failed to open partition file for write");
36 header.partition_id = partition_id;
37 header.payload_bytes = static_cast<std::uint64_t>(payload.size());
38 out.write(reinterpret_cast<const char*>(&header), sizeof(header));
39 if (!payload.empty()) {
40 out.write(reinterpret_cast<const char*>(payload.data()),
41 static_cast<std::streamsize>(payload.size()));
42 }
43 if (!out) throw std::runtime_error("failed to write partition file");
44 }
45
46 static std::vector<std::uint8_t> read(const std::filesystem::path& path,
47 std::uint64_t expected_partition_id) {
48 std::ifstream in(path, std::ios::binary);
49 if (!in) throw std::runtime_error("failed to open partition file for read");
50 PartitionFileHeader header{};
51 in.read(reinterpret_cast<char*>(&header), sizeof(header));
52 validate_header(header, expected_partition_id);
53 std::vector<std::uint8_t> payload(static_cast<std::size_t>(header.payload_bytes));
54 if (!payload.empty()) in.read(reinterpret_cast<char*>(payload.data()), static_cast<std::streamsize>(payload.size()));
55 if (!in) throw std::runtime_error("truncated partition payload");
56 return payload;
57 }
58
59 static std::vector<std::uint8_t> read_mmap_or_fallback(
60 const std::filesystem::path& path,
61 std::uint64_t expected_partition_id,
62 bool* used_mmap = nullptr) {
63 if (used_mmap) *used_mmap = false;
64#if defined(__linux__) || defined(__APPLE__)
65 const int fd = ::open(path.c_str(), O_RDONLY);
66 if (fd >= 0) {
67 struct stat st {};
68 if (::fstat(fd, &st) == 0 && st.st_size >= static_cast<off_t>(sizeof(PartitionFileHeader))) {
69 void* addr = ::mmap(nullptr, static_cast<std::size_t>(st.st_size), PROT_READ, MAP_PRIVATE, fd, 0);
70 if (addr != MAP_FAILED) {
71 PartitionFileHeader header{};
72 std::memcpy(&header, addr, sizeof(header));
73 try {
74 validate_header(header, expected_partition_id);
75 const auto total = sizeof(PartitionFileHeader) + static_cast<std::size_t>(header.payload_bytes);
76 if (total > static_cast<std::size_t>(st.st_size)) {
77 throw std::runtime_error("truncated mmap partition payload");
78 }
79 const auto* begin = static_cast<const std::uint8_t*>(addr) + sizeof(PartitionFileHeader);
80 std::vector<std::uint8_t> payload(begin, begin + static_cast<std::size_t>(header.payload_bytes));
81 ::munmap(addr, static_cast<std::size_t>(st.st_size));
82 ::close(fd);
83 if (used_mmap) *used_mmap = true;
84 return payload;
85 } catch (...) {
86 ::munmap(addr, static_cast<std::size_t>(st.st_size));
87 ::close(fd);
88 throw;
89 }
90 }
91 }
92 ::close(fd);
93 }
94#endif
95 return read(path, expected_partition_id);
96 }
97
98 private:
99 static void validate_header(const PartitionFileHeader& header,
100 std::uint64_t expected_partition_id) {
101 if (header.magic != 0x56475850u) throw std::runtime_error("invalid partition magic");
102 if (header.version != 1) throw std::runtime_error("unsupported partition version");
103 if (header.partition_id != expected_partition_id) throw std::runtime_error("partition id mismatch");
104 }
105};
106
107} // namespace velographx
static void write(const std::filesystem::path &path, std::uint64_t partition_id, const std::vector< std::uint8_t > &payload)
static std::vector< std::uint8_t > read_mmap_or_fallback(const std::filesystem::path &path, std::uint64_t expected_partition_id, bool *used_mmap=nullptr)
static std::vector< std::uint8_t > read(const std::filesystem::path &path, std::uint64_t expected_partition_id)