2 #include "ypc/core/exceptions.h"
3 #include "ypc/core/memref.h"
10 #include <glog/logging.h>
17 virtual const char *what() {
return "wrong magic number"; }
20 template <uint64_t MagicNumber_t, uint64_t BlockNumLimit_t,
21 uint64_t BlockSizeLimit_t>
24 const static uint64_t MagicNumber = MagicNumber_t;
25 const static uint64_t BlockSizeLimit = BlockSizeLimit_t;
26 const static uint64_t BlockNumLimit = BlockNumLimit_t;
29 : m_file(), m_file_path(), m_header(), m_is_header_valid(
false),
30 m_is_block_info_valid(
false), m_block_infos() {}
38 void open_for_read(
const char *file_path) {
39 if (m_file.is_open()) {
40 throw std::runtime_error(
"already open");
42 m_file_path = std::string(file_path);
43 m_file.open(file_path, std::ios::in | std::ios::binary);
44 if (!m_file.is_open()) {
50 void open_for_write(
const char *file_path) {
51 if (m_file.is_open()) {
52 throw std::runtime_error(
"already open");
54 m_file_path = std::string(file_path);
55 m_file.open(file_path, std::ios::out | std::ios::binary);
56 if (!m_file.is_open()) {
61 template <
typename ByteType>
62 int append_item(
const ByteType *data,
size_t len) {
63 static_assert(
sizeof(ByteType) == 1);
64 return append_item((
const char *)data, len);
67 int append_item(
const char *data,
size_t len) {
70 read_all_block_info();
74 m_header.item_number++;
75 m_header.magic_number = MagicNumber;
77 if (m_block_infos.empty()) {
78 bi.start_item_index = 0;
79 bi.end_item_index = 1;
80 bi.start_file_pos = block_start_offset;
81 bi.end_file_pos = bi.start_file_pos + len +
sizeof(len);
82 m_block_infos.push_back(bi);
83 m_header.block_number++;
85 bi = m_block_infos.back();
86 if (bi.end_item_index - bi.start_item_index >= BlockSizeLimit) {
87 auto back = m_block_infos.back();
88 bi.start_item_index = back.end_item_index;
89 bi.end_item_index = bi.start_item_index++;
90 bi.start_file_pos = back.end_file_pos;
91 bi.end_file_pos = bi.end_file_pos + len +
sizeof(len);
92 m_block_infos.push_back(bi);
93 m_header.block_number++;
96 back.end_item_index++;
97 back.end_file_pos = back.end_file_pos + len +
sizeof(len);
103 m_file.seekp(offset, m_file.beg);
104 m_file.write((
char *)&back,
sizeof(back));
105 m_file.seekp(0, m_file.beg);
106 m_file.write((
char *)&m_header,
sizeof(m_header));
108 m_file.seekp(back.end_file_pos - len -
sizeof(len), m_file.beg);
109 m_file.write((
char *)&len,
sizeof(len));
110 m_file.write(data, len);
114 void reset_read_item() {
117 read_all_block_info();
118 m_file.seekg(block_start_offset, m_file.beg);
121 bool next_item(
memref &s) {
126 m_file.read((
char *)&len,
sizeof(len));
130 if (s.data() ==
nullptr) {
133 if (s.size() < len) {
138 m_file.read((
char *)s.data(), len);
143 uint64_t item_number() {
144 if (!m_is_header_valid) {
147 return m_header.item_number;
151 m_is_header_valid =
false;
152 m_is_block_info_valid =
false;
153 m_block_infos.clear();
159 if (m_is_header_valid) {
162 auto prev = m_file.tellg();
164 m_file.seekg(0, m_file.beg);
165 m_file.read((
char *)&m_header,
sizeof(
header));
166 if (!m_file.eof() && m_header.magic_number != MagicNumber) {
169 m_is_header_valid =
true;
170 m_file.seekg(prev, m_file.beg);
172 void read_all_block_info() {
174 if (m_is_block_info_valid) {
177 m_file.seekg(
sizeof(
header), m_file.beg);
178 for (
size_t i = 0; i < m_header.block_number; ++i) {
180 m_file.read((
char *)&bi,
sizeof(bi));
181 m_block_infos.push_back(bi);
183 m_is_block_info_valid =
true;
188 uint64_t magic_number;
189 uint64_t version_number;
190 uint64_t block_number;
191 uint64_t item_number;
196 uint64_t start_item_index;
197 uint64_t end_item_index;
198 long int start_file_pos;
199 long int end_file_pos;
201 const static long int block_start_offset =
205 std::string m_file_path;
207 bool m_is_header_valid;
208 bool m_is_block_info_valid;
209 std::vector<block_info> m_block_infos;