1 #ifndef DIY_STORAGE_HPP
2 #define DIY_STORAGE_HPP
9 #include "serialization.hpp"
12 #include "io/utils.hpp"
18 typedef void (*Save)(
const void*, BinaryBuffer& buf);
19 typedef void (*Load)(
void*, BinaryBuffer& buf);
21 struct FileBuffer:
public BinaryBuffer
23 FileBuffer(FILE* file_): file(file_), head(0), tail(0) {}
26 virtual inline void save_binary(
const char* x,
size_t count)
override { fwrite(x, 1, count, file); head += count; }
27 virtual inline void load_binary(
char* x,
size_t count)
override { fread(x, 1, count, file); }
28 virtual inline void load_binary_back(
char* x,
size_t count)
override { fseek(file, static_cast<long>(tail), SEEK_END); fread(x, 1, count, file); tail += count; fseek(file, static_cast<long>(head), SEEK_SET); }
30 size_t size()
const {
return head; }
42 virtual int put(
const void* x, detail::Save
save) =0;
43 virtual void get(
int i,
MemoryBuffer& bb,
size_t extra = 0) =0;
44 virtual void get(
int i,
void* x, detail::Load
load) =0;
45 virtual void destroy(
int i) =0;
58 FileStorage(
const std::string& filename_template =
"/tmp/DIY.XXXXXX"):
59 filename_templates_(1, filename_template),
60 count_(0), current_size_(0), max_size_(0) {}
62 FileStorage(
const std::vector<std::string>& filename_templates):
63 filename_templates_(filename_templates),
64 count_(0), current_size_(0), max_size_(0) {}
68 auto log = get_logger();
70 int fh = open_random(filename);
72 log->debug(
"FileStorage::put(): {}; buffer size: {}", filename, bb.size());
74 size_t sz = bb.buffer.size();
77 r_type written = _write(fh, &bb.buffer[0], static_cast<unsigned int>(sz));
79 using r_type = ssize_t;
80 r_type written = write(fh, &bb.buffer[0], sz);
82 if (written < static_cast<r_type>(sz) || written == r_type(-1))
83 log->warn(
"Could not write the full buffer to {}: written = {}; size = {}", filename, written, sz);
87 #if 0 // double-check the written file size: only for extreme debugging
88 FILE* fp = fopen(filename.c_str(),
"r");
89 fseek(fp, 0L, SEEK_END);
92 log->warn(
"file size doesn't match the buffer size, {} vs {}", fsz, sz);
96 return make_file_record(filename, sz);
99 virtual int put(
const void* x, detail::Save
save)
override
101 std::string filename;
102 int fh = open_random(filename);
104 detail::FileBuffer fb(_fdopen(fh,
"wb"));
106 detail::FileBuffer fb(fdopen(fh,
"w"));
109 size_t sz = fb.size();
113 return make_file_record(filename, sz);
116 virtual void get(
int i,
MemoryBuffer& bb,
size_t extra)
override
118 FileRecord fr = extract_file_record(i);
120 get_logger()->debug(
"FileStorage::get(): {}", fr.name);
122 bb.buffer.reserve(fr.size + extra);
123 bb.buffer.resize(fr.size);
126 _sopen_s(&fh, fr.name.c_str(), _O_RDONLY | _O_BINARY, _SH_DENYNO, _S_IREAD);
127 _read(fh, &bb.buffer[0], static_cast<unsigned int>(fr.size));
129 int fh = open(fr.name.c_str(), O_RDONLY | O_SYNC, 0600);
130 read(fh, &bb.buffer[0], fr.size);
132 io::utils::close(fh);
136 virtual void get(
int i,
void* x, detail::Load
load)
override
138 FileRecord fr = extract_file_record(i);
143 _sopen_s(&fh, fr.name.c_str(), _O_RDONLY | _O_BINARY, _SH_DENYNO, _S_IREAD);
144 detail::FileBuffer fb(_fdopen(fh,
"rb"));
146 int fh = open(fr.name.c_str(), O_RDONLY, 0600);
147 detail::FileBuffer fb(fdopen(fh,
"r"));
155 virtual void destroy(
int i)
override
163 io::utils::remove(fr.name);
164 (*current_size_.access()) -= fr.size;
167 int count()
const {
return (*count_.const_access()); }
168 size_t current_size()
const {
return (*current_size_.const_access()); }
169 size_t max_size()
const {
return (*max_size_.const_access()); }
173 for (FileRecordMap::const_iterator it = filenames_.const_access()->begin();
174 it != filenames_.const_access()->end();
177 io::utils::remove(it->second.name);
182 int open_random(std::string& filename)
const
184 if (filename_templates_.size() == 1)
185 filename = filename_templates_[0].c_str();
189 filename = filename_templates_[
static_cast<size_t>(std::rand()) % filename_templates_.size()].c_str();
191 int fh = diy::io::utils::mkstemp(filename);
195 int make_file_record(
const std::string& filename,
size_t sz)
197 int res = (*count_.access())++;
198 FileRecord fr = { sz, filename };
199 (*filenames_.access())[res] = fr;
211 FileRecord extract_file_record(
int i)
214 FileRecord fr = (*accessor)[i];
219 void remove_file(
const FileRecord& fr)
221 io::utils::remove(fr.name);
222 (*current_size_.access()) -= fr.size;
226 typedef std::map<int, FileRecord> FileRecordMap;
231 std::vector<std::string> filename_templates_;
void load(BinaryBuffer &bb, T &x)
Loads x from bb by calling diy::Serialization<T>::load(bb,x).
Definition: serialization.hpp:106
virtual void save_binary(const char *x, size_t count)=0
copy count bytes from x into the buffer
Definition: storage.hpp:38
void save(BinaryBuffer &bb, const T &x)
Saves x to bb by calling diy::Serialization<T>::save(bb,x).
Definition: serialization.hpp:102
Definition: critical-resource.hpp:15
Definition: serialization.hpp:26
virtual void load_binary(char *x, size_t count)=0
copy count bytes into x from the buffer
Definition: storage.hpp:48
virtual void load_binary_back(char *x, size_t count)=0
copy count bytes into x from the back of the buffer
Definition: critical-resource.hpp:32