Skip to content

Commit

Permalink
Handle file output through a FileWriter, align interfaces for FileWri…
Browse files Browse the repository at this point in the history
…ter and FileReader
  • Loading branch information
duizendnegen committed Dec 4, 2016
1 parent 24b01fa commit 6503aae
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 15 deletions.
89 changes: 80 additions & 9 deletions include/storage/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/seek.hpp>

#include <cerrno>
#include <cstring>
#include <tuple>
#include <type_traits>
Expand All @@ -23,7 +22,7 @@ namespace io
class FileReader
{
private:
const std::string filename;
const boost::filesystem::path filepath;
boost::filesystem::ifstream input_stream;

public:
Expand All @@ -47,16 +46,16 @@ class FileReader
{
}

FileReader(const boost::filesystem::path &filename_, const FingerprintFlag flag)
: filename(filename_.string())
FileReader(const boost::filesystem::path &filepath_, const FingerprintFlag flag)
: filepath(filepath_)
{
input_stream.open(filename_, std::ios::binary);
input_stream.open(filepath, std::ios::binary);
if (!input_stream)
throw util::exception("Error opening " + filename + ":" + std::strerror(errno));
throw util::exception("Error opening " + filepath.string());

if (flag == VerifyFingerprint && !ReadAndCheckFingerprint())
{
throw util::exception("Fingerprint mismatch in " + filename);
throw util::exception("Fingerprint mismatch in " + filepath.string());
}
}

Expand All @@ -77,10 +76,10 @@ class FileReader
{
if (result.eof())
{
throw util::exception("Error reading from " + filename +
throw util::exception("Error reading from " + filepath.string() +
": Unexpected end of file");
}
throw util::exception("Error reading from " + filename + ": " + std::strerror(errno));
throw util::exception("Error reading from " + filepath.string());
}
}

Expand Down Expand Up @@ -170,6 +169,78 @@ class FileReader
return thisline;
}
};

class FileWriter
{
private:
const boost::filesystem::path filepath;
boost::filesystem::ofstream output_stream;

public:
enum FingerprintFlag
{
GenerateFingerprint,
HasNoFingerprint
};

FileWriter(const std::string &filename, const FingerprintFlag flag)
: FileWriter(boost::filesystem::path(filename), flag)
{
}

FileWriter(const boost::filesystem::path &filepath_, const FingerprintFlag flag)
: filepath(filepath_)
{
output_stream.open(filepath, std::ios::binary);
if (!output_stream)
throw util::exception("Error opening " + filepath.string());

if (flag == GenerateFingerprint)
{
WriteFingerprint();
}
}

/* Write count objects of type T from pointer src to output stream */
template <typename T> bool WriteFrom(T *src, const std::size_t count)
{
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value,
"bytewise writing requires trivially copyable type");
#endif

if (count == 0)
return true;

const auto &result = output_stream.write(reinterpret_cast<char *>(src), count * sizeof(T));
if (!result)
{
throw util::exception("Error writing to " + filepath.string());
}

return static_cast<bool>(output_stream);
}

template <typename T> bool WriteFrom(T &target) { return WriteFrom(&target, 1); }

template <typename T> bool WriteOne(T tmp) { return WriteFrom(tmp); }

bool WriteElementCount32(const std::uint32_t count) { return WriteOne<std::uint32_t>(count); }
bool WriteElementCount64(const std::uint64_t count) { return WriteOne<std::uint64_t>(count); }

template <typename T> bool SerializeVector(std::vector<T> &data)
{
const auto count = data.size();
WriteElementCount64(count);
return WriteFrom(data.data(), count);
}

bool WriteFingerprint()
{
const auto fingerprint = util::FingerPrint::GetValid();
return WriteOne(fingerprint);
}
};
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions include/util/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ template <typename simple_type>
bool serializeVectorIntoAdjacencyArray(const std::string &filename,
const std::vector<std::vector<simple_type>> &data)
{
std::ofstream out_stream(filename, std::ios::binary);
storage::io::FileWriter file(filename, storage::io::FileWriter::HasNoFingerprint);

std::vector<std::uint32_t> offsets;
offsets.reserve(data.size() + 1);
std::uint64_t current_offset = 0;
Expand All @@ -64,18 +65,23 @@ bool serializeVectorIntoAdjacencyArray(const std::string &filename,
current_offset += vec.size();
offsets.push_back(boost::numeric_cast<std::uint32_t>(current_offset));
}
if (!serializeVector(out_stream, offsets))
return false;

std::vector<simple_type> all_data;
all_data.reserve(offsets.back());
for (auto const &vec : data)
all_data.insert(all_data.end(), vec.begin(), vec.end());

if (!serializeVector(out_stream, all_data))
if (!file.SerializeVector(offsets))
{
return false;
}

return static_cast<bool>(out_stream);
if (!file.SerializeVector(all_data))
{
return false;
}

return true;
}

template <typename simple_type, std::size_t WRITE_BLOCK_BUFFER_SIZE = 1024>
Expand Down
2 changes: 1 addition & 1 deletion unit_tests/util/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(io_nonexistent_file)
{
std::cout << e.what() << std::endl;
BOOST_REQUIRE(std::string(e.what()) ==
"Error opening non_existent_test_io.tmp:No such file or directory");
"Error opening non_existent_test_io.tmp");
}
}

Expand Down

0 comments on commit 6503aae

Please sign in to comment.