-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve I/O error handling #3321
Conversation
This only needs tests? These should be added here: |
I'll try and open a branch to create PRs against this PR, not sure if I'll manage to find time in the coming days though. (Edit: it looks like all the |
@danpat for review please!! |
Benchmark on my machine, extracting California: FileReader Branch
Master
Benchmark on @danpat's machine: FileReader Branch
Master
|
38d08ce
to
64151ee
Compare
@danpat review por favor? |
ooor, because Dan and I have been working on this pretty much the whole time together, anybody else want to review? :D @TheMarex mayhaps? |
|
||
BOOST_ASSERT(buffer.size() > 1); | ||
stream.read(&buffer[0], static_cast<std::streamsize>(buffer.size())); | ||
|
||
file_reader.ReadInto(&buffer[0], buffer.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of the pattern
string b;
b.resize(reader.Size())
reader.ReadInto(&b[0], b.size());
why not abstract over this to let the reader already return a type filled with the contents?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ticketing and will tackle in a different PR.
{ | ||
namespace storage | ||
{ | ||
namespace dedicated_io |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is dedicated io different to the storage::io namespace? and how is it related to util::io?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@daniel-j-h dedicated_io
could have a better name. It's basically the parts of FileReader that is reading a specialized type of input. For example, readHSGRHeader
which "Reads the checksum, number of nodes and number of edges written in the header file of a .hsgr
file and returns them in a HSGRHeader struct". This is not your typical filestream that simply opens up a file, verifies a fingerprint or not and returns the FileReader object.
This file has readHSGRHeader
, readPropertiesCount
, readDatasourceIndexes
, readEdges
, readNodes
, readDatasourceNames
and the assoicated structs.
It strikes me that these are all related to reading graphs and graph components. So perhaps I can rename this header to graph_io
or something similar?
{ | ||
util::SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n" | ||
"Reprocess to get rid of this warning."; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was under the impression the FileReader is now doing all the checks and we don't have to do this ourselves?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that the FileReader doesn't do this specific fingerprint test: if (!fingerprint_loaded.TestGraphUtil(fingerprint_valid))
so we have to do it here.
input_file.ReadInto(header.number_of_edges); | ||
|
||
BOOST_ASSERT_MSG(0 != header.number_of_nodes, "number of nodes is zero"); | ||
// number of edges can be zero, this is the case in a few test fixtures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about checking: if (num edges > 0) assert num nodes > 0; ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@daniel-j-h I changed this to what you suggested above, but I'm missing context. Would you please explain? I'd like to know why BOOST_ASSERT_MSG(0 != header.number_of_nodes, "number of nodes is zero");
made sense at all.
BOOST_ASSERT(node_buffer); | ||
BOOST_ASSERT(edge_buffer); | ||
input_file.ReadInto(node_buffer, number_of_nodes); | ||
input_file.ReadInto(edge_buffer, number_of_edges); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume the reader handles a count of zero?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup! By returning:
osrm-backend/include/storage/io.hpp
Line 66 in 73e365d
if (count == 0) |
if (!turn_penalty_file) | ||
throw util::exception{"Unable to open turn penalty file " + filename}; | ||
|
||
storage::io::FileReader turn_penalty_file_reader(std::string(filename), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well this is weird. Earlier, both this and the segment_speed_filenames[idx] were failing to compile because filename was a char* and not a string. And therefore would not compile without being cast as a string. Now it seems to be compiling just fine. So I'll remove it.
TurnPenaltySourceFlatMap local; | ||
|
||
std::uint64_t from_node_id{}; | ||
std::uint64_t via_node_id{}; | ||
std::uint64_t to_node_id{}; | ||
double penalty{}; | ||
|
||
for (std::string line; std::getline(turn_penalty_file, line);) | ||
{ | ||
std::for_each(turn_penalty_file_reader.GetLineIteratorBegin(), turn_penalty_file_reader.GetLineIteratorEnd(), [&](const std::string &line) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -28,4 +30,77 @@ BOOST_AUTO_TEST_CASE(io_data) | |||
BOOST_CHECK_EQUAL_COLLECTIONS(data_out.begin(), data_out.end(), data_in.begin(), data_in.end()); | |||
} | |||
|
|||
BOOST_AUTO_TEST_CASE(io_nonexistent_file) | |||
{ | |||
static std::string IO_NONEXISTENT_FILE = "non_existent_test_io.tmp"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} catch (const osrm::util::exception &e) { | ||
std::cout << e.what() << std::endl; | ||
BOOST_REQUIRE(std::string(e.what()) == "Error opening non_existent_test_io.tmp:No such file or directory"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is a macro CHECK_THROWS of something like that for this exact use-case
data_in.resize(153); | ||
|
||
for (std::size_t i = 0; i < data_in.size(); ++i) | ||
data_in[i] = i; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check out std::iota
vector<int> v(n);
iota(begin(v), end(v));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool! done!
4f4c6b3
to
025cbb6
Compare
3cf65f8
to
b63f8b6
Compare
Issue
This PR is to address #3047. It adds some basic wrappers around our file I/O which include consistent error handling and useful exception messages on error.
No file formats are changed.
Tasklist