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;