Files
MP-SPDZ/Tools/Buffer.cpp

136 lines
3.1 KiB
C++

/*
* Buffer.cpp
*
*/
#include "Tools/Buffer.h"
#include "Processor/BaseMachine.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
bool BufferBase::rewind = false;
void BufferBase::setup(ifstream* f, int length, const string& filename,
const char* type, const string& field)
{
file = f;
tuple_length = length;
data_type = type;
field_type = field;
this->filename = filename;
}
bool BufferBase::is_pipe()
{
struct stat buf;
if (stat(filename.c_str(), &buf))
return S_ISFIFO(buf.st_mode);
else
return false;
}
void BufferBase::seekg(int pos)
{
assert(not is_pipe());
#ifdef DEBUG_BUFFER
if (pos != 0)
printf("seek %d %s thread %d\n", pos, filename.c_str(),
BaseMachine::thread_num);
#endif
if (not file)
{
if (pos == 0)
return;
else
file = open();
}
file->seekg(header_length + pos * tuple_length);
if (file->eof() || file->fail())
{
// let it go in case we don't need it anyway
if (pos != 0)
try_rewind();
}
#ifdef DEBUG_BUFFER
printf("seek %d %d thread %d\n", pos, int(file->tellg()),
BaseMachine::thread_num);
#endif
next = BUFFER_SIZE;
}
void BufferBase::try_rewind()
{
assert(not is_pipe());
#ifndef INSECURE
string type;
if (field_type.size() and data_type.size())
type = (string)" of " + field_type + " " + data_type;
throw not_enough_to_buffer(type, filename);
#endif
file->clear(); // unset EOF flag
file->seekg(header_length);
if (file->peek() == ifstream::traits_type::eof())
throw runtime_error("empty file: " + filename);
if (!rewind)
cerr << "REWINDING - ONLY FOR BENCHMARKING" << endl;
rewind = true;
eof = true;
}
void BufferBase::prune()
{
if (is_pipe())
return;
if (file and (not file->good() or file->peek() == EOF))
purge();
else if (file and file->tellg() != header_length)
{
#ifdef VERBOSE
cerr << "Pruning " << filename << endl;
#endif
string tmp_name = filename + ".new";
ofstream tmp(tmp_name.c_str());
size_t start = file->tellg();
char buf[header_length];
file->seekg(0);
file->read(buf, header_length);
tmp.write(buf, header_length);
file->seekg(start);
tmp << file->rdbuf();
if (tmp.fail())
throw runtime_error(
"problem writing to " + tmp_name + " from "
+ to_string(start) + " of " + filename);
tmp.close();
file->close();
rename(tmp_name.c_str(), filename.c_str());
file->open(filename.c_str(), ios::in | ios::binary);
}
}
void BufferBase::purge()
{
if (file and not is_pipe())
{
#ifdef VERBOSE
cerr << "Removing " << filename << endl;
#endif
unlink(filename.c_str());
file->close();
file = 0;
}
}
void BufferBase::check_tuple_length(int tuple_length)
{
if (tuple_length != this->tuple_length)
throw Processor_Error("inconsistent tuple length");
}