1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
#ifndef REORDERED_FILE_BUFFER_H
#define REORDERED_FILE_BUFFER_H
#include <fstream>
#include <vector>
#include <set>
#include "../util/logger.h"
class ReorderedFileBuffer {
public:
ReorderedFileBuffer(std::ofstream* stream, size_t maxSize)
: _nextWritePos(0),
_unflushedSize(0),
_maxSize(maxSize),
_stream(stream) {}
~ReorderedFileBuffer() { flush(); }
void seekp(size_t offset) { _nextWritePos = offset; }
void write(const char* data, size_t length) {
_buffer.insert(BufferEntry(_nextWritePos, data, length));
_nextWritePos += length;
_unflushedSize += length + sizeof(_nextWritePos) * 2;
if (_unflushedSize > _maxSize) flush();
}
void flush() {
Logger::Debug << "Flushing reordered file buffer...\n";
for (std::set<BufferEntry>::const_iterator i = _buffer.begin();
i != _buffer.end(); ++i) {
_stream->seekp(i->position, std::ios_base::beg);
_stream->write(i->data.data(), i->data.size());
if (_stream->fail())
throw std::runtime_error(
"Error: failed to write to reordered file! Check access rights and "
"free disk space.");
}
_buffer.clear();
_unflushedSize = 0;
}
std::ofstream& stream() { return *_stream; }
private:
struct BufferEntry {
BufferEntry(size_t pos_, const char* data_, size_t length_)
: position(pos_), data(data_, data_ + length_) {}
bool operator<(const BufferEntry& other) const {
return position < other.position;
}
size_t position;
std::vector<char> data;
};
std::set<BufferEntry> _buffer;
size_t _nextWritePos;
size_t _unflushedSize;
size_t _maxSize;
std::ofstream* _stream;
};
#endif
|