1 #ifndef DIY_STORAGE_HPP
2 #define DIY_STORAGE_HPP
13 #include "serialization.hpp"
21 typedef void (*Save)(
const void*, BinaryBuffer& buf);
22 typedef void (*Load)(
void*, BinaryBuffer& buf);
24 struct FileBuffer:
public BinaryBuffer
26 FileBuffer(FILE* file_): file(file_), head(0), tail(0) {}
29 virtual inline void save_binary(
const char* x,
size_t count)
override { fwrite(x, 1, count, file); head += count; }
30 virtual inline void load_binary(
char* x,
size_t count)
override { fread(x, 1, count, file); }
31 virtual inline void load_binary_back(
char* x,
size_t count)
override { fseek(file, tail, SEEK_END); fread(x, 1, count, file); tail += count; fseek(file, head, SEEK_SET); }
33 size_t size()
const {
return head; }
45 virtual int put(
const void* x, detail::Save
save) =0;
46 virtual void get(
int i,
MemoryBuffer& bb,
size_t extra = 0) =0;
47 virtual void get(
int i,
void* x, detail::Load
load) =0;
48 virtual void destroy(
int i) =0;
61 FileStorage(
const std::string& filename_template =
"/tmp/DIY.XXXXXX"):
62 filename_templates_(1, filename_template),
63 count_(0), current_size_(0), max_size_(0) {}
65 FileStorage(
const std::vector<std::string>& filename_templates):
66 filename_templates_(filename_templates),
67 count_(0), current_size_(0), max_size_(0) {}
71 auto log = get_logger();
73 int fh = open_random(filename);
75 log->debug(
"FileStorage::put(): {}; buffer size: {}", filename, bb.size());
77 size_t sz = bb.buffer.size();
78 size_t written = write(fh, &bb.buffer[0], sz);
79 if (written < sz || written == (
size_t)-1)
80 log->warn(
"Could not write the full buffer to {}: written = {}; size = {}", filename, written, sz);
85 #if 0 // double-check the written file size: only for extreme debugging
86 FILE* fp = fopen(filename.c_str(),
"r");
87 fseek(fp, 0L, SEEK_END);
90 log->warn(
"file size doesn't match the buffer size, {} vs {}", fsz, sz);
94 return make_file_record(filename, sz);
97 virtual int put(
const void* x, detail::Save
save)
override
100 int fh = open_random(filename);
102 detail::FileBuffer fb(fdopen(fh,
"w"));
104 size_t sz = fb.size();
108 return make_file_record(filename, sz);
111 virtual void get(
int i,
MemoryBuffer& bb,
size_t extra)
override
113 FileRecord fr = extract_file_record(i);
115 get_logger()->debug(
"FileStorage::get(): {}", fr.name);
117 bb.buffer.reserve(fr.size + extra);
118 bb.buffer.resize(fr.size);
119 int fh = open(fr.name.c_str(), O_RDONLY | O_SYNC, 0600);
120 read(fh, &bb.buffer[0], fr.size);
126 virtual void get(
int i,
void* x, detail::Load
load)
override
128 FileRecord fr = extract_file_record(i);
131 int fh = open(fr.name.c_str(), O_RDONLY, 0600);
132 detail::FileBuffer fb(fdopen(fh,
"r"));
139 virtual void destroy(
int i)
override
147 remove(fr.name.c_str());
148 (*current_size_.access()) -= fr.size;
151 int count()
const {
return (*count_.const_access()); }
152 size_t current_size()
const {
return (*current_size_.const_access()); }
153 size_t max_size()
const {
return (*max_size_.const_access()); }
157 for (FileRecordMap::const_iterator it = filenames_.const_access()->begin();
158 it != filenames_.const_access()->end();
161 remove(it->second.name.c_str());
166 int open_random(std::string& filename)
const
168 if (filename_templates_.size() == 1)
169 filename = filename_templates_[0].c_str();
173 filename = filename_templates_[std::rand() % filename_templates_.size()].c_str();
177 int fh = mkstemp(const_cast<char*>(filename.c_str()));
179 int fh = mkostemp(const_cast<char*>(filename.c_str()), O_WRONLY | O_SYNC);
185 int make_file_record(
const std::string& filename,
size_t sz)
187 int res = (*count_.access())++;
188 FileRecord fr = { sz, filename };
189 (*filenames_.access())[res] = fr;
201 FileRecord extract_file_record(
int i)
204 FileRecord fr = (*accessor)[i];
209 void remove_file(
const FileRecord& fr)
211 remove(fr.name.c_str());
212 (*current_size_.access()) -= fr.size;
216 typedef std::map<int, FileRecord> FileRecordMap;
221 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:41
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:51
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